« Azure pipeline » : différence entre les versions
De Banane Atomic
Aller à la navigationAller à la recherche
(127 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 3 : | Ligne 3 : | ||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops Azure Pipelines documentation] | * [https://docs.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops Azure Pipelines documentation] | ||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/get-started/key-pipelines-concepts?view=azure-devops Key concepts for new Azure Pipelines users] | * [https://docs.microsoft.com/en-us/azure/devops/pipelines/get-started/key-pipelines-concepts?view=azure-devops Key concepts for new Azure Pipelines users] | ||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/ | * [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/approvals?view=azure-devops&tabs=check-pass Define approvals and checks] | ||
= Definitions = | = Definitions = | ||
Ligne 22 : | Ligne 22 : | ||
| Release agent || the one who execute the tasks defined in the release pipeline definition<br>it is the same agent as the one used for the build | | Release agent || the one who execute the tasks defined in the release pipeline definition<br>it is the same agent as the one used for the build | ||
|} | |} | ||
= Steps of a release = | |||
# Build the software with a pipeline | |||
#* validate product quality (unit tests, SonarCloud) | |||
# Deploy the software | |||
#* validate runtime stability (compare telemetry with previous version) | |||
# Release the feature | |||
#* validate feature usage | |||
= [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch Release variables] = | = [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch Release variables] = | ||
= [https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml Predefined variables] = | |||
{| class="wikitable wtp wtmono1 wtmono2" | |||
! Name | |||
! Value | |||
|- | |||
| System.DefaultWorkingDirectory || E:\Agent\Release_INT_2\_work\24\s | |||
|- | |||
| System.ArtifactsDirectory || E:\Agent\Release_INT_2\_work\24\a | |||
|- | |||
| Pipeline.Workspace || E:\Agent\Release_INT_2\_work\24 | |||
|} | |||
= Trigger pipeline for PR = | |||
# Azure DevOps → MyProject → Project Settings (bottom left gear) | |||
# Repos → Repositories → MyRepo | |||
# Policies → Branch Policies → master | |||
# Build Validation → {{boxx|+}} | |||
= [https://docs.microsoft.com/en-us/azure/devops/pipelines/artifacts/artifacts-overview?view=azure-devops Artifact] = | |||
= YAML = | = YAML = | ||
Ligne 30 : | Ligne 57 : | ||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates Template types & usage] | * [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates Template types & usage] | ||
* [https://samlearnsazure.blog/2020/02/05/approvals-in-environments/ Approvals in environments with multi-stage YAML pipelines] | * [https://samlearnsazure.blog/2020/02/05/approvals-in-environments/ Approvals in environments with multi-stage YAML pipelines] | ||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#environment YAML schema reference] | |||
== Create a new pipeline == | == Create a new pipeline == | ||
=== From an existing YAML file === | === [https://stackoverflow.com/questions/59067096/create-a-new-pipeline-from-existing-yml-file-in-the-repository-azure-pipelines From an existing YAML file] === | ||
* Pipelines → New pipeline | |||
* Azure Repo Git YAML → Select your repo → Existing Azure pipelines YAML file | |||
== Exemple == | == Exemple == | ||
Ligne 72 : | Ligne 102 : | ||
</kode> | </kode> | ||
== [https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema# | == [https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#triggers Trigger] == | ||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#job Job] | {{warn | If you specify no push trigger, pushes to any branch trigger a build.}} | ||
<kode lang='yaml'> | |||
trigger: | |||
batch: true # batch changes if true; start a new build for every push if false (default) | |||
branches: | |||
include: # branch names which will trigger a build | |||
- master | |||
- release/* | |||
exclude: temp # branch names which will not | |||
paths: | |||
include: MyProject/* # file paths which must match to trigger a build | |||
exclude: temp # file paths which will not trigger a build | |||
trigger: none # will disable CI builds entirely | |||
</kode> | |||
== [https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#stage Stage] == | |||
<kode lang='yaml'> | |||
stages: | |||
- stage: stage_name # (A-Z, a-z, 0-9, and underscore) | |||
# friendly name to display in the UI | |||
displayName: 'Stage name' | |||
variables: # ... | |||
condition: # ... | |||
jobs: [ job | templateReference] | |||
</kode> | |||
== [https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#job Job] == | |||
<kode lang='yaml'> | <kode lang='yaml'> | ||
jobs: | jobs: | ||
Ligne 81 : | Ligne 140 : | ||
variables: # ... | variables: # ... | ||
pool: PoolName | pool: PoolName | ||
# wait the dependencies to run and succeed before starting current job | |||
dependsOn: job1 | |||
dependsOn: | |||
- job1 | |||
- job2 | |||
condition: # ... | condition: # ... | ||
Ligne 91 : | Ligne 158 : | ||
</kode> | </kode> | ||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/ | === [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/deployment-jobs?view=azure-devops Deployment job] === | ||
<kode lang='yaml'> | <kode lang='yaml'> | ||
# | jobs: | ||
pool: PoolName | - deployment: job_name # [A-Za-z0-9_]+ | ||
# same properties as normal job | |||
# ... | |||
environment: CI # target environment name | |||
CI.MyResource # and optionally a resource-name to record the deployment history; format: <environment-name>.<resource-name> | |||
pool: PoolName | |||
strategy: | |||
runOnce: | |||
preDeploy: # Used to run steps that initialize resources before application deployment starts. | |||
steps: | |||
# ... | |||
deploy: # Used to run steps that deploy your application. | |||
steps: | |||
# ... | |||
routeTraffic: # Used to run steps that serve the traffic to the updated version. | |||
steps: | |||
# ... | |||
postRouteTraffic: # Used to run the steps after the traffic is routed. | |||
# Typically, these tasks monitor the health of the updated version for defined interval. | |||
steps: | |||
# ... | |||
on: | |||
failure: # Used to run steps for rollback actions. | |||
steps: | |||
# ... | |||
success: # Used to run steps for clean-up. | |||
steps: | |||
# ... | |||
</kode> | </kode> | ||
== [https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=example%2Cparameter-schema#steps Task] == | |||
< | <kode lang='yaml'> | ||
steps: | steps: | ||
# step | |||
- task: TaskToCall@Version # VSBuild@1 | |||
name: StepName # A-Z, a-z, 0-9, and underscore | |||
displayName: 'My Step' | |||
timeoutInMinutes: 120 | |||
inputs: | |||
key: 'value' | |||
enabled: boolean | |||
# runs a script in Bash | # runs a script in Bash | ||
- bash: | | - bash: | | ||
Ligne 112 : | Ligne 210 : | ||
# friendly name displayed in the UI | # friendly name displayed in the UI | ||
displayName: Multiline Bash script | displayName: Multiline Bash script | ||
== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/powershell?view=azure-devops PowerShell task] == | # runs a script in PowerShell Core | ||
- pwsh: Write-Host Hello $(name) | |||
# runs a script in Windows PowerShell | |||
- powershell: Write-Host Hello $(name) | |||
# checkout git repo | |||
- checkout: self | none | repo name # self represents the repo where the initial Pipelines YAML file was found | |||
clean: boolean # if true, run `execute git clean -ffdx && git reset --hard HEAD` before fetching. Default: false | |||
fetchDepth: number # the depth of commits to ask Git to fetch | |||
</kode> | |||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/azure-repos-git?view=azure-devops&tabs=yaml#shallow-fetch Shallow fetch] | |||
* [https://learn.microsoft.com/en-us/azure/devops/pipelines/yaml-schema/steps-checkout Checkout] | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/powershell?view=azure-devops PowerShell task] === | |||
<kode lang='yaml'> | <kode lang='yaml'> | ||
- powershell: 'cmd' | |||
# 4 blank characters before the command | |||
- powershell: | | |||
cmd1 | |||
cmd2 | |||
# pwsh runs PowerShell Core, which must be installed on the agent or container. | |||
- pwsh: 'cmd' | |||
- task: PowerShell@2 | - task: PowerShell@2 | ||
displayName: 'PowerShell Script' | displayName: 'PowerShell Script' | ||
Ligne 128 : | Ligne 249 : | ||
targetType: inline | targetType: inline | ||
script: | | script: | | ||
' | cmd1 | ||
' | cmd2 | ||
</kode> | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/publish-pipeline-artifact?view=azure-devops Publish pipeline artifact] === | |||
<kode lang='yaml'> | |||
steps: | |||
- publish: MyProject\bin\Release # path to the folder to publish | |||
artifact: MyProject # artifact name | |||
- task: PublishPipelineArtifact@1 | |||
inputs: | |||
targetPath: MyProject\bin\Release # path to the folder to publish | |||
artifactName: MyProject | |||
parallel: true # Select whether to copy files in parallel using multiple threads. Default: false | |||
parallelCount: 8 # number of threads used to publish a package. Default: 8 | |||
</kode> | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/download-pipeline-artifact?view=azure-devops Download pipeline artifact] === | |||
<kode lang='yaml'> | |||
steps: | |||
# to stop artifacts from being downloaded automatically | |||
- download: none | |||
- download: current # options: current (default), specific | |||
artifact: ArtifactName | |||
# equivalent to | |||
- task: DownloadPipelineArtifact@2 | |||
inputs: | |||
artifact: ArtifactName | |||
# artifact from another pipeline | |||
- task: DownloadPipelineArtifact@2 | |||
inputs: | |||
buildType: 'specific' # current (default), specific | |||
project: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' # Required when buildType = specific | |||
pipeline: '0000' # Required when source = specific | |||
buildVersionToDownload: 'specific' | |||
buildId: '000000' # Required when source = specific && RunVersion = specific | |||
artifact: ArtifactName | |||
downloadPath: $(System.DefaultWorkingDirectory) # default: $(Pipeline.Workspace). relative path is concat to $(System.DefaultWorkingDirectory) | |||
</kode> | |||
* The Download Pipeline Artifact task can download both build artifacts (published with the Publish Build Artifacts task) and pipeline artifacts. | |||
* By default, files are downloaded to {{boxx|1=$(Pipeline.Workspace)/{artifact name} }} ({{boxx|E:\Agent\Release_INT_2\_work\1\ArtefactName}}) | |||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/artifacts/pipeline-artifacts?view=azure-devops&tabs=yaml-task#downloading-artifacts Downloading artifacts] | |||
* [https://docs.microsoft.com/en-us/rest/api/azure/devops/core/projects/list?view=azure-devops-rest-6.0 Get project GUID]: {{boxx|<nowiki>https://dev.azure.com/{organization}/_apis/projects</nowiki>}} | |||
* [https://docs.microsoft.com/en-us/rest/api/azure/devops/core/projects/list?view=azure-devops-rest-6.0 Get the pipeline definition ID]: {{boxx|<nowiki>https://dev.azure.com/{organization}/{project}/_apis/build/definitions?name={pipeline name}</nowiki>}} | |||
* [https://docs.microsoft.com/en-us/rest/api/azure/devops/build/builds/list?view=azure-devops-rest-6.0 Get the build ID]: {{boxx|<nowiki>https://dev.azure.com/{organization}/{project}/_apis/build/builds?definitions={pipeline definition ID}&buildNumber=x.x.xxxx.xxxxx</nowiki>}} | |||
* [https://docs.microsoft.com/en-us/rest/api/azure/devops/build/artifacts/list?view=azure-devops-rest-6.0 Get Artifact name]: {{boxx|<nowiki>https://dev.azure.com/{organization}/{project}/_apis/build/builds/{buildId}/artifacts</nowiki>}} | |||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/artifacts/pipeline-artifacts?view=azure-devops&tabs=yaml Publish and download artifacts in Azure Pipelines] | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/download-build-artifacts?view=azure-devops Download Build Artifacts] === | |||
<kode lang='yaml'> | |||
- task: DownloadBuildArtifacts@0 | |||
inputs: | |||
buildType: 'specific' # current (default), specific | |||
project: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' # Required when buildType = specific | |||
pipeline: '0000' # Required when source = specific | |||
buildVersionToDownload: 'specific' | |||
buildId: '000000' # Required when source = specific && RunVersion = specific | |||
artifactName: ArtifactName | |||
downloadPath: '$(System.ArtifactsDirectory)' | |||
</kode> | |||
* By default, files are downloaded to {{boxx|$(System.ArtifactsDirectory)/{artifact}}} | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/windows-machine-file-copy?view=azure-devops Windows Machine File Copy] === | |||
<kode lang='yaml'> | |||
- task: WindowsMachineFileCopy@2 | |||
displayName: 'Copy Files' | |||
inputs: | |||
sourcePath: '$(sourcePath)' | |||
machineNames: '$(machineNames=' | |||
adminUserName: '$(adminUserName)' | |||
adminPassword: '$(adminPassword)' | |||
targetPath: '$(targetPath)' | |||
additionalArguments: '/r:1 /w:10' # if a file copy fails, wait 10 seconds and retry 1 time | |||
cleanTargetBeforeCopy: true | |||
</kode> | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/powershell-on-target-machines?view=azure-devops PowerShell on Target Machines] === | |||
<kode lang='yaml'> | |||
- task: PowerShellOnTargetMachines@3 | |||
inputs: | |||
machines: '$(machines)' | |||
userName: '$(userName)' | |||
userPassword: '$(userPassword)' | |||
scriptType: 'filePath' # inline by default | |||
scriptPath: '$(scriptPath)' | |||
scriptArguments: '-Arg1 $(Arg1Value)' | |||
communicationProtocol: http | |||
- task: PowerShellOnTargetMachines@3 | |||
inputs: | |||
machines: '$(machines)' | |||
userName: '$(userName)' | |||
userPassword: '$(userPassword)' | |||
scriptType: 'inline' # inline by default | |||
inlineScript: | | |||
echo 'Hello !' | |||
communicationProtocol: http | |||
</kode> | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/package/nuget?view=azure-devops NuGet] === | |||
<kode lang='yaml'> | |||
- task: NuGetCommand@2 | |||
inputs: | |||
command: restore | |||
restoreSolution: MySolution.sln # relative path to a solution or project file | |||
</kode> | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/visual-studio-build?view=azure-devops Visual Studio Build task] === | |||
<kode lang='yaml'> | |||
- task: VSBuild@1 | |||
inputs: | |||
solution: MyProject\MyProject.csproj # relative path to a solution or project file | |||
platform: AnyCPU # options: Win32, x86, x64 or any cpu. For a project use AnyCPU | |||
configuration: release # options: debug or release | |||
clean: false # Set to false to make this an incremental build, it might reduce the build time. Make sure not to clean the repo too. | |||
msbuildArchitecture: x64 # options: x86 (default), x64 | |||
</kode> | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/file-transform?view=azure-devops&viewFallbackFrom=azure-devops%5D FileTransform] === | |||
Replace tokens with variable values in XML or JSON configuration files. | |||
<kode lang='yaml'> | |||
- job: | |||
variables: | |||
Name1: Value1 # replace ... by Value1 <setting name="Name1"><value>...</value></setting> | |||
- task: FileTransform@1 | |||
inputs: | |||
folderPath: $(Pipeline.Workspace)\MyArtefact | |||
fileType: xml | |||
targetFiles: MyProject.exe.config | |||
</kode> | |||
=== [https://github.com/magic-chunks/magic-chunks-dotnetcore MagicChunk] === | |||
Modify a XML, JSON or YAML file. | |||
<kode lang='yaml'> | |||
- task: MagicChunks@2 | |||
inputs: | |||
sourcePath: $(System.DefaultWorkingDirectory)\Folder\App.config | |||
transformations: | | |||
{ | |||
"root/node[@attribute1='value']/@attribute2": "true" | |||
} | |||
- | - task: MagicChunks@2 | ||
inputs: | |||
- | sourcePath: $(System.DefaultWorkingDirectory)\Folder\App.config | ||
transformationType: file | |||
transformationsFile: $(System.DefaultWorkingDirectory)\Folder\Transformations.json | |||
</kode> | |||
<filebox fn='Transformations.json'> | |||
{ | |||
"root/node[@attribute1='value']/@attribute2": "true" | |||
} | |||
</filebox> | |||
== [https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#pool Pool] == | |||
<kode lang='yaml'> | |||
# if you use a private pool and don't need to specify demands | |||
pool: PoolName | |||
# | pool: | ||
- | name: PoolName | ||
demands: | |||
- myCustomCapability # check for existence of capability | |||
- agent.os -equals Darwin # check for specific string in capability | |||
</kode> | </kode> | ||
Ligne 145 : | Ligne 428 : | ||
# scope: root, stage, job | # scope: root, stage, job | ||
variables: | variables: | ||
variable_name: 'value' | name1: 'value1' # name [\w\d._]+ | ||
name2: '${{ variables.name1 }} - value2' # reuse the value defined for name1 | |||
variables: | |||
- name: variable_name | |||
value: 'value' | |||
# groups are used to make variables inside that group available across multiple pipelines | |||
- group: group_name | |||
steps: | |||
- powershell: 'echo $(variable_name)' # pipeline variable | |||
- powershell: 'echo $(System.StageName)' # system variable | |||
- powershell: 'echo $(group_variable_name)' # variable in the group_name group variables | |||
- powershell: 'echo $env:VARIABLE_NAME' # environment variable | |||
- powershell: 'echo $(variable_name)' # macro syntax, processed during runtime before a task runs | |||
- powershell: 'echo ${{ variables.variable_name }}' # template expression syntax, processed at compile time, before runtime starts | |||
- powershell: 'echo $[variables.variable_name]' # Runtime expression syntax, processed during runtime, designed for use with conditions and expressions | |||
# Set a job-scoped variable from a script | |||
# the variable is available to downstream steps within the same job | |||
- powershell: echo "##vso[task.setvariable variable=variable_name]variable value" | |||
- powershell: echo $(variable_name) | |||
# Set a stage-scoped variable from a script | |||
jobs: | |||
- job: A | |||
steps: | |||
- powershell: echo "##vso[task.setvariable variable=variable_name;isOutput=true]variable value" | |||
name: task_name | |||
- powershell: echo $(task_name.variable_name) | |||
- job: B | |||
dependsOn: A | |||
variables: | |||
var_from_job_A: $[ dependencies.A.outputs['task_name.variable_name'] ] # expressions require single quotes | |||
# Set an inter-stage-scoped variable from a script | |||
stages: | |||
- stage: A | |||
jobs: | |||
- job: A1 | |||
steps: | |||
- powershell: echo "##vso[task.setvariable variable=variable_name;isOutput=true]variable value" | |||
name: task_name | |||
- stage: B | |||
dependsOn: A | |||
variables: | |||
var_from_stage_A: $[ stageDependencies.A.A1.outputs['task_name.variable_name'] ] | |||
</kode> | </kode> | ||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml Use predefined variables] | |||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/library/variable-groups?view=azure-devops&tabs=classic#create-a-variable-group Create a variable group] | |||
== [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/runtime-parameters?view=azure-devops&tabs=script Runtime parameters] == | == [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/runtime-parameters?view=azure-devops&tabs=script Runtime parameters] == | ||
Ligne 176 : | Ligne 509 : | ||
steps: | steps: | ||
- checkout: self # checkout in C:\agent\_work\1\s\CurrentRepoId | - checkout: self # checkout in $(Build.SourcesDirectory)\CurrentRepoId (C:\agent\_work\1\s\CurrentRepoId) | ||
- checkout: RepoId # checkout in C:\agent\_work\1\s\RepoId | - checkout: RepoId # checkout in $(Build.SourcesDirectory)\RepoId (C:\agent\_work\1\s\RepoId) | ||
</kode> | </kode> | ||
{{info | | {{info | | ||
* Single repository: If you have a single checkout step in your job, (or | * <u>Single repository:</u> If you have a single checkout step in your job, (or no checkout step which is equivalent to {{boxx|checkout: self}}), your source code is checked out into {{boxx|$(Build.SourcesDirectory)}}.<br>Ex: ({{boxx|C:\agent\_work\1\s}}) | ||
* Multiple repositories: If you have multiple checkout steps in your job, your source code is checked out into directories named after the repositories as a subfolder of {{boxx| | * <u>Multiple repositories:</u> If you have multiple checkout steps in your job, your source code is checked out into directories named after the repositories as a subfolder of {{boxx|$(Build.SourcesDirectory)}}.<br>Ex: {{boxx|C:\agent\_work\1\s\MyRepo}} | ||
}} | }} | ||
== [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/conditions?view=azure-devops&tabs=yaml Condition] == | == [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/conditions?view=azure-devops&tabs=yaml Condition and dependency] == | ||
{{info | It's as if you specified {{boxx|condition: succeeded()}}}} | |||
{| class="wikitable wtp wtmono1" | |||
! Condition | |||
! Description | |||
|- | |||
| succeeded() || Only when all previous dependencies have succeeded. This is the default if there is not a condition set in the YAML. | |||
|- | |||
| succeededOrFailed() || Even if a previous dependency has failed, unless the run was canceled. | |||
|- | |||
| always() || Even if a previous dependency has failed, even if the run was canceled. | |||
|- | |||
| failed() || Only when a previous dependency has failed. | |||
|} | |||
<kode lang='yaml'> | |||
# scope: stage, job, task | |||
condition: eq(variables.Var1, 'Value1') | |||
# parameter | |||
condition: eq('${{ parameters.Param1 }}', 'Value1') | |||
# and, or, eq, ne | |||
condition: or(eq(variables.Var1, 'Value1'), ne(variables.Var2, 'Value2')) | |||
# in | |||
condition: in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') | |||
# with dependencies: wait Job1 and Job2 to run | |||
dependsOn: | |||
- Job1 | |||
- Job2 | |||
# test Job1 and Job2 have succeeded and test Var1 = Value1 | |||
condition: and(succeeded(), eq(variables.Var1, 'Value1')) | |||
# test Job2 has succeeded and test Var1 = Value1 | |||
condition: and(succeeded('Job2'), eq(variables.Var1, 'Value1')) | |||
# test Job1 and Job2 have succeeded or skipped | |||
condition: | | |||
and | |||
( | |||
in(dependencies.Job1.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), | |||
in(dependencies.Job2.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') | |||
) | |||
# stage dependency | |||
- stage: Stage2 | |||
# on Stage1 | |||
condition: in(dependencies.Stage1.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') | |||
condition: eq(dependencies.Stage1.result, '') # Stage1 has not been selected | |||
# on Stage1.Job1.Task1.Var1 output variable | |||
condition: and(succeeded(), eq(dependencies.Stage1.outputs['Job1.Task1.Var1'], 'true')) | |||
# job dependency | |||
jobs: | |||
- job: Job2 | |||
# on Stage1.Job1 | |||
condition: in(stageDependencies.Stage1.Job1.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') | |||
# on Stage1.Job1.Task1.Var1 output variable | |||
condition: eq(stageDependencies.Stage1.Job1.outputs['Task1.Var1'], 'true') | |||
# on current stage Job3 | |||
condition: in(dependencies.Job3.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') | |||
# on current stage Job3.Task1.Var1 output variable | |||
condition: eq(dependencies.Job3.outputs['Task1.Var1'], 'true') | |||
</kode> | |||
{{info | You can specify conditions under which a {{boxx|step}}, {{boxx|job}}, or {{boxx|stage}} will run.}} | |||
{{info | By default, each stage in a pipeline depends on the one just before it in the YAML file.}} | |||
* [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#dependencies dependency] | |||
== [https://operatingops.org/2020/03/08/azure-pipelines-if-statements if statement] == | |||
<kode lang='yaml'> | <kode lang='yaml'> | ||
# conditional insertion | |||
variables: | |||
${{ if eq(variables['Build.SourceBranchName'], 'master') }}: | |||
var_name: value | |||
steps: | |||
- ${{ if eq(parameters.param_name, 'value') }}: | |||
- task: | |||
- task: | |||
inputs: | |||
${{ if eq(variables['Build.SourceBranchName'], 'master') }}: | |||
input_name: 'value' | |||
</kode> | |||
== [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops Template] == | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops#insert-a-template Insert a template] === | |||
Reuse stages, jobs ans tasks. | |||
<filebox fn='stages-template.yml'> | |||
stages: | stages: | ||
- stage: Stage1 | - stage: Stage1 | ||
jobs: | jobs: | ||
- job: | - job: Job1 | ||
steps: | |||
- script: echo 'stages template' | |||
</filebox> | |||
</ | |||
<filebox fn='jobs-template.yml'> | |||
jobs: | |||
- job: Job1 | |||
steps: | |||
- script: echo 'jobs template' | |||
</filebox> | |||
<filebox fn='tasks-template.yml'> | |||
steps: | |||
- script: echo 'tasks template' | |||
</filebox> | |||
<filebox fn='my-pipeline.yml'> | |||
stages: | |||
- template: stages-template.yml | |||
- stage: Stage2 | |||
jobs: | |||
- template: jobs-template.yml | |||
- stage: Stage3 | |||
jobs: | |||
- job: ExcecuteTasks | |||
steps: | |||
- template: tasks-template.yml | |||
</filebox> | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops#extend-from-a-template Extend from a template] === | |||
Copy the template in the pipeline. | |||
<filebox fn='my-template.yml'> | |||
resources: | |||
repositories: | |||
- repository: MyRepo | |||
type: git | |||
name: MyProject/MyRepo | |||
steps: | |||
- script: echo "My template" | |||
</filebox> | |||
<filebox fn='my-pipepline.yml'> | |||
extends: | |||
template: my-template.yml | |||
</filebox> | |||
=== [https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops#parameters Parameters] === | |||
<filebox fn='tasks-template.yml'> | |||
parameters: | |||
parameterName: 'parameter value' | |||
steps: | |||
- script: echo ${{ parameters.parameterName}} | |||
</filebox> | |||
<filebox fn='my-pipepline.yml'> | |||
variables: | |||
var: 'value' | |||
steps: | |||
- template: tasks-template.yml | |||
parameters: | |||
parameterName: 'value' | |||
parameterName: ${{ variables.var }} # $(var) doesn't work | |||
</filebox> | |||
=== Condition on a template === | |||
{{warn | It is not possible to set a condition on a template.}} | |||
<u>Solution 1</u>: pass a parameter to the template. | |||
<filebox fn='steps-template.yml'> | |||
parameters: | |||
enabled: true | |||
steps: | |||
- script: echo 'Task 1' | |||
condition: ${{ parameters.enabled }} | |||
</filebox> | |||
<filebox fn='my-pipepline.yml'> | |||
steps: | |||
- template: steps-template.yml | |||
parameters: | |||
enabled: false | |||
</filebox> | |||
<u>Solution 2:</u> use {{boxx|if}}. | |||
<filebox fn='my-pipepline.yml'> | |||
steps: | |||
- ${{ if eq($(MyVar), 'value') }}: | |||
- template: steps-template.yml | |||
</filebox> | |||
= | = Errors = | ||
== [https://developercommunity.visualstudio.com/content/problem/973090/environment-could-not-be-found-the-environment-doe.html Environment xxx could not be found] == | |||
# | # Pipelines → Environments → Select the env xxx → 3 dots button on top right → Security | ||
# | # Add the user with User role | ||
Dernière version du 13 octobre 2022 à 17:36
Links
- Azure Pipelines documentation
- Key concepts for new Azure Pipelines users
- Define approvals and checks
Definitions
Term | Definition |
---|---|
Artifact | item from a git repository or a build pipeline |
Stages | steps to deploy and validate a software a stage contains jobs |
Job | subparts of a stage, contains tasks to execute listed as steps a job runs on a agent or can be manually ran |
Tasks / Steps | subparts of a job, those are the concreate action to execute |
Release pipeline definition | steps to execute to get the artefacts, install and validate the software template to run a release |
Release agent | the one who execute the tasks defined in the release pipeline definition it is the same agent as the one used for the build |
Steps of a release
- Build the software with a pipeline
- validate product quality (unit tests, SonarCloud)
- Deploy the software
- validate runtime stability (compare telemetry with previous version)
- Release the feature
- validate feature usage
Release variables
Predefined variables
Name | Value |
---|---|
System.DefaultWorkingDirectory | E:\Agent\Release_INT_2\_work\24\s |
System.ArtifactsDirectory | E:\Agent\Release_INT_2\_work\24\a |
Pipeline.Workspace | E:\Agent\Release_INT_2\_work\24 |
Trigger pipeline for PR
- Azure DevOps → MyProject → Project Settings (bottom left gear)
- Repos → Repositories → MyRepo
- Policies → Branch Policies → master
- Build Validation → +
Artifact
YAML
- Specify jobs in your pipeline
- Template types & usage
- Approvals in environments with multi-stage YAML pipelines
- YAML schema reference
Create a new pipeline
From an existing YAML file
- Pipelines → New pipeline
- Azure Repo Git YAML → Select your repo → Existing Azure pipelines YAML file
Exemple
# do not trigger the pipeline on events trigger: none parameters: - name: myStepList type: stepList default: - bash: echo "We are on $(MyVar)" # If you have a single stage, you can omit the stages keyword and directly specify the jobs keyword stages: - stage: CI displayName: CI stage # remove implicite depency on the previous stage, the stages will run in parallel dependsOn: [] jobs: - job: ci_job pool: MyPool # If you have a single stage and a single job, you can omit the stages and jobs keywords and directly specify the steps keyword steps: - powershell: Write-Host "We are on CI" enabled: false # disable the task - stage: PROD displayName: PROD stage dependsOn: [] jobs: # use deployment job with environment and strategy to use the approval mechanism - deployment: prod_job environment: PROD strategy: runOnce: deploy: steps: ${{ parameters.myStepList }} |
Trigger
If you specify no push trigger, pushes to any branch trigger a build. |
trigger: batch: true # batch changes if true; start a new build for every push if false (default) branches: include: # branch names which will trigger a build - master - release/* exclude: temp # branch names which will not paths: include: MyProject/* # file paths which must match to trigger a build exclude: temp # file paths which will not trigger a build trigger: none # will disable CI builds entirely |
Stage
stages: - stage: stage_name # (A-Z, a-z, 0-9, and underscore) # friendly name to display in the UI displayName: 'Stage name' variables: # ... condition: # ... jobs: [ job | templateReference] |
Job
jobs: - job: job_name # (A-Z, a-z, 0-9, and underscore) # friendly name to display in the UI displayName: 'Job name' variables: # ... pool: PoolName # wait the dependencies to run and succeed before starting current job dependsOn: job1 dependsOn: - job1 - job2 condition: # ... # what to clean up before the job runs workspace: clean: outputs | resources | all steps: [ script | bash | pwsh | powershell | checkout | task | templateReference ] |
Deployment job
jobs: - deployment: job_name # [A-Za-z0-9_]+ # same properties as normal job # ... environment: CI # target environment name CI.MyResource # and optionally a resource-name to record the deployment history; format: <environment-name>.<resource-name> pool: PoolName strategy: runOnce: preDeploy: # Used to run steps that initialize resources before application deployment starts. steps: # ... deploy: # Used to run steps that deploy your application. steps: # ... routeTraffic: # Used to run steps that serve the traffic to the updated version. steps: # ... postRouteTraffic: # Used to run the steps after the traffic is routed. # Typically, these tasks monitor the health of the updated version for defined interval. steps: # ... on: failure: # Used to run steps for rollback actions. steps: # ... success: # Used to run steps for clean-up. steps: # ... |
Task
steps: # step - task: TaskToCall@Version # VSBuild@1 name: StepName # A-Z, a-z, 0-9, and underscore displayName: 'My Step' timeoutInMinutes: 120 inputs: key: 'value' enabled: boolean # runs a script in Bash - bash: | which bash echo Hello $(whoami) # friendly name displayed in the UI displayName: Multiline Bash script # runs a script in PowerShell Core - pwsh: Write-Host Hello $(name) # runs a script in Windows PowerShell - powershell: Write-Host Hello $(name) # checkout git repo - checkout: self | none | repo name # self represents the repo where the initial Pipelines YAML file was found clean: boolean # if true, run `execute git clean -ffdx && git reset --hard HEAD` before fetching. Default: false fetchDepth: number # the depth of commits to ask Git to fetch |
PowerShell task
- powershell: 'cmd' # 4 blank characters before the command - powershell: | cmd1 cmd2 # pwsh runs PowerShell Core, which must be installed on the agent or container. - pwsh: 'cmd' - task: PowerShell@2 displayName: 'PowerShell Script' inputs: targetType: filePath filePath: 'MyScript.ps1' arguments: '-Arg1 "Arg1"' - task: PowerShell@2 displayName: 'PowerShell Script' inputs: targetType: inline script: | cmd1 cmd2 |
Publish pipeline artifact
steps: - publish: MyProject\bin\Release # path to the folder to publish artifact: MyProject # artifact name - task: PublishPipelineArtifact@1 inputs: targetPath: MyProject\bin\Release # path to the folder to publish artifactName: MyProject parallel: true # Select whether to copy files in parallel using multiple threads. Default: false parallelCount: 8 # number of threads used to publish a package. Default: 8 |
Download pipeline artifact
steps: # to stop artifacts from being downloaded automatically - download: none - download: current # options: current (default), specific artifact: ArtifactName # equivalent to - task: DownloadPipelineArtifact@2 inputs: artifact: ArtifactName # artifact from another pipeline - task: DownloadPipelineArtifact@2 inputs: buildType: 'specific' # current (default), specific project: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' # Required when buildType = specific pipeline: '0000' # Required when source = specific buildVersionToDownload: 'specific' buildId: '000000' # Required when source = specific && RunVersion = specific artifact: ArtifactName downloadPath: $(System.DefaultWorkingDirectory) # default: $(Pipeline.Workspace). relative path is concat to $(System.DefaultWorkingDirectory) |
- The Download Pipeline Artifact task can download both build artifacts (published with the Publish Build Artifacts task) and pipeline artifacts.
- By default, files are downloaded to $(Pipeline.Workspace)/{artifact name} (E:\Agent\Release_INT_2\_work\1\ArtefactName)
- Downloading artifacts
- Get project GUID: https://dev.azure.com/{organization}/_apis/projects
- Get the pipeline definition ID: https://dev.azure.com/{organization}/{project}/_apis/build/definitions?name={pipeline name}
- Get the build ID: https://dev.azure.com/{organization}/{project}/_apis/build/builds?definitions={pipeline definition ID}&buildNumber=x.x.xxxx.xxxxx
- Get Artifact name: https://dev.azure.com/{organization}/{project}/_apis/build/builds/{buildId}/artifacts
- Publish and download artifacts in Azure Pipelines
Download Build Artifacts
- task: DownloadBuildArtifacts@0 inputs: buildType: 'specific' # current (default), specific project: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' # Required when buildType = specific pipeline: '0000' # Required when source = specific buildVersionToDownload: 'specific' buildId: '000000' # Required when source = specific && RunVersion = specific artifactName: ArtifactName downloadPath: '$(System.ArtifactsDirectory)' |
- By default, files are downloaded to $(System.ArtifactsDirectory)/{artifact}
Windows Machine File Copy
- task: WindowsMachineFileCopy@2 displayName: 'Copy Files' inputs: sourcePath: '$(sourcePath)' machineNames: '$(machineNames=' adminUserName: '$(adminUserName)' adminPassword: '$(adminPassword)' targetPath: '$(targetPath)' additionalArguments: '/r:1 /w:10' # if a file copy fails, wait 10 seconds and retry 1 time cleanTargetBeforeCopy: true |
PowerShell on Target Machines
- task: PowerShellOnTargetMachines@3 inputs: machines: '$(machines)' userName: '$(userName)' userPassword: '$(userPassword)' scriptType: 'filePath' # inline by default scriptPath: '$(scriptPath)' scriptArguments: '-Arg1 $(Arg1Value)' communicationProtocol: http - task: PowerShellOnTargetMachines@3 inputs: machines: '$(machines)' userName: '$(userName)' userPassword: '$(userPassword)' scriptType: 'inline' # inline by default inlineScript: | echo 'Hello !' communicationProtocol: http |
NuGet
- task: NuGetCommand@2 inputs: command: restore restoreSolution: MySolution.sln # relative path to a solution or project file |
Visual Studio Build task
- task: VSBuild@1 inputs: solution: MyProject\MyProject.csproj # relative path to a solution or project file platform: AnyCPU # options: Win32, x86, x64 or any cpu. For a project use AnyCPU configuration: release # options: debug or release clean: false # Set to false to make this an incremental build, it might reduce the build time. Make sure not to clean the repo too. msbuildArchitecture: x64 # options: x86 (default), x64 |
FileTransform
Replace tokens with variable values in XML or JSON configuration files.
- job: variables: Name1: Value1 # replace ... by Value1 <setting name="Name1"><value>...</value></setting> - task: FileTransform@1 inputs: folderPath: $(Pipeline.Workspace)\MyArtefact fileType: xml targetFiles: MyProject.exe.config |
MagicChunk
Modify a XML, JSON or YAML file.
- task: MagicChunks@2 inputs: sourcePath: $(System.DefaultWorkingDirectory)\Folder\App.config transformations: | { "root/node[@attribute1='value']/@attribute2": "true" } - task: MagicChunks@2 inputs: sourcePath: $(System.DefaultWorkingDirectory)\Folder\App.config transformationType: file transformationsFile: $(System.DefaultWorkingDirectory)\Folder\Transformations.json |
Transformations.json |
{ "root/node[@attribute1='value']/@attribute2": "true" } |
Pool
# if you use a private pool and don't need to specify demands pool: PoolName pool: name: PoolName demands: - myCustomCapability # check for existence of capability - agent.os -equals Darwin # check for specific string in capability |
Variables
# scope: root, stage, job variables: name1: 'value1' # name [\w\d._]+ name2: '${{ variables.name1 }} - value2' # reuse the value defined for name1 variables: - name: variable_name value: 'value' # groups are used to make variables inside that group available across multiple pipelines - group: group_name steps: - powershell: 'echo $(variable_name)' # pipeline variable - powershell: 'echo $(System.StageName)' # system variable - powershell: 'echo $(group_variable_name)' # variable in the group_name group variables - powershell: 'echo $env:VARIABLE_NAME' # environment variable - powershell: 'echo $(variable_name)' # macro syntax, processed during runtime before a task runs - powershell: 'echo ${{ variables.variable_name }}' # template expression syntax, processed at compile time, before runtime starts - powershell: 'echo $[variables.variable_name]' # Runtime expression syntax, processed during runtime, designed for use with conditions and expressions # Set a job-scoped variable from a script # the variable is available to downstream steps within the same job - powershell: echo "##vso[task.setvariable variable=variable_name]variable value" - powershell: echo $(variable_name) # Set a stage-scoped variable from a script jobs: - job: A steps: - powershell: echo "##vso[task.setvariable variable=variable_name;isOutput=true]variable value" name: task_name - powershell: echo $(task_name.variable_name) - job: B dependsOn: A variables: var_from_job_A: $[ dependencies.A.outputs['task_name.variable_name'] ] # expressions require single quotes # Set an inter-stage-scoped variable from a script stages: - stage: A jobs: - job: A1 steps: - powershell: echo "##vso[task.setvariable variable=variable_name;isOutput=true]variable value" name: task_name - stage: B dependsOn: A variables: var_from_stage_A: $[ stageDependencies.A.A1.outputs['task_name.variable_name'] ] |
Runtime parameters
Ces paramètres sont sélectionnable à chaque lancement de la pipeline.
parameters: - name: my_parameter displayName: My parameter type: string default: Value1 values: - Value1 - Value2 |
Repositories
By default current pipeline repo is checked out. |
resources: repositories: - repository: RepoId # A-Z, a-z, 0-9, and underscore name: ProjectName/RepoName # repository name (format depends on `type`) type: git ref: master steps: - checkout: self # checkout in $(Build.SourcesDirectory)\CurrentRepoId (C:\agent\_work\1\s\CurrentRepoId) - checkout: RepoId # checkout in $(Build.SourcesDirectory)\RepoId (C:\agent\_work\1\s\RepoId) |
|
Condition and dependency
It's as if you specified condition: succeeded() |
Condition | Description |
---|---|
succeeded() | Only when all previous dependencies have succeeded. This is the default if there is not a condition set in the YAML. |
succeededOrFailed() | Even if a previous dependency has failed, unless the run was canceled. |
always() | Even if a previous dependency has failed, even if the run was canceled. |
failed() | Only when a previous dependency has failed. |
# scope: stage, job, task condition: eq(variables.Var1, 'Value1') # parameter condition: eq('${{ parameters.Param1 }}', 'Value1') # and, or, eq, ne condition: or(eq(variables.Var1, 'Value1'), ne(variables.Var2, 'Value2')) # in condition: in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI') # with dependencies: wait Job1 and Job2 to run dependsOn: - Job1 - Job2 # test Job1 and Job2 have succeeded and test Var1 = Value1 condition: and(succeeded(), eq(variables.Var1, 'Value1')) # test Job2 has succeeded and test Var1 = Value1 condition: and(succeeded('Job2'), eq(variables.Var1, 'Value1')) # test Job1 and Job2 have succeeded or skipped condition: | and ( in(dependencies.Job1.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), in(dependencies.Job2.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') ) # stage dependency - stage: Stage2 # on Stage1 condition: in(dependencies.Stage1.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') condition: eq(dependencies.Stage1.result, '') # Stage1 has not been selected # on Stage1.Job1.Task1.Var1 output variable condition: and(succeeded(), eq(dependencies.Stage1.outputs['Job1.Task1.Var1'], 'true')) # job dependency jobs: - job: Job2 # on Stage1.Job1 condition: in(stageDependencies.Stage1.Job1.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') # on Stage1.Job1.Task1.Var1 output variable condition: eq(stageDependencies.Stage1.Job1.outputs['Task1.Var1'], 'true') # on current stage Job3 condition: in(dependencies.Job3.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') # on current stage Job3.Task1.Var1 output variable condition: eq(dependencies.Job3.outputs['Task1.Var1'], 'true') |
You can specify conditions under which a step, job, or stage will run. |
By default, each stage in a pipeline depends on the one just before it in the YAML file. |
if statement
# conditional insertion variables: ${{ if eq(variables['Build.SourceBranchName'], 'master') }}: var_name: value steps: - ${{ if eq(parameters.param_name, 'value') }}: - task: - task: inputs: ${{ if eq(variables['Build.SourceBranchName'], 'master') }}: input_name: 'value' |
Template
Insert a template
Reuse stages, jobs ans tasks.
stages-template.yml |
stages: - stage: Stage1 jobs: - job: Job1 steps: - script: echo 'stages template' |
jobs-template.yml |
jobs: - job: Job1 steps: - script: echo 'jobs template' |
tasks-template.yml |
steps: - script: echo 'tasks template' |
my-pipeline.yml |
stages: - template: stages-template.yml - stage: Stage2 jobs: - template: jobs-template.yml - stage: Stage3 jobs: - job: ExcecuteTasks steps: - template: tasks-template.yml |
Extend from a template
Copy the template in the pipeline.
my-template.yml |
resources: repositories: - repository: MyRepo type: git name: MyProject/MyRepo steps: - script: echo "My template" |
my-pipepline.yml |
extends: template: my-template.yml |
Parameters
tasks-template.yml |
parameters: parameterName: 'parameter value' steps: - script: echo ${{ parameters.parameterName}} |
my-pipepline.yml |
variables: var: 'value' steps: - template: tasks-template.yml parameters: parameterName: 'value' parameterName: ${{ variables.var }} # $(var) doesn't work |
Condition on a template
It is not possible to set a condition on a template. |
Solution 1: pass a parameter to the template.
steps-template.yml |
parameters: enabled: true steps: - script: echo 'Task 1' condition: ${{ parameters.enabled }} |
my-pipepline.yml |
steps: - template: steps-template.yml parameters: enabled: false |
Solution 2: use if.
my-pipepline.yml |
steps: - ${{ if eq($(MyVar), 'value') }}: - template: steps-template.yml |
Errors
Environment xxx could not be found
- Pipelines → Environments → Select the env xxx → 3 dots button on top right → Security
- Add the user with User role