Pipelines: design and implement pipelines · Topic 2 of 3
GitHub Integration, YAML Pipelines and Triggers
AZ-400 YAML pipelines: the Azure Pipelines GitHub app, CI, PR and scheduled triggers, path filters, dependsOn, conditions, matrix and parallel jobs.
- 5 min
- Use the Azure Pipelines GitHub app. Results come back as checks on pull requests.
triggeris CI,pris pull request validation,schedulesis cron in UTC. Azure Repos pull request builds use branch policy.- Stages run in sequence by default. Jobs in a stage run in parallel by default.
dependsOnchanges the order.
What it is
A YAML pipeline is a file in the repository that defines when a run starts (triggers), where it runs (pool) and what it does (stages, jobs and steps). Keeping it in the repository means the pipeline is versioned, reviewed and branched with the code.
This topic covers connecting GitHub repositories to Azure Pipelines, writing YAML with the right trigger rules, and designing job execution order with stages, dependencies, parallelism and conditions.
How it works
Connecting GitHub to Azure Pipelines
- Install the Azure Pipelines app (from the GitHub Marketplace) on the account or repositories, choosing which repositories it can see.
- In Azure DevOps, choose New pipeline, select GitHub, authorize and pick the repository.
- Azure Pipelines creates a service connection and a webhook, commits or saves the YAML file, and starts running on events.
| Authentication to GitHub | Notes |
|---|---|
| GitHub App (Azure Pipelines app) | Recommended. Fine grained permissions, reports checks on pull requests, not tied to a person |
| OAuth | Acts as the user who authorized |
| Personal access token | Works but tied to a user, and expires |
Results appear in GitHub as checks on commits and pull requests, so a required status check can block merging. For pull requests from forks, secrets are not made available by default, which protects them from untrusted code.
You can also stay entirely in GitHub with Actions, and deploy to Azure with the azure/login action using OpenID Connect.
Triggers
trigger:
branches:
include: [ main, release/* ]
paths:
include: [ src/* ]
exclude: [ docs/* ]
pr:
branches:
include: [ main ]
schedules:
- cron: "0 3 * * 1-5"
displayName: Weekday nightly
branches:
include: [ main ]
always: false
| Trigger | Notes |
|---|---|
CI trigger (trigger:) | Runs on pushes to included branches and paths. trigger: none turns it off. batch: true groups pushes while a run is in progress |
PR trigger (pr:) | Validates pull requests. For GitHub repositories, defined in YAML. For Azure Repos, use a branch policy with build validation instead |
Scheduled (schedules:) | Cron in UTC. always: false skips the run if nothing changed |
| Pipeline resource trigger | Starts when another pipeline completes |
| Repository resource trigger | Starts when a referenced repository changes |
| Tags | trigger.tags.include runs on release tags |
Putting [skip ci] in a commit message skips the CI run. Use path filters so a documentation edit does not start a heavy build.
In GitHub Actions the same ideas are on: push, on: pull_request, on: schedule, on: workflow_dispatch (manual) and on: workflow_call (reusable).
Stages, jobs and ordering
stages:
- stage: Build
jobs:
- job: Compile
pool: { vmImage: ubuntu-latest }
steps:
- script: ./build.sh
- stage: Test
dependsOn: Build
jobs:
- job: Unit
steps: [ { script: ./test.sh unit } ]
- job: Integration
steps: [ { script: ./test.sh integration } ]
- stage: Deploy
dependsOn: Test
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: Prod
environment: production
strategy:
runOnce:
deploy:
steps: [ { script: ./deploy.sh } ]
| Concept | Behavior |
|---|---|
| Stages | Run in order by default, each depending on the previous one. dependsOn: [] makes a stage start in parallel |
| Jobs | Jobs within a stage run in parallel by default, if parallel jobs are available |
dependsOn | Defines an explicit order or fan in/out between jobs and stages |
condition | Controls whether a stage or job runs. The default is succeeded(). always() and failed() support cleanup and notification |
strategy: matrix | Runs the same job once per combination, such as operating system and version. maxParallel limits how many run at once |
strategy: parallel | Runs several copies of one job, used to slice a test suite |
| Deployment jobs | Use environment and a deployment strategy (runOnce, rolling, canary) |
In GitHub Actions the order comes from needs:, and strategy.matrix handles combinations.
Complex and hybrid pipelines
- Hybrid pipelines: build on Microsoft-hosted agents, then deploy through a self-hosted agent that can reach a private network.
- Multiple pools: each job can have its own
pool. - VM templates: pipelines can build virtual machine images (for example with Packer) that become the template for scale set agents or app servers.
- Runtime parameters let someone choose options when they run the pipeline manually.
A worked scenario
A GitHub repository needs a build on every pull request and a nightly full test run. The team installs the Azure Pipelines app, sets pr: to main and a schedules: cron for weeknights with always: false. Build runs first, then unit and integration jobs run in parallel, then a deploy stage with a condition that allows only main and an environment with approvals. A path filter ignores changes under docs/.
What to remember for the exam
- Use the Azure Pipelines GitHub app. Results come back as checks on pull requests.
triggeris CI,pris pull request validation,schedulesis cron in UTC. Azure Repos pull request builds use branch policy.- Stages run in sequence by default. Jobs in a stage run in parallel by default.
dependsOnchanges the order. matrixfans out combinations.parallelslices work.maxParallellimits concurrency.- Deployment jobs reference an environment and a strategy such as
runOnce,rollingorcanary.
A pipeline that "does not start on a docs change" is path filters. One that "should only deploy from main" is a stage condition or an environment branch control check.
How the exam asks about this
- "Build every GitHub pull request." A
pr:trigger with the Azure Pipelines app. - "Run tests against three versions at once."
strategy: matrix. - "Run a stage only when the previous stage succeeded and branch is main."
dependsOnplus acondition. - "Stop a pipeline running when only documentation changes." Path exclude filter.
Common mistakes
Expecting pr: to work for Azure Repos. Use a build validation branch policy there.
Cron times in local time. Schedules use UTC.
Assuming stages run in parallel. They are sequential unless dependsOn: [] is set.
Using a PAT for the connection. It expires and is tied to a person. Prefer the GitHub App.
Check yourself
What reports Azure Pipelines results on a GitHub pull request?
Checks, posted by the Azure Pipelines GitHub app.
How do you make two stages run at the same time?
Give them no dependency, for example dependsOn with an empty list.
Which keyword runs a job once for each combination of values?
strategy matrix.
Topic 2 of 3 in Pipelines: design and implement pipelines
Test yourself on Pipelines: design and implement pipelines
The full Microsoft AZ-400 question bank has 766 questions, with timed practice exams and an explanation for every answer.
This study guide is independent and is not affiliated with, endorsed by, or sponsored by Microsoft. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.