Azure pipelines running steps inside service containers - azure-devops

Follow on question from a previous question about targeting containers in Azure pipelines
I am trying to use a playwright container in an Azure pipeline to access the default installed browsers in the image
My main 'azure-pipelines.yml' looks like this
trigger: none
pr: none
pool:
vmImage: ubuntu-latest
resources:
containers:
- container: playwright
image: mcr.microsoft.com/playwright:v1.30.0-focal
- container: pwsh
image: mcr.microsoft.com/powershell
stages:
- stage: dev
displayName: dev
jobs:
- template: templates/test.yml
And my 'templates.yml' looks like this
jobs:
- job: run_tests
displayName: Test
pool:
vmImage: ubuntu-latest
services:
playwright: playwright
pwsh: pwsh
steps:
- powershell: |
Write-Host "This is powershell"
target:
container: pwsh
- script: yarn test:integration:ci
displayName: "Run tests"
env:
environment: dev
CI: true
target:
container: playwright
But when I run the pipeline, the playwright part does not seem to be working?
Running 50 tests using 1 worker
FFFFF
1) [chromium] › alternativeJourneys.spec.ts:24:5 › Register interest =============================
browserType.launch: Executable doesn't exist at /home/vsts/.cache/ms-playwright/chromium-1045/chrome-linux/chrome
╔═════════════════════════════════════════════════════════════════════════╗
║ Looks like Playwright Test or Playwright was just installed or updated. ║
║ Please run the following command to download new browsers: ║
║ ║
║ npx playwright install ║
║ ║
║ <3 Playwright Team ║
╚═════════════════════════════════════════════════════════════════════════╝
I have pulled the playwright:v1.30.0-focal image locally and verified that the path mentioned
/ms-playwright/chromium-1045/chrome-linux/chrome
does exist. So am wondering if that /home/vsts/.cache prefix means this is not running inside the container?
My yarn.lock and package.json versions also match the 1.30.0 version of the image I am pulling.
I am wondering if my syntax of target: is the correct way to make this script run in that container?
If I modify the yaml to this to try to make the whole thing run in the playwright container, then the powershell command fails, again, as I am unsure if my target: syntax is the correct way to go?
- job: run_tests
displayName: Test
pool:
vmImage: ubuntu-latest
container: mcr.microsoft.com/playwright:v1.30.0-focal
services:
playwright: playwright
pwsh: pwsh
steps:
- powershell: |
Write-Host "This is powershell"
target:
container: pwsh
- script: yarn test:integration:ci
displayName: "Run tests"
env:
environment: dev
CI: true
target:
container: playwright
Is what I am attempting possible and I just have wrong syntax? Or am I approaching this in the wrong way?
Appreciate any insight, not a massive amount of hands on with container of Azure pipelines
Many thanks
=============================================================
New info:
It looks like the same hostname for each step
- script: |
echo "Powershell hostname $HOSTNAME"
target:
container: pwsh
- script: |
echo "Playwright hostname $HOSTNAME"
target:
container: playwright
Yields
Powershell hostname fv-az461-670
and
Playwright hostname fv-az461-670
respectively
fv-az461-670 is the the hostname of the agent host
I don't think I have got this quite right?

Found this
https://github.com/microsoft/azure-pipelines-yaml/blob/master/design/step-target.md
Which had a clearer example of using service containers. Showed my syntax was wrong
Adjusted my template to this and the pipeline worked
jobs:
- job:
displayName: Test
pool:
vmImage: ubuntu-latest
services:
playwright:
image: mcr.microsoft.com/playwright:v1.30.0-focal
pwsh:
image: mcr.microsoft.com/powershell
steps:
- powershell: |
Write-Host "Powershell"
target:
container: pwsh
- script: yarn test:integration:ci
displayName: "Run tests"
env:
environment: dev
CI: true
target:
container: playwright
Thank you

Related

Using service containers in Azure DevOps pipelines

