I have a job with a simple condition: succeededOrFailed(), along with some dependsOn entries of other jobs to complete first. This has been working fine until today. I discovered today that, from what I can tell, if the last job to complete in the dependsOn list gets skipped (because that job has a branch-based condition in this situation), then the succeededOrFailed evaluation turns to 'False' because (totally guessing at this) the last dependent phase's status is marked Skipped or something other than Succeeded, SucceededWithIssues, or Failed. When running on a branch where these skipped jobs actually run (because conditions match correctly), then the job runs as expected.
Using the same pipeline, I've added a dummy job that had all the same dependencies as the original job, and then added this dummy job to the original job's list of dependencies, hoping to get around this "last one in the line of dependencies is skipped" issue. Turns out that with a default condition (not defining a condition), it gets skipped too, because succeeded() is False from the previously skipped job. When I set this dummy job's condition to always(), the build proceeds as expected and the original job also runs. Unfortunately I don't want to use the always() condition for the original job as I don't want it running on canceled jobs.
According to your documentation, Agent.JobStatus, doesn't have a value for a skipped job, so I don't know what it is actually getting evaluated to. I'm hoping you can shed some light on this. Ultimately, I would like to ask that you include a skipped jobStatus to the succeededOrFailed() evaluation, or provide a way to create a condition which will handle both succeededOrFailed and skipped statuses.
⚠Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
Agent.JobStatus will never be populated in a job condition, so that's a red herring. I see that we have a job status of skipped but I don't think we ever exposed it to the expression parser in conditions. Seems like a bug to me, so I'll get that filed.
In the meantime, the workaround is what you've done: add a dummy job that will succeed. You should be able to avoid running on cancellation by giving condition: not(canceled()) on the dummy job.
I asked the dev who built this feature, and he gave me the correct answer :) I'll find a way to work it into the docs, but I figured I'd update you here for expediency:
jobs:
- job: a
condition: false
pool: Hosted Ubuntu 1604
steps:
- script: printenv|sort
- job: b
condition: false
pool: Hosted Ubuntu 1604
steps:
- script: printenv|sort
- job: c
dependsOn:
- a
- b
condition: |
and
(
in(dependencies.a.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
in(dependencies.b.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
)
pool: Hosted Ubuntu 1604
steps:
- script: printenv|sort
Fix pending.
Fixed a while ago, the bug just didn't get closed.
@vtbassmatt should I open a new issue to request a succeededOrSkipped() conditional that does the above without the extra-cumbersome conditional? If so, which repo should I file it in for a request like that?
@vexx32 You could file that request on Developer Community.
In case someone is trying to figure out a similar issue, I've used another workaround that seems to work too
condition: |
and(
not(failed()),
not(canceled()),
eq(${{ parameters.myParameter}}, true)
)
Most helpful comment
@vexx32 You could file that request on Developer Community.