练习 - 将多个环境添加到工作流

已完成

现在可以更新工作流,以部署到测试和生产环境。 在本单元中,你将更新工作流以使用被调用的工作流,以便可以跨环境重复使用这些作业。

在此过程中,你将:

  • 为 lint 作业添加可重用工作流。
  • 添加一个可重用工作流,用于定义部署到任何环境所需的作业。
  • 更新工作流以使用调用的工作流。
  • 运行工作流并查看结果。

为 lint 作业添加可重用工作流

无论工作流部署到多少个环境,lint 作业在工作流运行期间只发生一次。 因此,实际上不需要对 lint 作业使用被调用的工作流。 但是,若要使主工作流定义文件简单且易读,你决定在单独的工作流文件中定义 lint 作业。

  1. 在 Visual Studio Code 中,在 .github/workflows 文件夹中创建一个名为 lint.yml 的新文件。

    Visual Studio Code 资源管理器的屏幕截图,包含 .github 和 workflows 文件夹以及 lint dot YML 文件。

  2. 将以下工作流定义粘贴到文件中:

    name: lint
    
    on:
      workflow_call:
    
    jobs:
      lint:
        name: Lint code
        runs-on: ubuntu-latest
        steps:
        - uses: actions/checkout@v3
    
        - name: Lint code
          run: |
            az bicep build --file deploy/main.bicep
    

    lint 作业与工作流中已有的 lint 作业相同,但现在它位于单独的工作流文件中。

  3. 保存更改并关闭该文件。

为部署添加可重用工作流

