生成具有阶段的 YAML 管道

Azure DevOps Services |Azure DevOps Server 2022 - Azure DevOps Server 2019

通过多个阶段,可以隔离管道的不同部分,提高质量控制和安全性,更好地了解管道的进度,并降低风险。

本文介绍如何创建和运行具有多个阶段和条件的更复杂的 YAML 管道。 示例管道包括生成、测试和部署阶段,以及备用部署和回滚的可选阶段。 回滚阶段使你能够在出现问题时快速还原到稳定版本,从而提升系统的可靠性和稳定性。

此代码适用于大多数方案,但不包括特定于语言或平台的要求。 下一步,根据特定的实现需求自定义管道。

若要了解如何生成包含阶段的经典管道,请参阅 使用经典发布管道从多个分支部署到不同阶段

先决条件

产品 要求
Azure DevOps - 一个 Azure DevOps 项目
- 能够在 Microsoft 托管的代理上运行管道。 可以购买并行作业,也可以请求免费层。
- 对 YAML 和 Azure Pipelines 的基本知识。 有关详细信息,请参阅创建第一个管道
- 权限:
     若要创建管道,用户需要位于 “参与者 ”组中,并且该组需要将 “创建生成管道 ”权限设置为“允许”。 生成管理员和项目管理员组的成员还可以管理管道。
GitHub - GitHub 帐户。
- 用于授权 Azure Pipelines 的 GitHub 服务连接
天蓝色 一个 Azure 订阅

1. 创建初学者管道

  1. 在 Azure DevOps 项目中,选择 “管道>创建管道”,然后选择 GitHub 作为源代码的位置。
  2. “选择存储库 ”屏幕上,选择存储库。
  3. “配置管道 ”屏幕上,选择 “初学者管道”。
  4. 保存管道。

2.添加生成阶段

在上一阶段中添加的初学者管道是占位符。 删除初始管道代码,并添加一个具有构建阶段的新 YAML 管道。

  1. 删除管道中的所有代码。

  2. 将代码替换为以下包含 Build 阶段的 YAML。

    trigger:
    - main
    
    pool:
      vmImage: 'ubuntu-latest'
    
    stages:
    - stage: Build
      displayName: 'Build Stage'
      jobs:
      - job: BuildJob
        displayName: 'Build Job'
        steps:
        - script: |
            echo "Restoring project dependencies..."
          displayName: 'Restore dependencies'
        - script: |
            echo "Running unit tests..."
          displayName: 'Run unit tests'
    

在此 Build 阶段和整个示例管道中,都有占位符脚本任务。 生成工作管道时,请将占位符命令 Restoring project dependencies... 替换为实际代码。

在此示例中,你将还原依赖项并运行单元测试,以确保代码已准备好进行测试和部署。 如果应用程序需要编译源代码,这一过程也会在 Build 阶段进行。

3.添加测试阶段

Test 阶段对项目运行测试,并将测试结果发布到 Azure DevOps。 若要了解有关发布测试结果的详细信息,请参阅 发布测试结果任务

仅当Test阶段成功完成并且无法跳过时,Build阶段才会运行。

在你的管道中,在 Test 阶段之后添加 Build 阶段。

- stage: Test
  displayName: 'Test Stage'
  dependsOn: Build
  isSkippable: false
  jobs:
  - job: TestJob
    displayName: 'Test Job'
    steps:
    - script: |
        echo "Running unit tests..."
      displayName: 'Run unit tests'

测试阶段包括一个将 isSkippable 设置为 false 的属性。 如果将isSkippable设置为false,则无法跳过该阶段。 在 Azure DevOps UI 中,也会禁用跳过阶段的选项。

无法跳过的阶段的屏幕截图。

4. 部署到过渡环境

在你的管道中,在 DeployToStaging 阶段之后添加 Test 阶段。

DeployToStaging 阶段取决于要运行的 Test 阶段。 DeployToStaging 阶段有两个不同的作业 - DeployStagingJobDeployStagingJobWithValidationDeployStagingJob 应包含用于将暂存作业部署到暂存资源(如暂存服务器)的代码。

DeployStagingJobWithValidation 作业包含暂存部署随附的所有验证。 DeployStagingJobWithValidation 作业需要手动批准。 手动验证任务 暂停管道运行并等待手动交互。 用户需要在运行开始之前验证该阶段。 在您的流程中加入手动审批会增加安全防护级别,有助于规避风险,并确保适当的利益相关者审查所有更改。

手动审批池为 server。 手动验证仅在服务器池上运行。

- stage: DeployToStaging
  displayName: 'Deploy to Staging'
  dependsOn: Test
  jobs:
  - job: DeployStagingJob
    displayName: 'Deploy to Staging Job'
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - script: |
        echo "Build staging job..."
      displayName: 'Build and deploy to staging'

  - job: DeployStagingJobWithValidation
    pool: server
    timeoutInMinutes: 4320 # job times out in 3 days
    displayName: 'Deploy to Staging Job'
    steps:
    - task: ManualValidation@1
      timeoutInMinutes: 1440 # task times out in 1 day
      inputs:
        notifyUsers: user@example.com
        instructions: 'Please validate the stage configuration and resume'
        onTimeout: 'resume'

5. 部署到生产

在你的管道中,在 DeployToProduction 阶段之后添加 DeployToStaging 阶段。

DeployToProduction 阶段中,应用程序部署到生产环境,但前提是 DeployToStaging 阶段成功且源分支为或 mainrelease

DeployToProduction 阶段有两个不同的作业 - DeployProductionJobwaitForValidation