I'm trying to use service containers within Azure DevOps pipelines
The agent is an ubuntu host
I would like to have the agent run a powershell container and a playwright container
The doc for this is not very verbose
So far I have this in my main 'azure-pipelines.yml'
trigger: none
pr: none
resources:
containers:
- container: playwright
image: mcr.microsoft.com/playwright:v1.29.0-focal
- container: pwsh
image: mcr.microsoft.com/powershell
pool:
vmImage: "ubuntu-latest"
services:
playwright: playwright
pwsh: pwsh
stages:
- stage: dev
displayName: dev
jobs:
- template: templates/test.yml
And this in my 'template/test.yml' file
- job: run_tests
displayName: Test
pool:
vmImage: ubuntu-latest
steps:
- powershell: |
Write-Host "This is powershell"
target:
container: pwsh
- script: yarn test:integration:ci
displayName: "Run tests"
env:
environment: dev
CI: true
target:
container: playwright
Azure pipelines does not like this. It is failing with:
/.azure/azure-pipelines.yml (Line: 18, Col: 1): Unexpected value 'stages'
when I try to run the pipeline. I thought stages: was the first part of a pipeline? (but I am very new to Azure pipelines so my understanding might be way off)
Could anyone help to clarify why/where I am screwing up at all please?
Thanks
Make the following changes to your yaml files.
azure-pipelines.yml
trigger: none
pr: none
pool:
vmImage: ubuntu-latest
resources:
containers:
- container: playwright
image: mcr.microsoft.com/playwright:v1.29.0-focal
- container: pwsh
image: mcr.microsoft.com/powershell
stages:
- stage: dev
displayName: dev
jobs:
- template: templates/test.yml
template.yml
jobs:
- job: run_tests
displayName: Test
pool:
vmImage: ubuntu-latest
services:
playwright: playwright
pwsh: pwsh
steps:
- powershell: |
Write-Host "This is powershell"
target:
container: pwsh
- script: yarn test:integration:ci
displayName: "Run tests"
env:
environment: dev
CI: true
target:
container: playwright
Reason why you were getting the error (/.azure/azure-pipelines.yml (Line: 18, Col: 1): Unexpected value 'stages') is because of the property services. According to the example in service containers documentation, the property services is defined in the root level of the yaml because the example did not use any stage or jobs.
Since you are using stages and jobs in your yaml pipeline, the services property should be nested within your job.
Hence, I have moved the services to the template.yml file. You can check which property is allowed under a stage or job using this YAML schema documentation
Reference: https://learn.microsoft.com/en-us/azure/devops/pipelines/yaml-schema/jobs-job-container?view=azure-pipelines

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

Azure DevOps Pipeline define variable in deployment and reuse in subsequent job

I'm using an Azure DevOps pipeline to deploy my code and now I'm in need of passing a variable value from a deployment job to a subsequent job that depends on it. I've read up on this example but it does not seem to work at all.
What I'm trying to do is run an Azure ARM Deployment that provisions a Key Vault. The name of the key vault is outputted from the ARM deployment job and I'm then trying to pass that name to another job which needs to add specific secrets. Access control is taken care of, but I still need to pass the name.
I've boiled the problem down to the basics of passing a variable from a deployment to a job. Here is my complete test pipeline (almost entirely copied from here):
trigger: none
stages:
- stage: X
jobs:
- deployment: A
pool:
vmImage: "ubuntu-16.04"
environment: test
strategy:
runOnce:
deploy:
steps:
- script: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the deployment variable value"
name: setvarStep
- script: echo $(setvarStep.myOutputVar)
name: echovar
- job: B
dependsOn: A
pool:
vmImage: "ubuntu-16.04"
variables:
myVarFromDeploymentJob: $[ dependencies.A.outputs['deploy.setvarStep.myOutputVar'] ]
steps:
- script: "echo $(myVarFromDeploymentJob)"
name: echovar
Once I run this the echoed value is blank in job B, but defined in deployment A. Why is this? And is there a way to dum everything in dependencies.A.outputs so that I can see what I have to work with?
How can I pass a variable from a runOnce deployment job to a regular job?
I've solved it. The problem is that the documentation here specifies this schema for fetching the variable for a runOnce deployment:
$[dependencies.<job-name>.outputs['<lifecycle-hookname>.<step-name>.<variable-name>']]
This is in fact WRONG. The <lifecycle-hookname> parameter should be replaced with the name of the deployment like this:
$[dependencies.<job-name>.outputs['<job-name>.<step-name>.<variable-name>']]
The example from this documentation (scroll down a bit) is correct.
A full example pipeline that I've tested and works:
trigger: none
stages:
- stage: X
jobs:
- deployment: A # This name is important
pool:
vmImage: 'ubuntu-16.04'
environment: staging
strategy:
runOnce:
deploy:
steps:
- script: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the deployment variable value"
name: setvarStep # This name is also important
- script: echo $(setvarStep.myOutputVar)
name: echovar
- job: B
dependsOn: A
pool:
vmImage: 'ubuntu-16.04'
variables:
myVarFromDeploymentJob: $[ dependencies.A.outputs['A.setvarStep.myOutputVar'] ]
steps:
- script: "echo $(myVarFromDeploymentJob)"
name: echovar

