Azure DevOps YAML stage template - azure-devops

I have two environments, preprod and prod and they are pretty much the same.
So I created an yaml file, InfurstructureTemplate.yaml
parameters:
xxxx
jobs:
- job: provision_job
I want to use this template for my two environments, here is what in mind:
stages:
- stage: PreProd Environment
- template: InfurstructureTemplate.yaml
- parameters:
xxxx
- stage: Prod Environment
- template: InfurstructureTemplate.yaml
- parameters:
xxxx
Is this the right way to use yaml template? When I googled this, seems template is on Stages level and you can't put it on stage.

Yes, you can do it very similar, put the template in the jobs:
stages:
- stage: PreProd_Environment
displayName: PreProd Environment
jobs:
- template: InfurstructureTemplate.yaml
parameters:
projectDir: xxx
- stage: Prod_Environment
displayName: Prod Environment
dependsOn: [ PreProd_Environment ]
jobs:
- template: InfurstructureTemplate.yaml
parameters:
projectDir: xxx

You may try this too as described here
stages:
- template: InfurstructureTemplate.yaml
parameters:
xxxx
- template: InfurstructureTemplate.yaml
parameters:
xxxx

Related

Decrease the number of stages by making them into jobs

I tried to create the below yaml pipeline config file. Can I get some help on reducing the number of stages in YAML pipeline. This is to reduce number of stages per domain.
name: '$(Date:yyyy.MM.dd)$(Rev:.rr)'
trigger:
branches:
include:
- master
- features/*
pool:
name: CustomPool
stages:
- template: templates\build.yaml
- template: templates\deploy.yaml
parameters:
Environment: 'dev'
IsEnabled: true
Domain: 'domainX'
ServerList:
- name: ServerX
restartIIS: true
- template: templates\deploy.yaml
parameters:
Environment: 'test'
IsEnabled: true
Domain: 'domainY'
ServerList:
- name: ServerY
restartIIS: false
Scenario 1: If you don't want to use stages, you can only use jobs in the main YAML and your template. There is a demo you can refer to.
azure-pipelines.yml
trigger:
- none
pool:
vmImage: ubuntu-latest
jobs:
- template: JobTemplate1.yml
- template: JobTemplate2.yml
- template: JobTemplate3.yml
JobTemplate1.yml
jobs:
- job: job1_1
steps:
- script: echo This is job1_1
- job: job1_2
steps:
- script: echo This is job1_2
In this example, each template has 2 jobs. Eventually you can see a total of 6 jobs running.
Scenario 2: If you want to use stages in your main YAML but just want to decrease the stages in your template, you can use only one stage and several jobs in your template.
azure-pipelines.yml
trigger:
- none
pool:
vmImage: ubuntu-latest
stages:
- template: template1.yml
- template: template2.yml
- template: template3.yml
template1.yml
stages:
- stage: Template1_Stage
jobs:
- job: Template1_Stage_job1
steps:
- script: echo This is Template1_Stage_job1
- job: Template1_Stage_job2
steps:
- script: echo This is Template1_Stage_job2
In this example, template1 has one stage and two jobs. Template2 has two stages, and each stage has one job. Template3 has one stage and one job. For your case, you can refer to template1.

doing a task after a looping YAML template-ized azure devOps pipeline

I have a YAML Azure DevOps pipeline that loops through series of configurations, copying artifacts to various places. What I want to do is, after the looping is done, to do something else (I'd like to send an email, but the question is more general than that).
But I can't insert anything after the looping part of the YAML, at least not with any of the experiments I've tried. Here's the YAML that calls the YAML template, with a comment for where I'd like to do another step. How might I do this?
parameters:
- name: configuration
type: object
default:
- Texas
- Japan
- Russia
- Spaghetti
- Philosophy
trigger:
- dev
- master
resources:
repositories:
- repository: templates
name: BuildTemplates
type: git
stages:
- ${{ each configuration in parameters.configuration }}:
- template: build.yml#templates
parameters:
configuration: ${{ configuration }}
appName: all
# Where I'd like to have another task or job or step or stage that can send an email or perhaps other things
Just define a new stage:
stages:
- ${{ each configuration in parameters.configuration }}:
- template: build.yml#templates
parameters:
configuration: ${{ configuration }}
appName: all
- stage: secondStage
jobs:
- job: jobOne
steps:
- task: PowerShell#2

Azure Devops pipeline yml looping over stages

How can i loop over an array or through an object to create stages?
Below is a yml file that works. You can see the build stage loops over the parameters environments for jobs. IS it possible to achieve the same thing for the publishing stages?
The publishing stages require manual approval, must run in order and only when the previous stage is successfully complete?
parameters:
- name: 'environments'
type: object
default:
- environment: development
variableGroup: strata2-admin-spa-vg
dependsOn: 'build'
- environment: test
variableGroup: strata2-test-admin-spa-vg
dependsOn: 'development'
- environment: production
variableGroup: strata2-development-variables
dependsOn: 'development'
- name: 'buildTemplate'
type: string
default: buildTemplate.yml
- name: 'publishTemplate'
type: string
default: publishTemplate.yml
trigger:
- main
pool:
vmImage: ubuntu-latest
stages:
- stage: build
displayName: Build stage
jobs:
# Can I do this for stages?
- ${{each build in parameters.environments}}:
- template: ${{parameters.buildTemplate}}
parameters:
environment: ${{build.environment}}
variableGroup: ${{build.variableGroup}}
# How to loop over parameters.environments to dynamically create stages
- stage: Publish_Development
displayName: Publish development environment
dependsOn: build
jobs:
- template: ${{parameters.publishTemplate}}
parameters:
environment: Development_websites
variableGroup: strata2-admin-spa-vg
- stage: Publish_Test
displayName: Publish test environment
dependsOn: Publish_Dev
jobs:
- template: ${{parameters.publishTemplate}}
parameters:
environment: Test_websites
variableGroup: strata2-test-admin-spa-vg
- stage: Publish_Production
displayName: Publish production environment
dependsOn: Publish_Test
jobs:
- template: ${{parameters.publishTemplate}}
parameters:
environment: Production_websites
variableGroup: strata2-development-variables
You can create a stages object the same way you created the environments object.
stages:
Publish_Development:
- stage: Publish_Development
- displayName: Publish development environment
- dependsOn:
- ...
Publish_Test
- stage: Publish_Development
- ...
Then you can loop over the stages object like you did with environments.
- ${{each stage in parameters.stages}}:
- stage: ${{ stage.stage }}
displayName: ${{ stage.displayName}}
dependsOn: ${{ stage.dependsOn}}
...
Managed to get this working for myself. Stages automatically generated based on numerical batch numbers, that run in parallel. Hope it helps someone out there.
- name: batches
displayName: BATCH
type: object
default:
- 1
- 2
- 3
stages:
- ${{ each stage in parameters.batches }}:
- stage: BATCH_${{ stage }}
dependsOn: []
jobs:
- job: PREP
steps:
- template: install.yml
- job: RUN
dependsOn: PREP
timeoutInMinutes: 300
steps:
- template: run.yml
parameters:
batch: ${{ stage }}
Would be nice if the batch numbers weren't displayed as an editable box when running the pipeline from Azure DevOps. I tried setting them as fixed values, but couldn't get that to work, so this is what I went with in the end.

Why can't I use a variable to define the environment property in the Azure Pipeline YAML config file?

I'm trying to create a deploy pipeline YAML template for all environments/stages. I've set up the Environments on Azure DevOps so that I can add checks and approvals on the Test and Prod environments before they get deployed. I've set up a library group for each stage and each one of them has a variable called 'env' which defines the current stage running in the pipeline. For some reason, the environment property under the deployment job (see code snippet below) doesn't read that variable.
Has anyone faced this issue before, or is there a reason why the variable won't be read for that specific property?
Note: I've tested the variables and they do work, for example, the stage property outputs as 'deploy-dev/test/prod' (depending on the environment)
- stage: deploy-$(env)
jobs:
- deployment: DeployWeb
displayName: deploy Web App
pool:
vmImage: 'Ubuntu-latest'
# creates an environment if it doesn't exist
environment: 'smarthotel-$(env)'
strategy:
runOnce:
deploy:
steps:
- script: echo Hello world
You can't do this because it have to be know at compilation phase.
But you can try this (lets name this file deploy.yml):
parameters:
- name: env
type: string
default: 'dev'
stages:
- stage: deploy-${{ parameters.env }}
jobs:
- deployment: DeployWeb
displayName: deploy Web App
pool:
vmImage: 'Ubuntu-latest'
# creates an environment if it doesn't exist
environment: 'smarthotel-${{ parameters.env }}'
strategy:
runOnce:
deploy:
steps:
- script: echo Hello world
and then you need to run as follows (in build.yml file):
stages:
- template: deploy.yml
parameters:
env: dev
- template: deploy.yml
parameters:
env: qa
- template: deploy.yml
parameters:
env: prod

Create job dependency dynamically between jobs

I'm trying to figure how to dynamically create a dependency and run the job based on the condition.
Here is the structure of my pipeline:
main.yaml:
stages:
- stage: build
jobs:
- template: build.yaml
- stage: deployDev
dependsOn: build
jobs:
- template: deployApp1.yaml
parameters:
environmentName: Dev
- template: deployApp2.yaml
parameters:
environmentName: Dev
- stage: deployQA
dependsOn: deployDev
jobs:
- template: promote.yaml
parameters:
environmentName: QA
- template: deployApp1.yaml
parameters:
environmentName: QA
- template: deployApp2.yaml
parameters:
environmentName: QA
promote.yaml
jobs:
- job: copy
steps:
- task:
deployApp1.yaml
jobs:
-job: deployApp1
steps:
- task:
deployApp2.yaml
jobs:
- job: deployApp2
steps:
- task:
In deployQA i have a separate job which copies the build artifacts and the next two jobs (deployApp1 and deployApp2) will fail without the copy step in deployQA.
I would like to create a conditional dependency on job: copy for job: deployApp1 so that it should be able to skip if i'm deploying to Dev which doesn't have this dependency. I already tried different solutions from different posts without any luck.
I know if i can add additional stage for the copy that would solve my problem but i would like to have the copy as part of the QA stage.
You want deployApp1 to depend on copy when running in stage deployQA and not depend on anything when running in stage deployDev?
You could add a dependsOn parameter to your template and use it to control job's dependencies:
stages:
- stage: build
jobs:
- template: build.yaml
- stage: deployDev
dependsOn: build
jobs:
- template: deployApp1.yaml
parameters:
environmentName: Dev
- template: deployApp2.yaml
parameters:
environmentName: Dev
- stage: deployQA
dependsOn: deployDev
jobs:
- template: promote.yaml
parameters:
environmentName: QA
- template: deployApp1.yaml
parameters:
environmentName: QA
dependsOn: copy
- template: deployApp2.yaml
parameters:
environmentName: QA
dependsOn: copy
# promote.yaml
jobs:
- job: copy
steps:
- task:
# deployApp1.yaml
parameters:
- name: environmentName
- name: dependsOn
default: []
jobs:
- job: deployApp1
dependsOn: ${{ parameters.dependsOn }}
steps:
- task:
# deployApp2.yaml
parameters:
- name: environmentName
- name: dependsOn
default: []
jobs:
- job: deployApp2
dependsOn: ${{ parameters.dependsOn }}
steps:
- task:
I was able to figure out the solution for my scenario from below post however to be able to achieve the answer to my specific use-case i had to set the makeExplicitDependency parameter to false.
${{ if eq(parameters.makeExplicitDependency, true) }}:
dependsOn: Test
thanks to below post:
How to dynamically reference previous jobs in Azure Pipelines if there are any in the current stage