A production-ready, multi-stage Azure DevOps YAML pipeline designed as a reusable baseline for CI/CD scenarios.
| Category | Capabilities |
|---|---|
| Triggers | CI (branch + path filters), PR validation, Scheduled (nightly) |
| Build | Matrix builds, Caching, Artifact publishing |
| Deploy | Environment-based deployments, Azure CLI integration, Bicep/Terraform support |
| Architecture | Multi-repo checkout, Reusable templates, Conditional stages |
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Prep │───▶│ Build │───▶│ Test │───▶│ Infra │───▶│ App │───▶│ Post │
│ │ │ │ │(optional)│ │(optional)│ │ │ │(always) │
└─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘
│ │ │ │ │ │
checkout matrix unit tests Bicep/TF artifact notify
multi-repo cache pytest deploy deploy cleanup
set outputs artifacts dotnet test az cli app logic work items
- Copy
az-pipeline.yamlinto your repository - Create environment variable files in
variables/:variables/ ├── vars-dev.yaml ├── vars-acc.yaml └── vars-prod.yaml - Update repository references in
resources.repositories - Configure your Azure Service Connection
- Run the pipeline manually to validate
├── az-pipeline.yaml # Main pipeline definition
└── variables/
├── vars-dev.yaml # Dev environment variables
├── vars-acc.yaml # Acceptance environment variables
└── vars-prod.yaml # Production environment variables
Compile-time parameters for manual or triggered runs:
| Parameter | Type | Default | Description |
|---|---|---|---|
environment |
string | dev |
Target environment (dev, acc, prod) |
runInfra |
boolean | true |
Toggle infrastructure deployment stage |
runTests |
boolean | true |
Toggle test execution stage |
extraArgs |
string | "" |
Extra CLI args for infra deploy (e.g., --what-if) |
Example manual trigger:
environment: acc
runInfra: true
runTests: false
extraArgs: "--what-if"Checkout repositories and set output variables for downstream stages.
- Checks out
self,infraRepo, andtemplatesRepo - Logs directory paths for debugging
- Exports output variables (e.g., git SHA)
Build the application using matrix strategy with caching.
- Matrix job for parallel builds
- npm/pip cache restoration
- Publishes
dropartifact
Execute unit tests. Only runs when runTests=true.
Deploy infrastructure using Azure CLI. Only runs when runInfra=true.
- Uses deployment job with environment gates
- Executes Bicep/Terraform/ARM deployment
- Runs against configured Azure Service Connection
Deploy application using artifacts from Build stage.
- Downloads
dropartifact - Executes deployment logic
Finalization tasks that run regardless of previous stage results.
- Send notifications
- Create work items
- Cleanup resources
variables:
vmImage: ubuntu-latest
buildConfig: ReleaseLoaded from Azure DevOps Library:
- group: shared-secretsStore secrets like subscription IDs, service principals, and tokens.
Loaded per environment:
- template: variables/vars-${{ parameters.environment }}.yamlRequired variables in each environment file:
azureServiceConnection: "spoke-robin-dev"
adoEnvironmentName: "robin-dev"
location: "westeurope"resources:
repositories:
- repository: infraRepo
name: MyProject/infra-repo
- repository: templatesRepo
name: MyProject/pipeline-templates- checkout: infraRepo
path: shared-infra| Variable | Description |
|---|---|
$(System.DefaultWorkingDirectory) |
Root of self repo |
$(Pipeline.Workspace) |
Root for all repos + artifacts |
$(Build.SourcesDirectory) |
Self repo root |
Note: In deployment jobs, extra repos are located under
$(Pipeline.Workspace)/<path>
Example path setup:
SELF_ROOT="$(System.DefaultWorkingDirectory)"
INFRA_ROOT="$(Pipeline.Workspace)/shared-infra"
TEMPLATES_ROOT="$(Pipeline.Workspace)/templates"Infrastructure stage uses AzureCLI@2:
- task: AzureCLI@2
inputs:
azureSubscription: $(azureServiceConnection)
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
az group list -o tableEnsure your Service Connection has appropriate RBAC permissions on the target subscription.
- publish: $(System.DefaultWorkingDirectory)/dist
artifact: drop- download: current
artifact: dropArtifact location: $(Pipeline.Workspace)/drop
Add this step to debug directory structure:
echo "Build.SourcesDirectory=$(Build.SourcesDirectory)"
echo "System.DefaultWorkingDirectory=$(System.DefaultWorkingDirectory)"
echo "Pipeline.Workspace=$(Pipeline.Workspace)"
pwd
find "$(Pipeline.Workspace)" -maxdepth 2 -type d| Error | Cause | Solution |
|---|---|---|
unexpected value stage |
stage used without stages: |
Wrap top-level in stages: |
Repo not found under /s/ |
Deployment jobs store extra repos elsewhere | Use $(Pipeline.Workspace) |
| File not found | Variable points to wrong repo | Correct variable paths |
This pipeline template is intended for internal reuse. Fork and adapt per application or infrastructure stack.