Skip to content

๐Ÿš€ Mijn CICD pipelines

Ik heb 3 afzonderlijke pipelines om het overzihtelijk te houden

  • azure-pipe-pr.yml
  • azure-pipelines-merge.yml
  • azure-pipe-tag.yml

๐Ÿง Info

Alleen op de PR pipeline zetten we een Branch Policy Dit is nodig zodat op een PR de pipeline automatisch gestart gaat worden.

Projects Settings -> Repositories -> -> Policies -> Branch Policies
Select by Build pipeline Trigger Required en Immediatly
Geef een display name in ....

๐Ÿงจ trigger / pr selectie

je selecteer met trigger en/of pr waarop je pipeline reageert !! ( zie de onderstaande voorbeelden )

โšก Pull Request pipe

azure-pipe-pr.yml gestart op een PR

name: PR-Only-$(Date:yyyyMMdd)$(Rev:.r)

# โœ… EXPLICIET geen CI triggers
trigger: none

# โœ… ALLEEN PR triggers
pr:
  branches:
    include:
      - '*'  # Alle branches
  paths:
    exclude:
      - README.md  # Optioneel: exclude bepaalde paths

stages:
- stage: PR_Validation
  displayName: '๐Ÿ” PR Validation'
  # โœ… Condition is optioneel maar extra veilig
  condition: eq(variables['Build.Reason'], 'PullRequest')
  jobs:
  - job: Validate_PR
    steps:
    - script: |
        echo "โœ… Dit is een PR build"
        echo "PR Source: $(System.PullRequest.SourceBranch)"
        echo "PR Target: $(System.PullRequest.TargetBranch)"
      displayName: 'PR Info'

๐Ÿ› ๏ธ Merge pipe

azure-pipelines-merge.yml gestart op een MERGE

trigger:
- main

stages:
- stage: PA
  displayName: "PA Flow" 
  pool:
    vmImage: 'ubuntu-latest'

  jobs:
  - job: Detect
    steps:
    - checkout: self
      fetchDepth: 0

    - bash: |
        echo "Detecting changes..."
        # git fetch origin main
        # git diff --name-only HEAD^ HEAD
        # CHANGED=$(git diff --name-only origin/main...HEAD)
        CHANGED=$(git diff --name-only HEAD^ HEAD)
        echo "$CHANGED"

        if echo "$CHANGED" | grep -q "recover.yml"; then
          echo "##vso[task.setvariable variable=RecoverChanged;isOutput=true]true"
          echo "recover.yaml changed !!"  
        else
          echo "##vso[task.setvariable variable=RecoverChanged;isOutput=true]false"
          echo "recover.yml did not change" 
        fi
        if echo "$CHANGED" | grep -q "site.yml"; then
          echo "##vso[task.setvariable variable=SiteChanged;isOutput=true]true"
          echo "site.yaml changed !!"  
        else
          echo "##vso[task.setvariable variable=SiteChanged;isOutput=true]false"
          echo "site.yml did not change" 
        fi
        if echo "$CHANGED" | grep -q "vars"; then
          echo "##vso[task.setvariable variable=VarsChanged;isOutput=true]true"
          echo "vars changed !!"  
        else
          echo "##vso[task.setvariable variable=VarsChanged;isOutput=true]false"
          echo "vars did not change" 
        fi
      name: detect_step

๐Ÿ—๏ธ Tag pipe

azure-pipe-tag.yml gestart op pushen van een tag

name: Release-$(Build.SourceBranchName)-$(Date:yyyyMMdd)$(Rev:.r)

trigger:
  tags:
    include: ['v*']
  branches:
    exclude: ['*']

pool:
  vmImage: 'ubuntu-latest'

variables:
  tagName: $(Build.SourceBranchName)
  version: $[replace(variables['tagName'], 'v', '')]

steps:
- script: |
    echo "๐ŸŽฏ Release triggered by tag: $(tagName)"
    echo "๐Ÿ“ฆ Version: $(version)"
    echo "๐Ÿ”– Git tag: $(Build.SourceBranch)"
    echo "๐Ÿ“ Commit: $(Build.SourceVersion)"
  displayName: 'Release info'