创建一个可重用工作流,用于定义部署每个环境所需的所有作业。 你将使用输入和机密来指定环境之间可能不同的设置。

  1. 在 .github/workflows 文件夹中创建一个名为 deploy.yml 的新文件。

    Visual Studio Code 资源管理器的屏幕截图,包含 .github 和 workflows 文件夹以及 deploy dot YML 文件。

    此文件代表针对每个环境运行的所有部署活动。

  2. 将以下工作流名称、触发器、输入和机密粘贴到文件中:

    name: deploy
    
    on:
      workflow_call:
        inputs:
          environmentType:
            required: true
            type: string
          resourceGroupName:
            required: true
            type: string
        secrets:
          AZURE_CLIENT_ID:
            required: true
          AZURE_TENANT_ID:
            required: true
          AZURE_SUBSCRIPTION_ID:
            required: true
    

    注意

    当你开始在 Visual Studio Code 中使用 YAML 文件时,可能会看到一些红色波浪线,指示存在问题。 这是因为 YAML 文件的 Visual Studio Code 扩展有时会错误地猜测文件的架构。

    可以忽略扩展报告的问题。 或者,如果你愿意,可以将以下代码添加到文件顶部以禁用扩展的猜测:

    # yaml-language-server: $schema=./deploy.yml
    
  3. 在机密下方,粘贴验证作业的定义:

    jobs:
      validate:
         runs-on: ubuntu-latest
         steps:
         - uses: actions/checkout@v3
         - uses: azure/login@v1
           name: Sign in to Azure
           with:
            client-id: ${{ secrets.AZURE_CLIENT_ID }}
            tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
         - if: inputs.environmentType != 'Production'
           uses: azure/arm-deploy@v1
           name: Run preflight validation
           with:
             deploymentName: ${{ github.run_number }}
             resourceGroupName: ${{ inputs.resourceGroupName }}
             template: ./deploy/main.bicep
             parameters: >
               environmentType=${{ inputs.environmentType }}
             deploymentMode: Validate
         - if: inputs.environmentType == 'Production'
           uses: azure/arm-deploy@v1
           name: Run what-if
           with:
             failOnStdErr: false
             resourceGroupName: ${{ inputs.resourceGroupName }}
             template: ./deploy/main.bicep
             parameters: >
               environmentType=${{ inputs.environmentType }}
             additionalArguments: --what-if
    

    请注意,这些作业应用了一个条件。 预检验证仅适用于非生产环境。 what-if 操作仅适用于生产环境。 在学习路径的上一个模块中,你为这些操作使用了单独的作业,但在这里将它们合并以简化工作流。

    提示

    YAML 文件对缩进敏感。 无论是键入还是粘贴此代码,都请确保缩进正确。 在此练习的后续部分,你将看到完整的 YAML 工作流定义,使你可验证文件是否匹配。

  4. 在验证作业下方,粘贴部署作业的定义:

    deploy:
      needs: validate
      environment: ${{ inputs.environmentType }}
      runs-on: ubuntu-latest
      outputs:
        appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }}
      steps:
      - uses: actions/checkout@v3
      - uses: azure/login@v1
        name: Sign in to Azure
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      - uses: azure/arm-deploy@v1
        id: deploy
        name: Deploy Bicep file
        with:
          failOnStdErr: false
          deploymentName: ${{ github.run_number }}
          resourceGroupName: ${{ inputs.resourceGroupName }}
          template: ./deploy/main.bicep
          parameters: >
            environmentType=${{ inputs.environmentType }}
    
  5. 在部署作业下方,粘贴冒烟测试作业的定义:

    smoke-test:
      runs-on: ubuntu-latest
      needs: deploy
      steps:
      - uses: actions/checkout@v3
      - run: |
          $container = New-PesterContainer `
            -Path 'deploy/Website.Tests.ps1' `
            -Data @{ HostName = '${{needs.deploy.outputs.appServiceAppHostName}}' }
          Invoke-Pester `
            -Container $container `
            -CI
        name: Run smoke tests
        shell: pwsh
    
  6. 验证 deploy.yml 文件是否如以下示例所示:

    name: deploy
    
    on:
      workflow_call:
        inputs:
          environmentType:
            required: true
            type: string
          resourceGroupName:
            required: true
            type: string
        secrets:
          AZURE_CLIENT_ID:
            required: true
          AZURE_TENANT_ID:
            required: true
          AZURE_SUBSCRIPTION_ID:
            required: true
    
    jobs:
      validate:
         runs-on: ubuntu-latest
         steps:
         - uses: actions/checkout@v3
         - uses: azure/login@v1
           name: Sign in to Azure
           with:
            client-id: ${{ secrets.AZURE_CLIENT_ID }}
            tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
         - if: inputs.environmentType != 'Production'
           uses: azure/arm-deploy@v1
           name: Run preflight validation
           with:
             deploymentName: ${{ github.run_number }}
             resourceGroupName: ${{ inputs.resourceGroupName }}
             template: ./deploy/main.bicep
             parameters: >
               environmentType=${{ inputs.environmentType }}
             deploymentMode: Validate
         - if: inputs.environmentType == 'Production'
           uses: azure/arm-deploy@v1
           name: Run what-if
           with:
             failOnStdErr: false
             resourceGroupName: ${{ inputs.resourceGroupName }}
             template: ./deploy/main.bicep
             parameters: >
               environmentType=${{ inputs.environmentType }}
             additionalArguments: --what-if
    
      deploy:
        needs: validate
        environment: ${{ inputs.environmentType }}
        runs-on: ubuntu-latest
        outputs:
          appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }}
        steps:
        - uses: actions/checkout@v3
        - uses: azure/login@v1
          name: Sign in to Azure
          with:
            client-id: ${{ secrets.AZURE_CLIENT_ID }}
            tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
        - uses: azure/arm-deploy@v1
          id: deploy
          name: Deploy Bicep file
          with:
            failOnStdErr: false
            deploymentName: ${{ github.run_number }}
            resourceGroupName: ${{ inputs.resourceGroupName }}
            template: ./deploy/main.bicep
            parameters: >
              environmentType=${{ inputs.environmentType }}
    
      smoke-test:
        runs-on: ubuntu-latest
        needs: deploy
        steps:
        - uses: actions/checkout@v3
        - run: |
            $container = New-PesterContainer `
              -Path 'deploy/Website.Tests.ps1' `
              -Data @{ HostName = '${{needs.deploy.outputs.appServiceAppHostName}}' }
            Invoke-Pester `
              -Container $container `
              -CI
          name: Run smoke tests
          shell: pwsh
    
  7. 保存对该文件所做的更改。

