aboutBlog

Learn DevOps Step-by-Step Tutorials and fixing related issues.

Welcome to Py-Bucket, your go-to blog for DevOps tutorials and production issues fixes guide.

  • ✔ Beginner-friendly DevOps guides
  • ✔ Real-world production issues and fixes

Azure DevOps YAML Pipeline: Stages, Jobs, Steps and Triggers Explained

Azure DevOps YAML Pipeline: Stages, Jobs, Steps and Triggers Explained

Azure pipeline flow
Azure DevOps pipeline flow
 


If you've ever stared at an Azure DevOps YAML pipeline error wondering why your stage isn't triggering, or why a variable set in Job 1 is completely invisible in Job 2 — you're not alone. YAML pipelines are powerful, but their hierarchy and variable scoping trip up even experienced engineers.

In this tutorial, you'll get a clear, practical breakdown of how Azure DevOps YAML pipelines actually work — from the top-level stages down to individual steps, how to pass variables across tasks, jobs, and stages, how to configure CI and PR triggers correctly, and how to use conditions to control exactly when each part of your pipeline runs.

Whether you're setting up your first pipeline or trying to debug an existing one, this guide gives you the mental model and real code examples to get it right the first time.

Azure Devops YAML Pipeline Hierarchy

A YAML pipeline is structured in a hierarchical manner:

  1. Stages – The top-level division in a pipeline (e.g., "Build," "Test," "Deploy").

  2. Jobs – A sequence of steps that run sequentially or in parallel within a stage.

  3. Steps – The smallest executable unit, which can be a script or a predefined task.


1. Stages in Azure DevOps yml pipeline

In a YAML pipeline, the top level is stages. Each stage can contain multiple jobs, and each job consists of a series of steps.
Stages define logical boundaries in a pipeline,even if not explicitly defined, every pipeline has at least one stage.
Below are examples of stages:
  • Build App
  • Run Tests
  • Deploy to Production

Example:

yaml
stages:  
- stage: Build App
  jobs:  
  - job: BuildJob  
    steps:  
      - script: echo "Building the app..."  


2. Jobs

A job is a set of steps that run together. Jobs can:

  • Run sequentially or in parallel.
  • Have dependencies (e.g., Job2 depends on Job1).
  • Read more about job here

Example:

yaml
jobs:  
- job: JobA  
  steps:  
    - script: echo "Running Job A"  

- job: JobB  
  dependsOn: JobA  
  steps:  
    - script: echo "Running Job B after Job A" 


3. Steps (Tasks)

Steps are the smallest executable units in a pipeline. They can be:

  • Scripts (Bash, PowerShell, etc.)
  • Predefined tasks (e.g., npm installdotnet build)

Example:

yaml
steps:  
- script: echo "Restoring dependencies..."  
- task: DotNetCoreCLI@2  
  inputs:  
    command: 'build'  

Passing Variables Across Tasks, Jobs, and Stages of yaml pipeline

1. Pass variables accross  Tasks in the Same Job

Use task.setvariable to pass values between tasks.

Example:

yaml
steps:  
- powershell: |  
    Write-Host "##vso[task.setvariable variable=MYVAR]abc"  
- script: echo $(MYVAR)  # Output: abc  

2. Pass Variables Across Different Jobs

Use isOutput=true and reference the variable via dependencies.

Example:

yaml
jobs:  
- job: Job1  
  steps:  
    - bash: |  
        echo "##vso[task.setvariable variable=MYVAR;isOutput=true]abc"  
      name: SetVarStep  

- job: Job2  
  dependsOn: Job1  
  variables:  
    MYVAR: $[ dependencies.Job1.outputs['SetVarStep.MYVAR'] ]  
  steps:  
    - script: echo $(MYVAR)  # Output: abc  

3. Pass variables Across Different Stages

Use stageDependencies to pass variables between stages.

Example:

yaml
stages:  
- stage: StageA  
  jobs:  
  - job: JobA  
    steps:  
      - bash: |  
          echo "##vso[task.setvariable variable=MYVAR;isOutput=true]abc"  
        name: SetVarStep  

