Domain 3 β€” Module 5 of 12 42%
12 of 27 overall
Domain 3: Design and implement build and release pipelines Free ⏱ ~7 min read

YAML Pipelines: Events, Dependencies and Failure Conditions

Read a pipeline as an execution graph, verify AI-written trigger rules, and preserve diagnostics without accidentally allowing deployment.

Read the timetable and the connections

A train leaves because its timetable says when; a connecting train must also wait for passengers to arrive. Pipeline triggers decide whether a run starts. Dependencies and conditions decide what runs inside it. Confusing the two is a common source of unintended deployments.

Sketch the graph before asking Copilot for YAML:

             -> unit tests --------->
restore/build                       join -> test deployment -> production
             -> static analysis ---->

Decide which jobs need a shared build output and which can run independently. Parallel jobs may use different machines, so filesystem state does not automatically pass between them. Publish/download artifacts or rebuild deliberately.

An Azure Pipelines dependency example

This minimal, non-deploying example demonstrates ordering:

trigger:
  branches:
    include:
    - main

pool:
  vmImage: ubuntu-latest

jobs:
- job: Build
  steps:
  - script: echo "Build placeholder for the ordering exercise"
- job: UnitTests
  dependsOn: Build
  steps:
  - script: echo "Unit-test placeholder"
- job: StaticAnalysis
  dependsOn: Build
  steps:
  - script: echo "Analysis placeholder"
- job: ReleaseDecision
  dependsOn:
  - UnitTests
  - StaticAnalysis
  condition: succeeded()
  steps:
  - script: echo "Both prerequisite jobs succeeded"

The echo steps are explicitly ordering placeholders, not real tests or a functioning release. Replace them with the project’s validated commands before using the pattern for delivery. The two middle jobs can run concurrently subject to available capacity.

Azure YAML jobs in a stage run in parallel by default unless dependencies constrain them. Stages run sequentially by default unless configured otherwise. Be explicit where the correctness of a release depends on the relationship.

Do not let a custom condition erase success checks

A custom condition replaces the default condition. A branch comparison by itself can accidentally ignore whether a prerequisite failed. Combine outcome and branch when both are required:

condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))

Use broader conditions for diagnostics or cleanup, not automatically for deployment. always() can run even after cancellation in supported contexts; cleanup must be safe and bounded. Review stage/job parent behavior as well as a single step’s condition.

Pipeline-completion triggers need their own branch and source configuration. Check the pipeline resource, branch filters, and default-branch settings. Do not assume a YAML file’s location proves which version of its trigger configuration is evaluated.

Recognize the GitHub equivalent

A harmless Actions graph uses needs:

name: Ordering exercise
on:
  workflow_dispatch:
permissions:
  contents: read
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Check placeholder"
  decision:
    needs: check
    runs-on: ubuntu-latest
    steps:
      - run: echo "Prerequisite succeeded"

Actions event filters, if, needs, environments, and concurrency each control a different aspect. A branch filter on pull_request normally refers to the PR’s target branch, not simply the contributor’s branch name.

Avoid privileged pull_request_target execution of untrusted PR code. Its trust and token context differ from ordinary PR events. Do not change event type just to make a secret available.

Ask Copilot for constraints and a negative test

Provide the platform, repository layout, supported runtime, permitted triggers, expected graph, and forbidden actions:

Draft a GitHub Actions workflow for this existing test command.
Run on PRs into main and manual dispatch. No deployment or secrets.
Use read-only contents permission. Explain each event and dependency.
Show what should happen when the test command exits 1.

Compare its answer with current syntax and a sandbox run. Check indentation, event scope, shell, working directory, output paths, token permissions, and skipped-job behavior. Ask it to explain the generated graph, then inspect the platform’s actual graph.

Knowledge Check

An Azure deployment job has only a custom 'branch is main' condition. Why might that be unsafe?

Try it: inspect the graph, not just the YAML

Prerequisites: a sandbox Azure Pipelines or GitHub Actions project. Runs may consume billable minutes.

Use one of the harmless graphs above. Run it successfully, then make the first placeholder step exit with code 1. Observe which dependent jobs are skipped and where diagnostics would run. Restore the command. Do not add a production deployment to this experiment.

Expected observation: the actual run graph matches the intended dependency graph, and failure prevents the release-decision path.

Cleanup: remove the disposable workflow/pipeline or keep it disabled in the sandbox. Restore any edited commands and delete only your test runs if appropriate.

Question

Trigger versus condition?

Click or press Enter to reveal answer

Decision check: the required check never appears

Inspect event and path filters, workflow naming, and skip behavior. A filtered-out workflow can leave a required check pending; absence is not a successful check.

Read the source