Can't get a deployment job output variable to pass to another deployment job

I am trying to use Azure DevOps to configure a docker swarm cluster, with an environment containing 3 RHEL7 vm's with Docker installed and one of them being configured as the swarm host.
Here is the yaml file for the pipeline:
jobs:
- deployment: MasterNode
strategy:
runOnce:
deploy:
steps:
- bash: |
SWARMTOKEN=$(docker swarm join-token manager -q)
echo "##vso[task.setvariable variable=tokenswarm;isOutput=true]$SWARMTOKEN"
name: setvar
- script: echo $(setvar.tokenswarm)
name: echovar
environment:
name: swarm
resourceType: VirtualMachine
tags: SwarmNodeMaster
- deployment: SwarmNode
dependsOn: MasterNode
variables:
tokenvar: $[ dependencies.MasterNode.outputs['deploy.setvar.tokenswarm'] ]
strategy:
runOnce:
deploy:
steps:
- bash: |
echo $(tokenvar)
environment:
name: swarm
resourceType: VirtualMachine
tags: SwarmNode
I have logged this over at VSD https://developercommunity.visualstudio.com/content/problem/937451/unable-to-share-variable-from-one-deployment-job-t.html
I have tried setting the second deployment job to a normal job as per the syntax at https://learn.microsoft.com/en-us/azure/devops/release-notes/2020/sprint-164-update#support-for-output-variables-in-a-deployment-job
jobs:
- deployment: masternode
strategy:
runOnce:
deploy:
steps:
- script: |
SWARMTOKEN="Docker GUID"
echo "##vso[task.setvariable variable=token;isOutput=true]$SWARMTOKEN"
name: 'setvar'
- script: echo $(setvar.token)
name: echovar
environment:
name: swarm
resourceType: VirtualMachine
tags: SwarmNodeMaster
- job: 'swarmnode'
dependsOn: 'masternode'
variables:
tokenvar: $[ dependencies.masternode.outputs['deploy.setvar.token'] ]
steps:
- script: echo $(tokenvar)
name: echovar
It seems whatever I try I can't get the variable to expand in the next deployment step.
Thanks in advance for any help!
UPDATE:
#Kontekst thanks for sharing your working yaml, using that i've managed to track it down to defining the environment for the "master" node:
environment:
name: swarm
resourceType: VirtualMachine
tags: SwarmNodeMaster
The swarm master node has the tag "SwarmNodeMaster" and is part of the same environment as the 2 other VMs which have the tag "SwarmNode" which is used in the second step if I change the above to just environment: 'swarm' I can pass a variable to the next step, but again stops working if I try and target the master node...
Here is the yaml that successfully passes a variable to the next deployment job:
https://hastebin.com/gudelokufi.bash
My main problem is that I need to get the token from the swarm host to the swarm nodes, but when I try and pass a variable from the deployment step that targets the swarm host, to the deployment job that targets the swarm nodes, the variable cannot be expanded in the second deployment job...
This is what I want to work, but seems to break the output variable: https://hastebin.com/yocepowopu.bash
So after much trial and error I found that when you use environment tags as part of a deployment job, it appends the job name with the environment resource name, followed by the lifecycle hook. This is the working code:
stages:
- stage: MyStage
jobs:
- deployment: masterNode
displayName: AnyDeploy
pool:
vmImage: 'ubuntu-latest'
environment:
name: swarm
resourceType: virtualmachine
tags: swarmnodemaster
strategy:
runOnce:
deploy:
steps:
- task: Bash#3
displayName: 'Setting output variable'
inputs:
targetType: 'inline'
script: |
token=Some_Value
echo "##vso[task.setvariable variable=token;isOutput=true]$token"
echo $token
name: setvarStep
- task: Bash#3
inputs:
targetType: 'inline'
script: 'env | sort'
- deployment: swarmNode
dependsOn: masterNode
pool:
vmImage: 'ubuntu-latest'
environment:
name: swarm
resourceType: virtualmachine
tags: swarmnode
variables:
myToken: $[ dependencies.masterNode.outputs['masterNode_<resource name>_Deploy.setvarStep.token'] ]
strategy:
runOnce:
deploy:
steps:
- task: Bash#3
displayName: 'Checking if output variable was passed'
inputs:
targetType: 'inline'
script: |
echo My docker token = $(myToken)
I haven't found a way to reference the job name as a variable yet, as the value changes with each job, but the system variable is "SYSTEM_JOBNAME"

