Edit

Share via


extends definition

Extend a pipeline using a template.

extends:
  template: string # The template referenced by the pipeline to extend.
  parameters: # Parameters used in the extend.

Definitions that reference this definition: pipeline

Properties

template string.
The template referenced by the pipeline to extend.

parameters template parameters.
Parameters used in the extend.

Usage

The extends keyword allows a pipeline to use another pipeline (or template) as a base. This is useful for:

  • Reusing pipeline structure: Create a base pipeline that multiple projects can extend
  • Enforcing standards: Define required stages, jobs, or steps that all pipelines must include
  • Reducing duplication: Share common configuration across pipelines
  • Template inheritance: Build pipelines from templates with parameters

A pipeline can extend a single template. The template file should be a complete, valid pipeline structure. When you use extends, your pipeline YAML becomes a template that references the base template and optionally overrides parameters.

Extends vs includes

  • extends: Creates a pipeline that inherits from a template. Used at the root level of a pipeline.
  • include: Imports template content directly. Used at specific points within a pipeline.

Examples

Basic extends example

The simplest way to use extends is to have a pipeline inherit stages and jobs from a base template.

# File: base-pipeline.yml
# This is the base template that other pipelines extend
stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - script: echo Building...
      displayName: 'Build step'
# File: azure-pipelines.yml
# This pipeline extends the base template
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

extends:
  template: base-pipeline.yml

In this example, the pipeline in azure-pipelines.yml extends the base template to inherit the stages and jobs. The trigger and pool are defined in the consuming pipeline, not in the template.

Extends with parameters

You can pass parameters to a template when extending it:

# File: base-pipeline.yml
parameters:
- name: buildConfiguration
  type: string
  default: 'Debug'

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - script: echo Building with configuration ${{ parameters.buildConfiguration }}
      displayName: 'Build step'
# File: azure-pipelines.yml
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

extends:
  template: base-pipeline.yml
  parameters:
    buildConfiguration: 'Release'

In this example, the template defines parameters and stages, while the consuming pipeline defines trigger and pool alongside the extends keyword.

Multi-stage pipeline with extends

You can use extends to inherit multiple stages from a template. This is useful for teams that want a consistent pipeline structure across projects.

# File: multi-stage-template.yml
# This template defines a three-stage pipeline structure
stages:
- stage: Build
  displayName: 'Build Stage'
  jobs:
  - job: BuildJob
    displayName: 'Build Job'
    steps:
    - script: npm install
      displayName: 'Install dependencies'
    - script: npm run build
      displayName: 'Build application'

- stage: Test
  displayName: 'Test Stage'
  dependsOn: Build
  jobs:
  - job: TestJob
    displayName: 'Run Tests'
    steps:
    - script: npm run test
      displayName: 'Run unit tests'
    - script: npm run lint
      displayName: 'Run linter'

- stage: Deploy
  displayName: 'Deploy Stage'
  dependsOn: Test
  jobs:
  - job: DeployJob
    displayName: 'Deploy Job'
    steps:
    - script: npm run deploy
      displayName: 'Deploy to production'
# File: azure-pipelines.yml
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

extends:
  template: multi-stage-template.yml

In this example, the pipeline extends the template to inherit all three stages (Build, Test, and Deploy) with their dependencies and job definitions. The trigger and pool are defined in the consuming pipeline.

Type-safe parameters with extends

Templates and their parameters are turned into constants before the pipeline runs. Template parameters provide type safety to input parameters. In this example, the template start.yml defines the parameter buildSteps, which is then used in azure-pipelines.yml. If a buildStep gets passed with a script step, then it's rejected and the pipeline build fails.

# File: start.yml
parameters:
- name: buildSteps # the name of the parameter is buildSteps
  type: stepList # data type is StepList
  default: [] # default value of buildSteps
stages:
- stage: secure_buildstage
  pool:
    vmImage: windows-latest
  jobs:
  - job: secure_buildjob
    steps:
    - script: echo This happens before code 
      displayName: 'Base: Pre-build'
    - script: echo Building
      displayName: 'Base: Build'

    - ${{ each step in parameters.buildSteps }}:
      - ${{ each pair in step }}:
          ${{ if ne(pair.value, 'CmdLine@2') }}:
            ${{ pair.key }}: ${{ pair.value }}       
          ${{ if eq(pair.value, 'CmdLine@2') }}: 
            # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
            '${{ pair.value }}': error         

    - script: echo This happens after code
      displayName: 'Base: Signing'
# File: azure-pipelines.yml
trigger:
- main

extends:
  template: start.yml
  parameters:
    buildSteps:  
      - bash: echo Test #Passes
        displayName: succeed
      - bash: echo "Test"
        displayName: succeed
      # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
      - task: CmdLine@2
        inputs:
          script: echo "Script Test"
      # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
      - script: echo "Script Test"

See also