Azure Devops - Run a task only if previous task has run successfully - azure-devops

I am currently writing a pipeline to deploy my infrastructure in Terraform.
I would like that some tasks do not run unless the first task has run successfully. I have found the use of conditions such as success() or failed().
However, upon reading closely, I realize that these conditions are based on Job Status, while in my case there is just one job containing all my tasks.
Is there any way to specify such condition ? And will it be able to refer to a specific task name ? (For example, Task C can run only if Task A ran with success).

You could add a PowerShell task just behind the first task to set a variable (ones for example) by using ##vso[task.setvariable variable=ones]true. Then, use this variable in condition for those tasks that you want them do not run unless the first task has run successfully.
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[task.setvariable variable=ones]true"
Then, set condition: condition: eq(variables.ones, 'true') for each task that you do not want it run unless the first task has run successfully. for example:
- task: PowerShell#2
displayName: task4
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host "Hello World"
condition: eq(variables.ones, 'true')
The PowerShell task will run if the previous tasks run successfully, in my case, there only is task1. Thus, if the task1 succeed, PowerShell task will set the variable value as true. Next tasks will run when the variable equal true. When the task1 failed, neither PowerShell task will run nor the next tasks.

Related

Azure Devops pipeline -> how to priorities one pipeline over another in build queue

we have only one agent and several pipelines.
Is it possible to set a rule so that in case of a queue, pipelien A will always run before pipeline B?
The situation:
Pipeline A is running, with 2 jobs:
Job 1 triggering pipeline B.
We want the agent to run Pipelien B before running Job 2 on pipeline A..
Thank you.
All the attempts are based on one agent.
Separate your Pipeline A's 2 jobs into 2 stages.
Using "Agentless job" Approvals and checks defined in the Variable Group to get the latest build for Pipeline B: https://learn.microsoft.com/en-us/rest/api/azure/devops/build/latest/get?view=azure-devops-rest-6.0
Trigger Pipeline B after Job 1 in Pipeline A.
Define the variable group in Stage 2:
- stage: Prod
variables:
- group: 1013
jobs:
- job: CheckBuildSuccess
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host "Hello World"
This check will start before stage 2 to check the latest build for pipeline B.
Check the test run result:

Azure DevOps. Reference Pipeline Settings in PowerShell

I'd like to reference a user who ran pipeline and indicate that a previous specific task in multi-stage pipeline ran successfully or not in a PowerShell script. How can I do that?
Something like:
Write-Host $env:UserThatRanPipeline $env:Task:BuildApp1:SuccessOrFail
So I'd get output:
John Smith Success
I'd like to reference a user who ran pipeline and indicate that a
previous specific task in multi-stage pipeline ran successfully or not
in a PowerShell script.
1.Just as Shayki Abramczyk suggests above, you can use Build.RequestedFor to output the user who runs the pipeline. See predefined variables, you can use something like: Write-Host $(Build.RequestedFor)
2.To get status of your AzureRmWebAppDeployment#4 task, for now there's no predefined variable available to do that job. So you have to do that with some logic...
As a workaround:
You can set one variable SuccessOrFail: 'Succeed' like this in yml:
variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
SuccessOrFail: 'Succeed'
And then add one powershell task right after your AzureRmWebAppDeployment#4 task:
- task: PowerShell#2
condition: failed()
inputs:
targetType: 'inline'
script: |
# This script will run only when any previous task failed
echo "##vso[task.setvariable variable=SuccessOrFail]Fail"
3.Make sure there's no custom condition set for your AzureRmWebAppDeployment#4 task. As I know this task is not a independent task, so it will run when all previous tasks succeed.
To sum up:
This ps script will run when AzureRmWebAppDeployment#4 task failed or skipped, and it will reset the value of SuccessOrFail to Fail. So if your AzureRmWebAppDeployment#4 succeeds, the value of $(SuccessOrFail) is Succeed, if it fails or skips, the value would be Fail.
Now the value Succeed represents the task should certainly succeed, and if the value is Fail, it actually represents your task is NotSucceed(Fail+Skip).
The order of your tasks should be: other tasks =>AzureRmWebAppDeployment#4=> PS task above=> other tasks => Your own Powershell Task.

Lock resources between multiple builds that run parallel in Azure DevOps