- task: PowerShell@2
  inputs:
    targetType: 'inline'
    script: |
      # Semantische versioning validatie
      if ($env:VERSION -notmatch '^v\d+\.\d+\.\d+$') {
        Write-Error "Version format must be MAJOR.MINOR.PATCH"
        exit 1
      }
      Write-Host "โœ… Valid version format: $env:VERSION"
  env:
    VERSION: $(version)
  displayName: 'Validate version format'

- script: |
    # Build je project met release configuratie
    echo Do some building  Version=$(version)
  displayName: 'Build release'
  condition: succeeded()

๐Ÿ”„ Using Vars

Azure DevOps automatically exposes variables as environment variables.
The naming convention converts variables to uppercase and replaces . with _.

Use vars used in pipeline definition.

steps:
- script: |
    echo "Build ID: $BUILD_BUILDID"
    echo "Build number: $BUILD_BUILDNUMBER"
    echo "Repository name: $BUILD_REPOSITORY_NAME"
  displayName: 'Use predefined variables'

- script: |
    echo "Custom variable: $MY_CUSTOM_VAR"
  displayName: 'Use custom variable'
  env:
    MY_CUSTOM_VAR: $(myCustomVariable)

$(variable) Syntax

You can directly reference variables in your script content:

variables:
  appName: 'my-app'
  environment: 'dev'

steps:
- script: |
    echo "Application name: $(appName)"
    echo "Environment: $(environment)"
    echo "Build reason: $(Build.Reason)"
  displayName: 'Use variables directly'

Passing Script Args

variables:
  deploymentRegion: 'eastus'

steps:
- script: |
    echo "Region: $1"
    echo "Build ID: $2"
  displayName: 'Use variables as arguments'
  arguments: '$(deploymentRegion) $(Build.BuildId)'

Vars in Script Output

You can also set variables from bash script output:

steps:
- script: |
    current_time=$(date +%Y%m%d%H%M%S)
    echo "##vso[task.setvariable variable=timestamp]$current_time"
  displayName: 'Set variable from script'

- script: |
    echo "Generated timestamp: $(timestamp)"
  displayName: 'Use the set variable'

๐Ÿ”’ Using Secret Variables

variables:
  mySecret: $(secretPassword)  # Defined in variable group or pipeline settings

steps:
- script: |
    echo "Secret value is set (but won't be printed)"
    # Use the secret in your script
    export PASSWORD="$MY_SECRET"
  displayName: 'Use secret variable'
  env:
    MY_SECRET: $(mySecret)

Example Diff Vars Types

variables:
  - name: appName
    value: 'my-application'
  - name: environment
    value: 'production'
  - group: 'my-variable-group'  # Reference to variable group

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - script: |
        echo "Build Information:"
        echo "Build ID: $BUILD_BUILDID"
        echo "Build Number: $BUILD_BUILDNUMBER"
        echo "Source Branch: $BUILD_SOURCEBRANCH"

        echo ""
        echo "Custom Variables:"
        echo "App Name: $(appName)"
        echo "Environment: $(environment)"
        echo "Database URL: $(databaseUrl)"  # From variable group

        # Using variables in commands
        docker build -t $(appName):$(Build.BuildNumber) .

        # Set output variable
        echo "##vso[task.setvariable variable=buildStatus;isOutput=true]success"
      displayName: 'Build and set variables'
      name: buildStep
      env:
        DOCKER_PASSWORD: $(dockerPassword)  # Secret variable

    - script: |
        echo "Build status from previous step: $(buildStep.buildStatus)"
      displayName: 'Use output variable'

Conditional Variable Usage

variables:
  ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}:
    environment: 'prod'
    deployUrl: 'https://prod.example.com'
  ${{ else }}:
    environment: 'dev'
    deployUrl: 'https://dev.example.com'

steps:
- script: |
    echo "Deploying to $(environment) environment"
    echo "Target URL: $(deployUrl)"

    # Use variables in conditional logic
    if [ "$(environment)" = "prod" ]; then
      echo "Running production deployment checks..."
    fi
  displayName: 'Conditional deployment'

Key Points to Remember

Predefined variables are automatically available as environment variables

Custom variables need to be mapped or used with $(variableName) syntax

Secret variables should only be passed through env mapping for security

Variable names are converted to uppercase with . replaced by _ in environment variables

Use ##vso[task.setvariable] syntax to set variables from script output

Output variables from one step can be referenced in subsequent steps using $(stepName.variableName)

๐Ÿท๏ธ Spec. Vars

Build Vars

