Post cancellation task in Azure Pipelines - azure-devops

We have a scenario where once we manually cancel a pipeline in Azure DevOps, we need to terminate a particular process (exe). We wanted to know how can a task be triggered in YAML post cancellation, to achieve this.

Please try with the following ways:
If there are multiple jobs in your pipeline, make sure the job that runs the task to terminate the particular process (exe) is processed after all other jobs have completed processing (Succeeded, Failed or Canceled). You can use the 'dependsOn' key to set the execution order of the jobs. For more details, see "Dependencies".
Then, as #ShaykiAbramczyk mentioned, on the job that terminates the particular process (exe), you can use the 'condition' key to specify the condition under which the job runs. For more details, see "Conditions".
jobs:
. . .
- job: string
dependsOn: string
condition: eq(variables['Agent.JobStatus'], 'Canceled')
If there is only one job in your pipeline, make sure the task to terminate the particular process (exe) is the last step in the job. You need to put this task to the bottom of the steps list of this job.
Then also need to specify the condition on the task to terminate the particular process (exe).
If using the 'condition' key on this step, this step will be always listed and display in the job run, regardless of whether it is skipped or not.
steps:
- step: string
condition: eq(variables['Agent.JobStatus'], 'Canceled')
If using the 'if' statement on the step, this step will be listed and display in the job run only when the 'if' condition is met and to run this step. If the condition is not met and the step is skipped, this step will be hidden in the job run.
steps:
- ${{ if eq(variables['Agent.JobStatus'], 'Canceled') }}:
- step: string

You can add the step that terminate the process, and configure him to run only if the pipeline is canceled - with custom condition:
condition: eq(variables['Agent.JobStatus'], 'Canceled')

Related

Azure Devops Release Pipeline - Run this job Custom Condition when certain stages succeed

I have a release pipeline in Azure which "Deploys Website" and another stage which "Updates Azure". The next stage runs a "Smoke Test" and run jobs is set to "only when all previous jobs have succeeded".
I want to create a new stage after the smoke test to run a regression test stage - only when "Deploy Website" and "Update Azure" both succeed i.e. it doesnt matter if "Run Smoke Tests" succeeds or fails.
In the agent job of the new stage I think I need set Run this job to "Custom condition using variable expressions" and then set a Variable Expression.
I cant figure out the variable condition to put in the custom field for? - only when "Deploy Website" and "Update Azure" both succeed.
Is there a way of accessing the yaml code for the "Agent job"?
You can do this by adding the regression test stage, setting the pre-deployment conditions for this stage as after the smoke test and selecting Trigger even when the selected stages partially succeed.
Within the tasks of the smoke test, under control options enable continue on error. This causes the smoke tests to register as partial success despite the errors and ensures your regressions tests will run regardless of the outcome of smoke test
You can't do that in Classic releases, but it can be done in YAML:
stages:
- stage: A
# stage B runs if A fails
- stage: B
condition: failed()
# stage C runs if B succeeds
- stage: C
dependsOn:
- A
- B
condition: succeeded('B')
You may be able to hack together a REST based release gate though.

azure devops: How to end a build successfully with warnings when a step fails

When a certain step in my build fails I would like the build to end there, but show success with warnings instead of fail. I know continueOnError has this effect, but it still executes the subsequent steps. I would like to exit early instead of executing those but still keep the success with warnings status. How can I achieve this?
- task: DownloadBuildArtifacts#0
displayName: 'Download build artifacts'
continueOnError: true
inputs:
artifactName: 'build-artifacts'
buildType: 'current'
downloadType: 'single'
downloadPath: '$(Agent.BuildDirectory)/s'
- task: myNextTask#0
inputs:...
In other words, if downloadBuildArtifact has nothing to download I would like the pipeline to not execute myNextTask, but end the process with a 'success with warnings'
There's no easy way to do that with just conditions.
I suspect you can get it to work as follows:
Mark your Download Artifact task to succeed on error.
Add a script task that checks whether the artifact is present and sets the value of a variable accordingly.
Add a condition to the following tasks to only run when the variable has a certain value.
Do be careful though, if the Download Artifact task fails for another reason, like connection issues, interruptions, permissions etc, the error will be hidden.
An alternate route would be to add a script prior to the Download Artifact task that checks the presence of the desired artifact by querying the REST API. It can then set a variable which is used as a condition for all following tasks.