Azure devops container jobs login issues with multiple jobs

I am running a server with 10 azure devops agents. I have created a build that has 5 jobs and once in awhile we get an error initialize the container for a job. The image is already on the server so it doesn't need to download the image but as you can see the below log it fails to login
View raw log
'1.40'
Docker daemon API version: '1.40'
C:\Program Files\Docker\docker.EXE version --format '{{.Client.APIVersion}}'
'1.40'
Docker client API version: '1.40'
C:\Program Files\Docker\docker.EXE ps --all --quiet --no-trunc --filter "label=413526"
C:\Program Files\Docker\docker.EXE network prune --force --filter "label=413526"
C:\Program Files\Docker\docker.EXE login --username "***" --password *** https://***
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in C:\Users\devagent\.docker\config.json.
Configure a credential helper to remove this warning. See
Login Succeeded
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
C:\Program Files\Docker\docker.EXE pull ***/builds/vs2017:1.0.0.0
Error response from daemon: Get https://***/v2/builds/vs2017/manifests/1.0.0.0: unauthorized: authentication required
##[warning]Docker pull failed with exit code 1, back off 3.597 seconds before retry.
C:\Program Files\Docker\docker.EXE pull ***/builds/vs2017:1.0.0.0
Error response from daemon: Get https://***/v2/builds/vs2017/manifests/1.0.0.0: unauthorized: authentication required
##[warning]Docker pull failed with exit code 1, back off 3.068 seconds before retry.
C:\Program Files\Docker\docker.EXE pull ***/builds/vs2017:1.0.0.0
Error response from daemon: Get https://***/v2/builds/vs2017/manifests/1.0.0.0: unauthorized: authentication required
C:\Program Files\Docker\docker.EXE logout https://***
Not logged in to ***
##[error]Docker pull failed with exit code 1
Finishing
Yaml Build
variables:
application.Name: 'Product'
application.version: '5.12.0.0'
name: '$(application.name)_$(application.version)_$(Date:yyyMMdd)$(Rev:.rr)'
resources:
- repo: self
clean: true
schedules:
- cron: "0 8 * * Mon-Fri"
displayName: Nightly Build
branches:
include:
- master
- release/*/base
stages:
- stage: CI
displayName: 'Continuous Integration'
condition: |
or(
in(variables['Build.Reason'], 'PullRequest'),
and(
in(variables['Build.Reason'], 'Manual'),
eq(variables['ManualCI'], 'true')
)
)
jobs:
- job: ProductCI
displayName: Product
condition: succeeded()
pool:
name: DW
workspace:
clean: all
timeoutInMinutes: 120
steps:
- template: templates/product-buildsteps.yml
- template: templates/product-api-buildsteps.yml
- job: AutomationCI
displayName: Automation
condition: succeeded()
workspace:
clean: all
pool:
name: DW
container:
image: AzureContainerRepo/builds/vs2017:1.0.0.0
endpoint: Azure Container Builds
steps:
- template: templates/product-automation-buildsteps.yml
- job: FluentMigratorCI
displayName: FluentMigrator
condition: succeeded()
workspace:
clean: all
pool:
name: DW
container:
image: AzureContainerRepo/builds/vs2017:1.0.0.0
endpoint: Azure Container Builds
steps:
- template: templates/product-fm-buildsteps.yml
- job: DeploymentCheckerCI
displayName: Deployment Checker
condition: succeeded()
pool:
name: DW
container:
image: AzureContainerRepo/builds/vs2017:1.0.0.0
endpoint: Azure Container Builds
steps:
- template: templates/product-deploymentchecker-buildsteps.yml