手动验证任务waitForValidation为安全和质量控制添加了第二个人工验证步骤。 我们还在 DeployToStaging 阶段使用了手动验证任务。

- stage: DeployToProduction
  displayName: 'Deploy to Production'
  dependsOn: DeployToStaging
  lockBehavior: sequential
  condition: and(succeeded(), in(variables['Build.SourceBranch'], 'refs/heads/main', 'refs/heads/release'))
  jobs:
  - job: DeployProductionJob
    displayName: 'Deploy to Production Job'
    steps:
    - script: |
        echo "Deploying to production..."
        # Add your deployment commands here
      displayName: 'Run deployment commands'
  - job: waitForValidation
    displayName: Wait for external validation
    pool: server
    timeoutInMinutes: 4320 # job times out in 3 days
    steps:
    - task: ManualValidation@1
      timeoutInMinutes: 1440 # task times out in 1 day
      inputs:
        notifyUsers: user@example.com
        instructions: 'Please validate the build configuration and resume'
        onTimeout: 'resume'

6.添加可选的备用生产和回滚阶段

可以选择在DeployToAlternateProduction阶段之后添加RollbackDeployToProduction两个阶段。

DeployToAlternateProductionRollback 已手动排队。 DeployToAlternateProduction 阶段允许在主环境发生故障时准备好备份生产环境。 环境可以是 Azure DevOps 环境 ,也可以是其他云提供商等其他位置。 这增强了应用程序的整体可靠性和可用性。 你可能还希望有备用部署环境进行灾难恢复或测试和验证。 有关更复杂的部署策略,请参阅 部署作业添加阶段、依赖项和条件

Rollback 阶段提供了一个安全网,用于在部署期间或部署后出现问题时将应用程序还原为以前稳定的状态。 这可能是因为部署失败、bug、合规性要求、灾难恢复或其他问题。 回滚阶段对于维护应用程序的稳定性和可靠性至关重要。

- stage: DeployToAlternateProduction
  displayName: 'Deploy to Alternate Production'
  condition: succeeded()
  trigger: manual
  jobs:
  - job: DeployAlternateProductionJob
    displayName: 'Deploy to Alternate Production Job'
    steps:
    - script: |
        echo "Deploying to alternate production..."
        # Add your deployment commands here
      displayName: 'Run deployment commands'

- stage: Rollback
  displayName: 'Rollback Stage'
  trigger: manual
  jobs:
  - job: RollbackJob
    displayName: 'Rollback Job'
    steps:
    - script: |
        echo "Rolling back the deployment..."
        # Add your rollback commands here
      displayName: 'Run rollback commands'

查看整个 YAML 管道

下面是包含所有提到的阶段的整个管道。

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Build
  displayName: 'Build Stage'
  jobs:
  - job: BuildJob
    displayName: 'Build Job'
    steps:
    - script: |
        echo "Restoring project dependencies..."
      displayName: 'Restore dependencies'
    - script: |
        echo "Running unit tests..."
      displayName: 'Run unit tests'

- stage: Test
  displayName: 'Test Stage'
  dependsOn: Build
  isSkippable: false
  jobs:
  - job: TestJob
    displayName: 'Test Job'
    steps:
    - script: |
        echo "Running unit tests..."
      displayName: 'Run unit tests'


- stage: DeployToStaging
  displayName: 'Deploy to Staging'
  dependsOn: Test
  jobs:
  - job: DeployStagingJob
    displayName: 'Deploy to Staging Job'
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - script: |
        echo "Build staging job..."
      displayName: 'Build and deploy to staging'

  - job: DeployStagingJobWithValidation
    pool: server
    timeoutInMinutes: 4320 # job times out in 3 days
    displayName: 'Deploy to Staging Job'
    steps:
    - task: ManualValidation@1
      timeoutInMinutes: 1440 # task times out in 1 day
      inputs:
        notifyUsers: user@example.com
        instructions: 'Please validate the stage configuration and resume'
        onTimeout: 'resume'

- stage: DeployToProduction
  displayName: 'Deploy to Production'
  dependsOn: DeployToStaging
  lockBehavior: sequential
  condition: and(succeeded(), in(variables['Build.SourceBranch'], 'refs/heads/main', 'refs/heads/release'))
  jobs:
  - job: DeployProductionJob
    displayName: 'Deploy to Production Job'
    steps:
    - script: |
        echo "Deploying to production..."
        # Add your deployment commands here
      displayName: 'Run deployment commands'
  - job: waitForValidation
    displayName: Wait for external validation
    pool: server
    timeoutInMinutes: 4320 # job times out in 3 days
    steps:
    - task: ManualValidation@1
      timeoutInMinutes: 1440 # task times out in 1 day
      inputs:
        notifyUsers: user@example.com
        instructions: 'Please validate the build configuration and resume'
        onTimeout: 'resume'

- stage: DeployToAlternateProduction
  displayName: 'Deploy to Alternate Production'
  condition: succeeded()
  trigger: manual
  jobs:
  - job: DeployAlternateProductionJob
    displayName: 'Deploy to Alternate Production Job'
    steps:
    - script: |
        echo "Deploying to alternate production..."
        # Add your deployment commands here
      displayName: 'Run deployment commands'

- stage: Rollback
  displayName: 'Rollback Stage'
  trigger: manual
  jobs:
  - job: RollbackJob
    displayName: 'Rollback Job'
    steps:
    - script: |
        echo "Rolling back the deployment..."
        # Add your rollback commands here
      displayName: 'Run rollback commands'

后续步骤