练习 - 将多个环境添加到管道
现在可以更新管道,以部署到测试和生产环境。 在本单元中,你将更新管道以使用模板,以便可以跨环境重用阶段。
在此过程中,你将:
- 为 Lint 分析阶段添加管道模板。
- 添加一个管道模板,用于定义部署到任何环境所需的阶段。
- 更新管道以使用模板。
- 运行管道并查看结果。
为 Lint 分析阶段添加管道模板
无论管道部署到多少个环境,Lint 分析阶段在管道运行期间只发生一次。 因此,实际上不需要为 Lint 分析阶段使用模板。 但是为了保持主管道定义文件简单易读,你决定在模板中定义 Lint 分析阶段。
在 Visual Studio Code 中,在 deploy 文件夹中创建一个名为 pipeline-templates 的新文件夹。
在 pipeline-templates 文件夹中创建一个名为 lint.yml 的新文件。
将以下管道模板定义粘贴到文件中:
jobs: - job: LintCode displayName: Lint code steps: - script: | az bicep build --file deploy/main.bicep name: LintBicepCode displayName: Run Bicep linter
Lint 分析阶段与管道中已有的 Lint 分析阶段相同,但现在它位于单独的管道模板文件中。
保存更改并关闭该文件。
添加用于部署的管道模板
创建一个管道模板,用于定义部署每个环境所需的所有阶段。 你需要使用模板参数来指定环境之间可能不同的设置。
在 pipeline-templates 文件夹中创建一个名为 deploy.yml 的新文件。
此文件代表针对每个环境运行的所有部署活动。
将以下管道模板参数粘贴到文件中:
parameters: - name: environmentType type: string - name: resourceGroupName type: string - name: serviceConnectionName type: string - name: deploymentDefaultLocation type: string default: westus3
注意
当你开始在 Visual Studio Code 中使用 YAML 文件时,可能会看到一些红色波浪线,指示存在问题。 这是因为 YAML 文件的 Visual Studio Code 扩展有时会错误地猜测文件的架构。
可以忽略扩展报告的问题。 或者,如果你愿意,可以将以下代码添加到文件顶部以禁用扩展的猜测:
# yaml-language-server: $schema=./deploy.yml
在参数下方,粘贴验证阶段的定义:
stages: - ${{ if ne(parameters.environmentType, 'Production') }}: - stage: Validate_${{parameters.environmentType}} displayName: Validate (${{parameters.environmentType}} Environment) jobs: - job: ValidateBicepCode displayName: Validate Bicep code steps: - task: AzureResourceManagerTemplateDeployment@3 name: RunPreflightValidation displayName: Run preflight validation inputs: connectedServiceName: ${{parameters.serviceConnectionName}} ___location: ${{parameters.deploymentDefaultLocation}} deploymentMode: Validation resourceGroupName: ${{parameters.resourceGroupName}} csmFile: deploy/main.bicep overrideParameters: > -environmentType ${{parameters.environmentType}}
请注意,这个阶段应用了一个条件。 它仅针对非生产环境运行。
另请注意,阶段标识符包括
environmentType
参数的值。 此参数可确保管道中的每个阶段都具有唯一标识符。 该阶段还有一个displayName
属性,用于创建格式正确的名称供你阅读。在验证阶段下方,粘贴预览阶段的定义:
- ${{ if eq(parameters.environmentType, 'Production') }}: - stage: Preview_${{parameters.environmentType}} displayName: Preview (${{parameters.environmentType}} Environment) jobs: - job: PreviewAzureChanges displayName: Preview Azure changes steps: - task: AzureCLI@2 name: RunWhatIf displayName: Run what-if inputs: azureSubscription: ${{parameters.serviceConnectionName}} scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | az deployment group what-if \ --resource-group ${{parameters.resourceGroupName}} \ --template-file deploy/main.bicep \ --parameters environmentType=${{parameters.environmentType}}
请注意,这个阶段也应用了一个条件,但它与验证阶段的条件相反。 预览阶段仅针对生产环境运行。
在预览阶段下方,粘贴部署阶段的定义:
- stage: Deploy_${{parameters.environmentType}} displayName: Deploy (${{parameters.environmentType}} Environment) jobs: - deployment: DeployWebsite displayName: Deploy website environment: ${{parameters.environmentType}} strategy: runOnce: deploy: steps: - checkout: self - task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: ${{parameters.serviceConnectionName}} deploymentName: $(Build.BuildNumber) ___location: ${{parameters.deploymentDefaultLocation}} resourceGroupName: ${{parameters.resourceGroupName}} csmFile: deploy/main.bicep overrideParameters: > -environmentType ${{parameters.environmentType}} deploymentOutputs: deploymentOutputs - bash: | echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs)
在部署阶段下方,粘贴版本验收测试阶段的定义:
- stage: SmokeTest_${{parameters.environmentType}} displayName: Smoke Test (${{parameters.environmentType}} Environment) jobs: - job: SmokeTest displayName: Smoke test variables: appServiceAppHostName: $[ stageDependencies.Deploy_${{parameters.environmentType}}.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ] steps: - task: PowerShell@2 name: RunSmokeTests displayName: Run smoke tests inputs: targetType: inline script: | $container = New-PesterContainer ` -Path 'deploy/Website.Tests.ps1' ` -Data @{ HostName = '$(appServiceAppHostName)' } Invoke-Pester ` -Container $container ` -CI - task: PublishTestResults@2 name: PublishTestResults displayName: Publish test results condition: always() inputs: testResultsFormat: NUnit testResultsFiles: 'testResults.xml'
请注意,
appServiceAppHostName
变量定义在引用发布主机名的阶段时合并了environmentType
参数。 此参数可确保每个版本验收测试阶段都针对正确的环境运行。验证 deploy.yml 文件是否如以下示例所示:
parameters: - name: environmentType type: string - name: resourceGroupName type: string - name: serviceConnectionName type: string - name: deploymentDefaultLocation type: string default: westus3 stages: - ${{ if ne(parameters.environmentType, 'Production') }}: - stage: Validate_${{parameters.environmentType}} displayName: Validate (${{parameters.environmentType}} Environment) jobs: - job: ValidateBicepCode displayName: Validate Bicep code steps: - task: AzureResourceManagerTemplateDeployment@3 name: RunPreflightValidation displayName: Run preflight validation inputs: connectedServiceName: ${{parameters.serviceConnectionName}} ___location: ${{parameters.deploymentDefaultLocation}} deploymentMode: Validation resourceGroupName: ${{parameters.resourceGroupName}} csmFile: deploy/main.bicep overrideParameters: > -environmentType ${{parameters.environmentType}} - ${{ if eq(parameters.environmentType, 'Production') }}: - stage: Preview_${{parameters.environmentType}} displayName: Preview (${{parameters.environmentType}} Environment) jobs: - job: PreviewAzureChanges displayName: Preview Azure changes steps: - task: AzureCLI@2 name: RunWhatIf displayName: Run what-if inputs: azureSubscription: ${{parameters.serviceConnectionName}} scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | az deployment group what-if \ --resource-group ${{parameters.resourceGroupName}} \ --template-file deploy/main.bicep \ --parameters environmentType=${{parameters.environmentType}} - stage: Deploy_${{parameters.environmentType}} displayName: Deploy (${{parameters.environmentType}} Environment) jobs: - deployment: DeployWebsite displayName: Deploy website environment: ${{parameters.environmentType}} strategy: runOnce: deploy: steps: - checkout: self - task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: ${{parameters.serviceConnectionName}} deploymentName: $(Build.BuildNumber) ___location: ${{parameters.deploymentDefaultLocation}} resourceGroupName: ${{parameters.resourceGroupName}} csmFile: deploy/main.bicep overrideParameters: > -environmentType ${{parameters.environmentType}} deploymentOutputs: deploymentOutputs - bash: | echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs) - stage: SmokeTest_${{parameters.environmentType}} displayName: Smoke Test (${{parameters.environmentType}} Environment) jobs: - job: SmokeTest displayName: Smoke test variables: appServiceAppHostName: $[ stageDependencies.Deploy_${{parameters.environmentType}}.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ] steps: - task: PowerShell@2 name: RunSmokeTests displayName: Run smoke tests inputs: targetType: inline script: | $container = New-PesterContainer ` -Path 'deploy/Website.Tests.ps1' ` -Data @{ HostName = '$(appServiceAppHostName)' } Invoke-Pester ` -Container $container ` -CI - task: PublishTestResults@2 name: PublishTestResults displayName: Publish test results condition: always() inputs: testResultsFormat: NUnit testResultsFiles: 'testResults.xml'
保存对该文件所做的更改。
更新管道定义以使用模板
打开“azure pipelines.yml”文件。
通过使用以下代码替换内容来更新文件以使用新模板:
trigger: batch: true branches: include: - main pool: vmImage: ubuntu-latest stages: # Lint the Bicep file. - stage: Lint jobs: - template: pipeline-templates/lint.yml # Deploy to the test environment. - template: pipeline-templates/deploy.yml parameters: environmentType: Test resourceGroupName: ToyWebsiteTest serviceConnectionName: ToyWebsiteTest # Deploy to the production environment. - template: pipeline-templates/deploy.yml parameters: environmentType: Production resourceGroupName: ToyWebsiteProduction serviceConnectionName: ToyWebsiteProduction
该管道运行一次 Lint 分析阶段。 然后它使用 deploy.yml 模板文件两次:每个环境一次。 这使得管道定义清晰易懂。 此外,注释还有助于解释发生的情况。
保存所做更改。
通过在 Visual Studio Code 终端中运行以下命令来提交更改并将其推送到 Git 存储库:
git add . git commit -m "Add pipeline templates" git push
查看管道运行
在浏览器中,转到“管道”。
选择管道的最新运行。
请注意,管道运行现在显示了你在 YAML 文件中定义的所有阶段。 可能需要水平滚动才能看到所有这些内容。
在部署(生产环境)阶段之前等待管道暂停。 管道可能需要几分钟时间才能达到这一点。
通过选择“审核”按钮批准部署到生产环境。
选择“批准”按钮。
等待管道完成运行。
选择“测试”选项卡以显示此管道运行的测试结果。
请注意,现在有四个测试结果。 版本验收测试会在测试和生产这两个环境中运行,因此你可以看到两组测试的结果。
选择“管道”“环境”。
选择生产环境。
请注意,在环境详细信息屏幕上,你会看到生产环境部署历史记录的概述。
选择该部署,然后选择“更改”选项卡。
请注意,“更改”选项卡显示了部署中包含的提交列表。 此信息可帮助你准确了解环境中一段时间的变化。
在浏览器中,转到 Azure 门户。
请转到 ToyWebsiteProduction 资源组。
在资源列表中,打开 Azure 应用服务应用。
请注意,应用服务计划的类型为 S1。
转到 ToyWebsiteTest 资源组中的应用服务应用。
请注意,应用服务计划的类型为 F1。 正如你在 Bicep 文件中定义的那样,这两种环境使用不同的设置。