Azure Pipelines
Azure Pipelines: YAML pipelines, jobs, agents, templates, and the patterns that scale across teams.
CI/CD — Azure Pipelines
EXAMPLE
# ===== The model =====
# - Pipelines defined in azure-pipelines.yml
# - Stages -> Jobs -> Steps
# - Agent: where the job runs (Microsoft-hosted or self-hosted)
# ===== Minimal pipeline (Node) =====
# azure-pipelines.yml
trigger:
branches: { include: [main] }
pool:
vmImage: 'ubuntu-latest'
variables:
NODE_VERSION: '20.x'
steps:
- task: NodeTool@0
inputs: { versionSpec: $(NODE_VERSION) }
- script: npm ci
displayName: 'Install'
- script: npm run lint
displayName: 'Lint'
- script: npm test -- --coverage
displayName: 'Test'
- script: npm run build
displayName: 'Build'
- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/junit.xml'
# ===== Stages =====
stages:
- stage: Build
jobs:
- job: Build
steps:
- script: npm ci && npm run build
- stage: Test
dependsOn: Build
jobs:
- job: UnitTest
- job: E2ETest
- stage: Deploy
dependsOn: Test
condition: succeeded()
jobs:
- deployment: ToProd
environment: production
strategy:
runOnce:
deploy:
steps:
- script: ./deploy.sh
# ===== Matrix =====
jobs:
- job: TestMatrix
strategy:
matrix:
node18: { NODE_VERSION: '18.x' }
node20: { NODE_VERSION: '20.x' }
node22: { NODE_VERSION: '22.x' }
steps:
- task: NodeTool@0
inputs: { versionSpec: $(NODE_VERSION) }
- script: npm test
# ===== Templates (reuse across pipelines) =====
# .ci/build-and-test.yml
parameters:
- name: nodeVersion
type: string
default: '20.x'
steps:
- task: NodeTool@0
inputs: { versionSpec: ${{ parameters.nodeVersion }} }
- script: npm ci && npm test
# Use:
- template: .ci/build-and-test.yml
parameters: { nodeVersion: '20.x' }
# ===== Variables + secrets =====
# UI: Pipeline -> Variables (mark as secret)
# YAML reference:
- script: echo $(MY_SECRET)
env:
MY_SECRET: $(MY_SECRET)
# Variable groups for sharing across pipelines:
variables:
- group: prod-secrets
# ===== Approvals + gates =====
# Configure via Environment 'production':
# - Required reviewers
# - Branch restrictions
# - Service health checks
# The deployment job pauses until approval is granted.
# ===== Self-hosted agents =====
# Install agent on your VM / k8s pool; register it.
# Useful for private networks, custom hardware, GPU builds.
pool:
name: 'self-hosted'
demands:
- Agent.OS -equals Linux
# ===== Artifacts =====
- task: PublishPipelineArtifact@1
inputs: { targetPath: 'dist', artifact: 'web-bundle' }
# Consume in a downstream job:
- task: DownloadPipelineArtifact@2
inputs: { artifact: 'web-bundle', path: '$(Build.SourcesDirectory)/dist' }
# ===== Useful tasks =====
# AzureCLI@2 run az commands with service principal
# Docker@2 docker build / push
# KubernetesManifest apply manifests
# AzureWebApp deploy to App Service
# AzureFunctionApp deploy to Functions
# ===== Patterns to internalise =====
# - YAML pipelines in the repo; do not use Classic editor
# - Templates for reuse across services
# - Environment approvals on prod
# - Required status checks on the default branch
# ===== Pitfalls =====
# - Secrets in plain YAML
# - Pipelines longer than 30 min -> people batch commits
# - 'latest' container tags in deploy -> non-reproducible
# - Classic builds + YAML mixed in one repo
Why it matters
Azure Pipelines: YAML in the repo, stages + jobs + steps, templates for reuse, environments for approvals. Mature, integrates deeply with Azure, and scales across teams once you commit to YAML over the Classic editor.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# azure-pipelines.yml
trigger: [main]
pool: { vmImage: ubuntu-latest }
steps:
- task: NodeTool@0
inputs: { versionSpec: '20.x' }
- script: npm ci && npm test
Try it Yourself »
Discussion
Loading…