Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
With multiple stages, you can isolate different parts of your pipeline, improve quality control and security, have better visibility into the pipeline's progress, and mitigate risk.
In this article, learn how to create and run a more complex YAML pipeline with multiple stages and conditions. The example pipeline includes build, test, and deploy stages and also has optional stages for alternate deployments and rollbacks. The rollback stage lets you quickly revert to a stable version if something goes wrong, enhancing reliability and stability.
This code works for most scenarios but doesn't include language or platform-specific requirements. As a next step, customize the pipeline for your specific implementation needs.
To learn how to build a Classic pipeline with stages, see Deploy to different stages from multiple branches using Classic release pipelines.
Prerequisites
Product | Requirements |
---|---|
Azure DevOps | - An Azure DevOps project. - An ability to run pipelines on Microsoft-hosted agents. You can either purchase a parallel job or you can request a free tier. - Basic knowledge of YAML and Azure Pipelines. For more information, see Create your first pipeline. - Permissions: To create a pipeline, users need to be in the Contributors group and the group needs to have Create build pipeline permission set to Allow. Members of the Build Administrators and Project Administrators groups can also manage pipelines. |
GitHub | - A GitHub account. - A GitHub service connection to authorize Azure Pipelines. |
Azure | An Azure subscription. |
1. Create a starter pipeline
- In your Azure DevOps project, select Pipelines > Create Pipeline, and then select GitHub as the location of your source code.
- On the Select a repository screen, select your repository.
- On the Configure your pipeline screen, select Starter pipeline.
- Save your pipeline.
2. Add the build stage
The starter pipeline you added in the previous stage was a placeholder. Remove the starter pipeline code and add in a new YAML pipeline with a Build stage.
Remove all of the code in your pipeline.
Replace the code with the following YAML that includes a
Build
stage.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'
In this Build
stage and throughout the sample pipeline, there are placeholder script tasks. When you build a working pipeline, replace the placeholder commands like Restoring project dependencies...
with actual code.
In this sample, you're restoring dependencies and running unit tests to make sure the code is ready for testing and deployment. If your application needs to compile source code, that will also happen in the Build
stage.
3. Add the test stage
The Test
stage runs tests on the project and publishes the test results to Azure DevOps. To learn more about publishing test results, see the Publish Test Results task.
The Test
stage only runs if the Build
stage completes successfully and the stage can't be skipped.
Add the Test
stage after the Build
stage in your pipeline.
- 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'
The Test stage includes an attribute that sets isSkippable
to false
. When you set isSkippable
to false
, a stage can't be skipped. The option to skip the stage is also disabled in the Azure DevOps UI.
4. Deploy to staging
Add the DeployToStaging
stage after the Test
stage in your pipeline.
The DeployToStaging
stage depends on the Test
stage to run. There are two different jobs in the DeployToStaging
stage - DeployStagingJob
and DeployStagingJobWithValidation
. The DeployStagingJob
should contain the code to deploy your staging job to staging resources like a staging server.
The DeployStagingJobWithValidation
job contains all of the validation that goes with your staging deployment. The DeployStagingJobWithValidation
job requires manual approval. The manual validation task pauses the pipeline run and waits for a manual interaction. A user needs to validate the stage before the run proceeds. Having a manual approval in your pipeline adds another level of security, helps mitigate risks, and makes sure that all changes get reviewed by the appropriate stakeholders.
The pool for the manual approval is server
. Manual validations only run on a server pool.
- 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: [email protected]
instructions: 'Please validate the stage configuration and resume'
onTimeout: 'resume'
5. Deploy to production
Add the DeployToProduction
stage after the DeployToStaging
stage in your pipeline.
In the DeployToProduction
stage, the application deploys to production, but only if the DeployToStaging
stage succeeds and the source branch is either main
or release
.
There are two different jobs in the DeployToProduction
stage - DeployProductionJob
and waitForValidation
.
The manual validation task in waitForValidation
adds a second human validation step for security and quality control. We also used a manual validation task in the DeployToStaging
stage.
- 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: [email protected]
instructions: 'Please validate the build configuration and resume'
onTimeout: 'resume'
6. Add optional alternate production and rollback stages
You can optionally add two stages DeployToAlternateProduction
and Rollback
after the DeployToProduction
stage.
DeployToAlternateProduction
and Rollback
are manually queued. The DeployToAlternateProduction
stage lets you have a backup production environment ready in case your primary environment fails. An environment can be an Azure DevOps Environment or another location like a different cloud provider. This enhances the overall reliability and availability of your application. You might also want to have an alternate deployment environment for disaster recovery or testing and validation. For more complicated deployment strategies, see Deployment jobs and Add stages, dependencies, and conditions.
The Rollback
stage provides a safety net to revert your application to a previously stable state if something goes wrong during or after a deployment. This could be because of a deployment failure, bug, compliance requirement, disaster recovery, or other issue. A rollback stage is essential for maintaining the stability and reliability of your application.
- 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'
View the entire YAML pipeline
Here's the entire pipeline with all of the referenced stages.
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: [email protected]
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: [email protected]
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'