Value of succeeded() in Azure DevOps pipeline before first stage is run
-
In an Azure DevOps pipeline, what is the value of Agent.JobStatus before any stages have been run? Is it initialized to 'Succeeded' or is it initially undefined or set to null or something like that, only to be set to 'Succeeded' after the first successful execution?
In other words:
- If I include
succeeded()
(which is the same thing as,in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues')
) in a condition for running the first stage, is it going to return true even though there have been no previous stages to return a successful result? - If I include
succeeded()
in a conditional for running the second stage, where the first stage has a condition that evaluated to false so the first stage was skipped, will it be true even though no previous stages have been executed returning a successful result?
The way I'd like to think it works is such that
succeeded
will returntrue
in both places where I use it in the following code, where I want the first stage to run if the original triggering repo branch was 'main' and the second stage to run if the original branch was 'release/*'. (This is a slightly simplified version of the actual logic.) Am I correct?stages: - template: my-template.yml condition: and(succeeded(), eq(variables['resources.pipeline.previousPipeline.SourceBranch'], 'refs/heads/main')) parameters: ... - template: my-template.yml condition: and(succeeded(), startsWith(variables['resources.pipeline.previousPipeline.SourceBranch'], 'refs/heads/release/')) parameters: ...
Alternatively, if
succeeded()
doesn't work in this manner, would I get what I need if, instead, I were to usenot(failed())
?
- If I include
-
Five minutes later I found this dealt with at https://github.com/MicrosoftDocs/azure-devops-docs/issues/7738 . Indeed, it appears that the Succeed outcome is not set until a stage has actually been executed. One respondent in the discussion indicates that this has worked for them:
As a work-around, our team has had success (no pun intended) using:
condition: not(or(failed(), canceled())
This works because the previous stage being skipped does not set a failed status.