更新工作流定义以使用模板

  1. 打开“.github/workflows”文件夹中的“workflow.yml”文件。

  2. 删除 env: 部分的内容,包括两个环境变量。 你很快就会将它们替换为特定于环境的变量。

  3. 删除 lint: 作业定义的内容并将其替换为以下代码,以使用前面创建的 lint.yml 文件:

    # Lint the Bicep file.
    lint:
      uses: ./.github/workflows/lint.yml
    
  4. 删除已更新的 lint 作业下面的文件中的所有内容。

  5. 在文件底部,添加以下代码以部署到测试环境:

    # Deploy to the test environment.
    deploy-test:
      uses: ./.github/workflows/deploy.yml
      needs: lint
      with:
        environmentType: Test
        resourceGroupName: ToyWebsiteTest
      secrets:
        AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_TEST }}
        AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
        AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    
  6. 在刚添加的代码下面,添加以下代码以部署到生产环境:

    # Deploy to the production environment.
    deploy-production:
      uses: ./.github/workflows/deploy.yml
      needs: deploy-test
      with:
        environmentType: Production
        resourceGroupName: ToyWebsiteProduction
      secrets:
        AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_PRODUCTION }}
        AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
        AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    

    更新后的工作流运行 lint 作业一次。 然后它使用 deploy.yml 被调用的工作流两次:每个环境一次。 这使得工作流定义清晰易懂。 YAML 文件中的注释标识了每个作业的目标环境。

  7. 验证 workflow.yml 文件是否如以下示例所示:

    name: deploy-toy-website-environments
    concurrency: toy-company
    
    on:
      push:
        branches:
          - main
      workflow_dispatch:
    
    permissions:
      id-token: write
      contents: read
    
    jobs:
    
      # Lint the Bicep file.
      lint:
        uses: ./.github/workflows/lint.yml
    
      # Deploy to the test environment.
      deploy-test:
        uses: ./.github/workflows/deploy.yml
        needs: lint
        with:
          environmentType: Test
          resourceGroupName: ToyWebsiteTest
        secrets:
          AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_TEST }}
          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
          AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    
      # Deploy to the production environment.
      deploy-production:
        uses: ./.github/workflows/deploy.yml
        needs: deploy-test
        with:
          environmentType: Production
          resourceGroupName: ToyWebsiteProduction
        secrets:
          AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_PRODUCTION }}
          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
          AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    
  8. 保存更改。

  9. 通过在 Visual Studio Code 终端中运行以下命令来提交更改并将其推送到 Git 存储库:

    git add .
    git commit -m "Add reusable workflows"
    git push
    
  10. 由于这是你首次推送到存储库,系统可能会提示你登录。

    在Windows 上,键入 1 以使用 Web 浏览器进行身份验证,然后选择 Enter

    在 macOS 上,选择“授权”。

  11. 将会出现一个浏览器窗口。 你可能需要再次登录到 GitHub。 选择“授权”。

查看工作流运行

  1. 在浏览器中,转到“Actions”。

    工作流的第一次运行(标记为“初始提交”)显示为失败。 创建存储库时,GitHub 会自动运行工作流。 由于机密当时未准备就绪,所以失败了。 你可以忽略此次失败。

  2. 选择 deploy-toy-website-environments 工作流。

  3. 选择工作流的最新运行。

    请注意,工作流运行现在显示了你在 YAML 文件中定义的所有作业。

    “注释”面板中列出了一些警告。 所有这些警告均因 Bicep 将信息性消息写入工作流日志的方式而起。 你可以忽略这些警告。

  4. 在“deploy-production / deploy”作业之前,等待作业暂停。 工作流可能需要几分钟时间才能达到这一点。

    GitHub 的屏幕截图,显示工作流运行暂停供审批。

  5. 通过选择“审核部署”按钮批准部署到生产环境。

  6. 选择“生产”环境,然后选择“批准和部署”按钮。

    GitHub 界面的屏幕截图,其中显示了“工作流审批”页面和“批准和部署”按钮。

    等待工作流完成运行。 工作流成功完成。

  7. 选择“代码”。

  8. 选择“生产”部署。

    GitHub 的屏幕截图,显示代码页环境,其中突出显示了生产环境。

  9. 请注意,在部署屏幕上,你会看到生产环境部署历史记录的概述。

    GitHub 的屏幕截图,其中显示了生产环境,包含显示单个部署的部署历史记录。

  10. 选择提交标识符。

    请注意,GitHub 显示了部署中包含的提交列表。 这有助于查看一段时间内环境中的更改。

    GitHub 的屏幕截图,其中显示了生产环境的部署详细信息,包含提交列表。

  11. 在浏览器中转到 Azure 门户

  12. 请转到 ToyWebsiteProduction 资源组。

  13. 在资源列表中,打开 Azure 应用服务应用。

    Azure 门户的屏幕截图,其中显示了应用程序服务玩具网站生产应用和应用服务计划 SKU 详细信息。

    请注意,应用服务计划的类型为 S1。

  14. 转到 ToyWebsiteTest 资源组中的应用服务应用。

    请注意,应用服务计划的类型为 F1。 正如你在 Bicep 文件中定义的那样,这两种环境使用不同的设置。