Suppose I have a build:
Job1:
Task1: Build
Job2:
dependsOn: Job1
Task2: Test
And the test task uses some kind of database, or another unique resource.
I would like to know if it is possible, when multiple builds are running in parallel, to lock Job2 to run unique without other builds trying to access the same resource.
I am using cmake and ctest, so I know I can do something similar between separate unit tests with RESOURCE_LOCK, but I am certain that I will not be able to lock that resource between multiple ctest processes.
Agree with #MarTin's work around. Set one variable with powershell task in Job1, then get this variable and use it in job condition for Job2.
You don't need to use API to add global variable. There has another easier way can for you try: Output variables. We expand one feature that customer can configure one output variable and access this output variable in the next job which is depending on the first job.
The sample of set output variable in Job1:
##vso[task.setvariable variable=firstVar;isOutput=true]Job2 Need skip
Then get the output variable from Job1 in Job2:
Job2Var: $[dependencies.Job1.outputs['outputVars.firstVar']]
Then, in job2, you can use it into job condition:
condition: eq(dependencies.Job1.outputs['outputVars.firstVar'], 'Job2 Need skip')
The completed simple sample script look like this:
jobs:
- job: Job1
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: 'echo "##vso[task.setvariable variable=firstVar;isOutput=true]Need skip Job2"'
name: outputVars
- job: Job2
dependsOn: Job1
variables:
Job2Var: $[dependencies.Job1.outputs['outputVars.firstVar'], 'Need skip Job2']
steps:
...
...
The logic I want to express is dynamically assign values to output variable based on Job1 and the current pipeline execution state. One specific value represent that the Job2 should be locked, which means skip its execution. In Job2's condition expression, when the obtained value $[dependencies.Job1.outputs['outputVars.firstVar'] satisfies the predefined expected value, skip current Job2.

Continue build after script fails in Azure DevOps

In my Azure DevOps build task I run a Cypress test. If the test fails the build is canceled. But I want to run another task after Cypress the publishes the test results.
I've tried it with this task in my pipeline.yml file:
- task: PowerShell#2
inputs:
targetType: "inline"
script: "yarn test:cypress"
errorActionPreference: "continue"
displayName: "start server and run cypress"
But this doesn't seem to have any effect.
I've tried add -ErrorAction 'Continue' to to script"
"start": "npm-run-all -s build:shared-web run:shell",
"cy:run": "cypress run -ErrorAction 'Continue'",
"test:cypress": "start-server-and-test start http://localhost:3000 cy:run"
But this fails with:
error: unknown option: -E
It looks like Cypress is seeing the ErrorAction as a Cypress parameter.
So what's the correct way of continuing a build if a task fails?
You can add to the task this:
continueOnError: true
Now the build will keep running even the tests will fail.
If you want to fail the build if the tests failed but you want to run only one task to publish the results, you can add this to the publish tests task:
condition: always()
Now the publish task will be running always, even the tests are failed and the build canceled/failed.

Passing value from PowerShell script task (variable) into subsequent task within the same agent job

I am following this link to set a variable in a task such that it can be used in another task in the same agent job.
In a PowerShell script task I am using the foll. line to set variable:
Write-Host "##vso[task.setvariable variable=sauce]crushed tomatoes"
The next section on the link shows how to read variable - it has got arguments and script. Where do I have to enter the arguments? Is it into another powershell task? This next part suggests that I also need to set isOutput=true when the variable needs to be used by another task - https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=classic%2Cbatch#using-variables-as-task-inputs
I am confused between accessing the variable set in above step. If I want to fetch the value in another PowerShell task or if I want to pass the value to another non-powershell task, then should I use $(sauce) or $env:SAUCE to fetch/send the value?
Yes, you can read the variable with another PowerShell task, the simple way is:
For inline script:
Write-Host $(sauce)
For file script:
Write-Host $env:sauce
You don't need to add the isOutput=true.
My YAML:
steps:
- task: PowerShell#2
displayName: 'Set var'
inputs:
targetType: filePath
filePath: ./test.ps1
- powershell: |
Write-Host $(sauce)
displayName: 'Read inline'
- task: PowerShell#2
displayName: 'Read from file'
inputs:
targetType: filePath
filePath: ./read.ps1
The file test.ps1 is:
The file read.pd1 is:
The build output is: