Reputation: 1091
I'm setting up a pipeline using Azure Pipelines YAML format. I have created 3 stages: Build, Staging, and Production. As the names suggest, the Build stage builds the project and publishes the build artifacts. The Staging stage deploys to the Staging environment and the Production stage deploys to the Production environment.
In the Environments section of my project, I have added a check for the Production environment so that I can approve the deployment before going live.
The way that my pipeline works is that both Staging and Production stages are triggered automatically after the Build stage is finished. What I don't like about this is that when developers deploy their code to Staging, they need a couple of days to test it on Staging before pushing their code to Production. So, until then, my pipeline keeps running and waiting for my approval. The spinner at the top-left corner keeps spinning and the "Duration" field keeps passing.
Is there any ways that develpers manually trigger the Production stage whenever they are ready instead of the Build stage triggering it?
Upvotes: 63
Views: 89016
Reputation: 8058
This functionality is rolling out now (August 2024). To make use of it you need to use the following within the Stage
trigger: manual
See the release note for more details. Doesn't appear to be in the documentation yet.
Upvotes: 6
Reputation: 111
Five years after the feature request has been placed at Microsoft, the thing is on its way.
But for those who (need to) stick with an older ADO Server version, the best workaround we have found is the following. lets say for the QA
environment you want a manual gate:
QA
1 minute
(don't worry).skipped
, but you can give it a manual kick:
Retry Stage
and approve right after.Little downside: notifications. We turned the global notifications for pipeline( do not confuse with 'release notification for approvals') approvals off and added a manual subscription:
Now, in terms of filters, it is a bit dirty since you cannot scope the subscription to an environment, but only a resource name
/ type
, pipeline
or stage name
. EnvironmentName
would be great, but well....
There is also the ManualIntervention@8
or ManualValidation
tasks which you could consider with timeouts. On the upside they would not necessarily notify, but on the downside they would move the pipeline into failed
state after the timeout.
Upvotes: 1
Reputation: 1742
This is possible via manual approval steps as mentioned by @Blue_Clouds and described in detail here;
https://samlearnsazure.blog/2020/02/05/approvals-in-environments/
In my case I am building a nuget package to two different feeds, a pre-release feed with nuget packages built in DEBUG and when approved that same package with the same version number is built in RELEASE configuration and deployed to the main release feed. Now developers can reference a package from the pre-release feed and debug all the way into the nuget package, and release packages with optimised code can be used for building the production deployable code.
These are the high level steps.
The process involves doing the following, In Azure DevOps
Now you need to connect that environment to your release via a stages deployment.
Here is the main part of the "release" section of the .yaml file
- stage: Release
jobs:
- deployment: Build_Release_Deploy
displayName: Build and Deploy Release Package
environment: NugetRelease
pool:
vmImage: 'windows-latest'
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: DotNetCoreCLI@2
displayName: DotNet Restore
inputs:
command: 'restore'
projects: '**/MyProject.sln'
feedsToUse: 'select'
vstsFeed: '40a781fa-22c1-xxxx-xxxx-xxxxxxxxxxxx/9b2782f5-76e8-xxxx-xxxx-xxxxxxxxxxxx'
This is what it looks like;
Published to Pre-Release feed and awaiting approval for Release deployment
Review
Approval
Deployed
Here is a full example of a pipeline that would run to create and publish a nuget package to a pre-release feed and then a release package to a release feed on approval. In my example the file structure is as follows:
trigger:
- main
# the build will run on a Microsoft hosted agent, using the lastest Windows VM Image
pool:
vmImage: 'windows-latest'
variables:
majorMinor: 2.0
name: $(majorMinor)$(rev:.r)
stages:
- stage: PreRelease
jobs:
- job: Build_PreRelease
displayName: Build PreRelease
steps:
- task: DotNetCoreCLI@2
displayName: DotNet Restore
inputs:
command: 'restore'
projects: '**/MySolution.sln'
feedsToUse: 'select'
vstsFeed: '40a781fa-xxxx-xxxx-xxxx-xxxxxxxxxxxx/d7b8f0fe-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
- task: SnykSecurityScan@1
inputs:
serviceConnectionEndpoint: 'Snyk Security'
testType: 'app'
targetFile: 'src/MySolution.sln'
monitorWhen: 'always'
failOnIssues: true
- task: DotNetCoreCLI@2
displayName: 'DotNet Build'
inputs:
command: 'build'
arguments: '--configuration Debug'
projects: '**/MySolution/MySolution.csproj'
- job: PackageDeploy_PreRelease
displayName: Package and Deploy PreRelease
dependsOn: Build_PreRelease
condition: succeeded()
steps:
#package
- task: DotNetCoreCLI@2
displayName: 'DotNet Pack'
inputs:
command: 'pack'
packagesToPack: '**/MySolution/MySolution.csproj'
versioningScheme: byEnvVar
versionEnvVar: BUILD_BUILDNUMBER
#push
- task: DotNetCoreCLI@2
displayName: "NuGet Push"
inputs:
command: 'push'
packagesToPush: '$(Build.ArtifactStagingDirectory)/*.nupkg'
nuGetFeedType: 'internal'
publishVstsFeed: '40a781fa-xxxx-xxxx-xxxx-xxxxxxxxxxxx/d7b8f0fe-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
#publish
- task: PublishBuildArtifacts@1
displayName: "Publish Artifact"
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
TargetPath: '\\MySolution\$(Build.DefinitionName)\$(Build.BuildNumber)'
publishLocation: 'Container'
- stage: Release
jobs:
- deployment: Build_Release_Deplpy
displayName: Build and Deploy Release Package
environment: NugetRelease
pool:
vmImage: 'windows-latest'
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: PowerShell@2
displayName: 'Echo Version'
inputs:
targetType: inline
script: echo $(Build.BuildNumber)
- task: DotNetCoreCLI@2
displayName: DotNet Restore
inputs:
command: 'restore'
projects: '**/MySolution.sln'
feedsToUse: 'select'
vstsFeed: '40a781fa-xxxx-xxxx-xxxx-xxxxxxxxxxxx/9b2782f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
- task: SnykSecurityScan@1
inputs:
serviceConnectionEndpoint: 'Snyk Security'
testType: 'app'
targetFile: 'src/MySolution.sln'
monitorWhen: 'always'
failOnIssues: true
- task: DotNetCoreCLI@2
displayName: 'DotNet Build'
inputs:
command: 'build'
arguments: '--configuration Release'
projects: '**/MySolution/MySolution.csproj'
#package
- task: DotNetCoreCLI@2
displayName: 'DotNet Pack'
inputs:
command: 'pack'
packagesToPack: '**/MySolution/MySolution.csproj'
versioningScheme: byEnvVar
versionEnvVar: BUILD_BUILDNUMBER
#push
- task: DotNetCoreCLI@2
displayName: "NuGet Push"
inputs:
command: 'push'
packagesToPush: '$(Build.ArtifactStagingDirectory)/*.nupkg'
nuGetFeedType: 'internal'
publishVstsFeed: '40a781fa-xxxx-xxxx-xxxx-xxxxxxxxxxxx/9b2782f5-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
#publish
- task: PublishBuildArtifacts@1
displayName: "Publish Artifact"
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
TargetPath: '\\MySolution\$(Build.DefinitionName)\$(Build.BuildNumber)'
publishLocation: 'Container'
Hopefully this helps :-)
Upvotes: 4
Reputation: 1156
One great workaround with YAML is using conditions and variables.
Just add condition: eq(variables['Build.Reason'], 'Manual')
in the stage that needs manual intervention and it should be it.
There is a lot of useful information on https://ochzhen.com/blog/manual-trigger-in-yaml-azure-pipelines
Here is a link to view all values of Build.Reason: https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml
Upvotes: 3
Reputation: 1402
I have a much cleaner solution that I've been using for quite a while. It's similar to my original solution posted here but instead of manually adding a variable to the pipeline I add a parameter and use it as a condition to trigger the deployment in a particular environment.
The azure-pipelines.yaml looks like this:
trigger:
- master
parameters:
- name: deployDEV
displayName: Deploy to DEV
type: boolean
default: false
stages:
- stage: Build
jobs:
- job: Build
steps:
- script: |
echo "Building something..."
- stage: Release_DEV
displayName: Release to DEV
condition: |
and(
succeeded('Build'),
eq(${{ parameters.deployDEV }}, true)
)
dependsOn: Build
jobs:
- job: Release DEV
steps:
- script: |
echo "Releasing to DEV..."
The beauty of this solution is that when you're starting a new instance you'll get the parameters as options in the UI like this:
Upvotes: 11
Reputation: 41545
You can specify which stage you want to run.
When you click "Run pipeline", click on "Stages to run":
Now choose which staged will run:
Upvotes: 18
Reputation: 1402
I think there's a better way. You can add a pipeline variable which can can be overridden when starting the pipeline.
You have to add a new variable to your pipeline and chose 'Let users override this value when running this pipeline'.
In your pipeline add a condition to your stage such as:
condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['DEPLOY_PROD'], 'true')))
Now whenever you want a build to deploy to Production you start the build and then override the variable from here:
Set the value to 'true' and your build will trigger the stage you want.
Upvotes: 9
Reputation: 2918
you can set the trigger to none to disable CI and only trigger it manual
trigger: none
Upvotes: 48
Reputation: 8153
Yes it can be done. We do not do it in the yaml directly. But instead we add environment in YAML. And on environment we add manual trigger.
environment: 'smarthotel-dev'
Environment and triggers are managed through UI.
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/environments?view=azure-devops
Upvotes: 1
Reputation: 30313
Manual stages in yaml pipeline is not available currently. This feature request has been submitted to Microsoft. You can go and vote it up or submit a new one.
There are workarounds to achieve this.
You can move your staging and production stages to Classic Web UI Release Pipeline. Manually trigger a stage is available in Web UI Release pipeline. Please check here for more information.
Another way to achieve this is to separate your yaml pipeline into two yaml pipelines(stage pipeline and production pipeline). And disable CI build for production pipeline( in the pipeline edit page, click on the 3dots on the top right corner and choose triggers. Please refer to below pics).
So that you can manually run production pipeline after Developer done with their tests.
Upvotes: 22