Stop GitHub Jobs in Progress if Another Failed (stop on fail)

TL; DR: Running jobs a,b in parallel. If a fails, stop the execution of b, while it's still running.
My company uses GitHub Actions to deploy our code.
The first step in our deployment is building dockers and pushing them to DockerHub.
We wrote a test for our code, which we want to run in parallel with building the dockers.
Both of these are separate jobs, and we have a few more jobs depending on the success of the first two.
Right now, if the test job fails, the other job continues to run, but obviously, the next one won't run, because the test job failed.
What I would like to do is cancel the docker building job while it's running, if the test failed.
Is that possible? After searching the web, StackOverflow and the GitHub Actions page, I haven't found a way to do that.
Thanks!
You can specify the needs option and refer to the job name. See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idneeds
An example could be something like:
jobs:
build:
...
deploy:
needs: build
...
You can use the Cancel this build action.
The basic idea is to add it as a final step in each of your jobs that you want to cause a short-circuit in case of failure:
jobs
job_a:
steps:
- run: |
echo 'I am failing'
exit 1
- name: Cancelling parallel jobs
if: failure()
uses: andymckay/cancel-action#0.2
job_b:
steps:
- run: echo 'long task'
This will basically cancel job_b or any other in the same workflow whenever job_a fails.
Since you are working on an enterprise project, I would prefer to avoid using unverified actions from public repositories no matter how many stars they have. I think you can add a step to the end of each job a, b. This step will only run if previous steps failed. If it is failed then it will send a cancel-workflow api call.
- if: failure()
name: Check Job Status
uses: actions/github-script#v6
env:
RUN_ID: ${{ github.run_id }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
script: |
const runId = process.env.RUN_ID
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
const resp = await github.rest.actions.cancelWorkflowRun({
owner,
repo,
runId
})
Note: You may need to add another custom github_pat since this api-call may require higher permissions than default actions. I also suggest you to take a look at this post , I found it quite useful.

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.

How to conditionally run a build agent job with a pipeline variable?

In Azure DevOps pipelines there's an option to conditionally run a task based on a pipeline variable. This is handled under the Run this task > Custom conditions field and it uses the syntax:
eq(variables['VarName'], 'Desired Value')
An agent job has a similar field for conditional execution under Run this job > Custom condition using variable expressions.
However, when I use the same syntax as a conditional task the result always evaluates to 'false'.
So how can I conditionally run an agent job?
Screenshots:
Something like this worked for me:
- job: Job1
steps:
- powershell: |
if (some condition)
{
Write-Host ("##vso[task.setvariable variable=RunJob2;isOutput=true]True")
}
name: ScriptStep
- job: Job2
dependsOn: Create_Build_Matrix
condition: and(succeeded(), eq(dependencies.Job1.outputs['ScriptStep.RunJob2'], 'True'))
I discovered the answer. Unfortunately, it is not possible to conditionally run an agent job with a variable that is modified during build execution.
From the Azure DevOps Pipeline documentation under Pipeline Variables:
To define or modify a variable from a script, use the task.setvariable
logging command. Note that the updated variable value is scoped to
the job being executed, and does not flow across jobs or stages.
Try this one: https://stefanstranger.github.io/2019/06/26/PassingVariablesfromStagetoStage/
This one gives you to pass variables from one stage/job to another stage/job in the same release pipeline. I tried and it's working fine.
Also to run this you need to give some permissions for release pipeline. To allow for updating the Release Definition during the Release you need to configure the Release Permission Manage releases for the Project Collection Build Service.