Variable                    Description                     Example
Build.BuildId               Unique identifier for the build 12345
Build.BuildNumber           Build number format             20240115.1
Build.SourceBranch          Source branch name              refs/heads/main
Build.SourceBranchName      Short branch name               main, feature-branch
Build.SourceVersion         Commit ID                       a1b2c3d4e5f67890
Build.Repository.Name       Repository                      name    my-app
Build.Repository.Provider   Repository type                 GitHub, TfsGit
Build.DefinitionName        Pipeline definition name        my-app-ci
Build.DefinitionVersion     Pipeline version                1
Build.QueuedBy              Who triggered the build         John Doe
Build.RequestedFor          For whom build was requested    johndoe@example.com
Build.Reason                Reason for build                Manual, IndividualCI, PullRequest

System Vars

Variable                    Description             Example
System.JobId                Unique ID for the job   a1b2c3d4-e5f6-7890-abcd-ef1234567890
System.StageName            Current stage name      build
System.JobName              Current job name        build_job
System.JobAttempt           Job attempt number      1
System.PhaseId              Phase ID                12345678-1234-1234-1234-123456789012
System.PhaseDisplayName     Phase display name      Job
System.StageAttempt         Stage attempt number    1

PR Vars

Variable                                Description         Example
System.PullRequest.PullRequestId        PR ID               789
System.PullRequest.PullRequestNumber    PR number           42
System.PullRequest.SourceBranch         PR source branch    refs/heads/feature-branch
System.PullRequest.TargetBranch         PR target branch    refs/heads/main
System.PullRequest.SourceRepositoryURI  Source repo URI     https://github.com/org/repo.git

There are much more e.g. Agent Variables, Pipeline Variables, ** Release Variables (For Release Pipelines)**

Env Vars

# Build information
echo "Build ID: $BUILD_BUILDID"
echo "Build Number: $BUILD_BUILDNUMBER"
echo "Source Branch: $BUILD_SOURCEBRANCH"
echo "Source Branch Name: $BUILD_SOURCEBRANCHNAME"
echo "Commit ID: $BUILD_SOURCEVERSION"
echo "Repository: $BUILD_REPOSITORY_NAME"

# System information
echo "Job ID: $SYSTEM_JOBID"
echo "Stage: $SYSTEM_STAGENAME"
echo "Job: $SYSTEM_JOBNAME"

# Agent information
echo "Agent OS: $AGENT_OS"
echo "Agent Name: $AGENT_NAME"
echo "Work Folder: $AGENT_WORKFOLDER"

# Pipeline information
echo "Workspace: $PIPELINE_WORKSPACE"

Example

steps:
- script: |
    echo "=== BUILD INFORMATION ==="
    echo "Build ID: $BUILD_BUILDID"
    echo "Build Number: $BUILD_BUILDNUMBER"
    echo "Branch: $BUILD_SOURCEBRANCHNAME"
    echo "Commit: $BUILD_SOURCEVERSION"
    echo "Repository: $BUILD_REPOSITORY_NAME"

    echo "=== SYSTEM INFORMATION ==="
    echo "OS: $AGENT_OS"
    echo "Agent: $AGENT_NAME"
    echo "Workspace: $PIPELINE_WORKSPACE"

    echo "=== BUILD REASON ==="
    echo "Reason: $BUILD_REASON"
    echo "Requested by: $BUILD_REQUESTEDFOR"

    # Conditional logic based on branch
    if [ "$BUILD_SOURCEBRANCHNAME" = "main" ]; then
      echo "This is a production build"
    elif [ "$BUILD_SOURCEBRANCHNAME" = "develop" ]; then
      echo "This is a development build"
    fi

    # Check if it's a PR build
    if [ "$BUILD_REASON" = "PullRequest" ]; then
      echo "PR ID: $SYSTEM_PULLREQUEST_PULLREQUESTID"
      echo "Target Branch: $SYSTEM_PULLREQUEST_TARGETBRANCH"
    fi
  displayName: 'Display build information'

Most Useful

* Branch-specific:          Build.SourceBranchName, Build.SourceBranch
* Versioning:               Build.BuildNumber, Build.BuildId
* Repository:               Build.Repository.Name, Build.SourceVersion
* Environment detection:    Agent.OS, Build.Reason
* Path references:          Agent.WorkFolder, Pipeline.Workspace
* Audit info:               Build.QueuedBy, Build.RequestedFor