- stage: StageB  
  dependsOn: StageA  
  variables:  
    MYVAR: $[ stageDependencies.StageA.JobA.outputs['SetVarStep.MYVAR'] ]  
  jobs:  
  - job: JobB  
    steps:  
      - script: echo $(MYVAR)  # Output: abc  

Triggers in Azure DevOps yml pipeline

Triggers automate pipeline execution based on events like code commits or pull requests.

1. CI Trigger in yaml pipeline (Continuous Integration)

Runs when changes are pushed to specified branches/paths.

Example:

yaml
trigger:  
  branches:  
    include:  
      - main  
  paths:  
    include:  
      - src/**  
    exclude:  
      - src/docs/**  

2. PR Trigger (Pull Request Validation)

Runs when a PR is created or updated.

Example:

yaml
pr:  
  branches:  
    include:  
      - main  
  paths:  
    include:  
      - src/**  

🔹 Best Practices for Triggers:

  • Use batch: true to optimize CI runs.
  • Path filters are case-sensitive.
  • Wildcards (*) are not supported in path filters.


Conditions in Pipelines

Control when jobs, steps, or stages run using conditions.

Common Conditions in Azure DevOps yml pipeline:

ConditionDescription
succeeded()Runs only if previous steps succeeded (default).
always()Runs regardless of previous failures.
failed()Runs only if previous steps failed.
eq(variables['var'], 'value')Runs if a variable matches a value.

Example:

yaml
steps:  
- script: echo "This runs only on main branch"  
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')  


FAQ

Q1. What is the difference between a stage, job, and step in Azure DevOps YAML pipeline?

A stage is the highest level in a YAML pipeline — it represents a major phase like Build, Test, or Deploy. A job is a collection of steps that run together on the same agent. A step is the smallest unit — a single script or task like running npm install or dotnet build. Think of it as: pipeline → stages → jobs → steps.


Q2. Can jobs run in parallel in an Azure DevOps YAML pipeline?

Yes. By default, jobs within the same stage run in parallel if you have available agents. To run them sequentially, use dependsOn to define the order — for example, Job2 can be set to run only after Job1 completes successfully.


Q3. How do I pass a variable from one stage to another in Azure DevOps YAML?

Use isOutput=true when setting the variable in the source stage, then reference it in the target stage using stageDependencies. The target stage must also declare dependsOn pointing to the source stage, otherwise the variable reference will fail silently.


Q4. Why is my Azure DevOps YAML pipeline CI trigger not working?

The most common reasons are: the branch name in your trigger block doesn't exactly match your repository branch (including case sensitivity), path filters are misconfigured, or the pipeline was manually set to override triggers in the UI. Also check that trigger: none isn't accidentally set at the top of your YAML file.


Q5. What is the difference between a CI trigger and a PR trigger in Azure DevOps?

A CI trigger (trigger:) fires when code is pushed or merged into a branch. A PR trigger (pr:) fires when a pull request is created or updated against a target branch. CI triggers are used to deploy or build after merging, while PR triggers are used to validate code before merging.


Q6. What does the succeeded() condition do in Azure DevOps YAML?

succeeded() is the default condition applied to every step, job, or stage. It means the task only runs if all previous tasks completed without errors. You can override this with always() to run regardless of failures, or failed() to run a cleanup step only when something goes wrong.


Q7. Can I reuse YAML pipeline code across multiple pipelines in Azure DevOps?

Yes — Azure DevOps supports YAML templates, which let you define reusable stages, jobs, or steps in a separate .yml file and reference them from multiple pipelines using the template: keyword. This is one of the most powerful features for keeping large pipeline codebases maintainable.



=======================================

You will like these blogs as well:

Kubernetes guide 


Featured posts

🔥 Featured Tutorials

Devops

DevOps Tutorials

Author Details

Hi, I'm Prashant — a full-time software engineer with a passion for automation, DevOps, and sharing what I learn. I started Py-Bucket to document my journey through tools like Docker, Kubernetes, Azure DevOps, and PowerShell scripting — and to help others navigate the same path. When I’m not coding or writing, I’m experimenting with side projects, exploring productivity hacks, or learning how to build passive income streams online. This blog is my sandbox — and you're welcome to explore it with me. Get in touch or follow me for future updates!