Extends
The extends
keyword allows you to create a pipeline that inherits from and extends a template. This approach is powerful for standardizing pipelines across your organization while still providing flexibility for individual projects.
Schema Reference
extends: # Required. Extends a template.
template: string # The template referenced by the pipeline to extend.
parameters: # Parameters used in the extend.
pool: string | pool # Pool where jobs in this pipeline will run unless otherwise specified.
name: string # Pipeline run number.
appendCommitMessageToRunName: boolean # Append the commit message to the build number. The default is true.
trigger: none | trigger | [ string ] # Continuous integration triggers.
parameters: [ parameter ] # Pipeline template parameters.
pr: none | pr | [ string ] # Pull request triggers.
schedules: [ cron ] # Scheduled triggers.
resources: # Containers and repositories used in the build.
builds: [ build ] # List of build resources referenced by the pipeline.
containers: [ container ] # List of container images.
pipelines: [ pipeline ] # List of pipeline resources.
repositories: [ repository ] # List of repository resources.
webhooks: [ webhook ] # List of webhooks.
packages: [ package ] # List of package resources.
variables: variables | [ variable ] # Variables for this pipeline.
lockBehavior: string # Behavior lock requests from this stage should exhibit in relation to other exclusive lock requests.
Basic Example
Here's a basic example of a pipeline that extends a template:
# azure-pipelines.yml
extends:
template: templates/main-pipeline-template.yml
parameters:
projectName: 'MyProject'
buildConfiguration: 'Release'
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
Template Example
The template being extended (templates/main-pipeline-template.yml
):
# templates/main-pipeline-template.yml
parameters:
- name: projectName
type: string
default: 'DefaultProject'
- name: buildConfiguration
type: string
default: 'Debug'
stages:
- stage: Build
jobs:
- job: BuildJob
steps:
- script: echo "Building ${{ parameters.projectName }} in ${{ parameters.buildConfiguration }} mode"
displayName: 'Build Project'
- stage: Test
jobs:
- job: TestJob
steps:
- script: echo "Testing ${{ parameters.projectName }}"
displayName: 'Test Project'
Advanced Examples
Extending Templates with Multiple Stages
# azure-pipelines.yml
extends:
template: templates/enterprise-ci-cd-template.yml
parameters:
projectName: 'MyWebApp'
environmentsToDeploy:
- name: 'Development'
serviceName: 'webapp-dev'
serviceConnection: 'azure-dev'
- name: 'Staging'
serviceName: 'webapp-staging'
serviceConnection: 'azure-staging'
approvalRequired: true
trigger:
branches:
include:
- main
- release/*
variables:
buildConfiguration: 'Release'
dotNetVersion: '6.0.x'
Template with Conditional Stages
# templates/enterprise-ci-cd-template.yml
parameters:
- name: projectName
type: string
- name: environmentsToDeploy
type: object
default: []
- name: runSecurityScan
type: boolean
default: true
stages:
- stage: Build
jobs:
- job: BuildJob
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '$(dotNetVersion)'
- script: dotnet build --configuration $(buildConfiguration)
displayName: 'Build ${{ parameters.projectName }}'
- task: DotNetCoreCLI@2
displayName: 'Run unit tests'
inputs:
command: 'test'
projects: '**/*Tests/*.csproj'
arguments: '--configuration $(buildConfiguration)'
- ${{ if eq(parameters.runSecurityScan, true) }}:
- stage: SecurityScan
displayName: 'Security Scan'
dependsOn: Build
jobs:
- job: RunSecurityScan
steps:
- script: echo "Running security scan on ${{ parameters.projectName }}"
displayName: 'Security Scan'
# Dynamic stages for each environment
- ${{ each environment in parameters.environmentsToDeploy }}:
- stage: Deploy_${{ environment.name }}
displayName: 'Deploy to ${{ environment.name }}'
dependsOn: ${{ if eq(parameters.runSecurityScan, true) }}:
- SecurityScan
${{ else }}:
- Build
jobs:
- deployment: Deploy
environment: ${{ environment.name }}
${{ if eq(environment.approvalRequired, true) }}:
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
displayName: 'Deploy to Azure Web App'
inputs:
azureSubscription: '${{ environment.serviceConnection }}'
appName: '${{ environment.serviceName }}'
package: '$(System.ArtifactsDirectory)/**/*.zip'
${{ else }}:
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
displayName: 'Deploy to Azure Web App'
inputs:
azureSubscription: '${{ environment.serviceConnection }}'
appName: '${{ environment.serviceName }}'
package: '$(System.ArtifactsDirectory)/**/*.zip'
Using Extends with Repository Templates
Templates can be stored in different repositories and reused across multiple projects:
# azure-pipelines.yml
resources:
repositories:
- repository: templates
type: git
name: DevOpsTemplates/pipeline-templates
ref: refs/tags/v1.0
extends:
template: dotnet-web-app-ci-cd.yml@templates
parameters:
projectName: 'CustomerPortal'
sonarQubeProject: 'customer-portal'
artifactName: 'website'
Best Practices for Template Extension
Standardize Core Build Logic: Keep core build, test, and deployment logic in templates to ensure consistency across projects.
Use Parameters for Flexibility: Design templates with parameters to accommodate different project requirements without modifying the template itself.
Version Your Templates: Use tags or specific branch references when extending templates from a shared repository to ensure stability.
Template Composition: Create specialized templates for different types of projects (e.g., web apps, APIs, libraries) that can extend more generic base templates.
Document Template Parameters: Clearly document the required and optional parameters for each template to facilitate adoption.
Include Validation: Add parameter validation in your templates to catch configuration errors early.
Multi-stage Templates: Design templates that cover the entire CI/CD process, from build to deployment across multiple environments.
Environment Specific Logic: Use conditionals to include environment-specific steps (e.g., additional security checks for production).
Template Extension Use Cases
Standardized CI/CD Pipelines: Create organizational standards for different application types.
Compliance Enforcement: Ensure all projects follow security and compliance requirements by embedding them in templates.
Accelerating New Projects: Provide ready-to-use pipeline templates for new projects, reducing setup time.
Multi-environment Deployment: Create templates that handle the complexity of deploying to multiple environments with appropriate approvals.
Cross-platform Applications: Use templates with matrix strategies to build and test applications on multiple platforms.
Last updated