Search code examples
azuredevopsazure-pipelines-release-pipelineartifact

How can i release only artifacts that have changed in Azure DevOps?


I have one release with many artifacts, and every night I have scheduled deployments of this release. But usually only 1-2 artifacts have changes, the rest of it, none.

I have like 30 artifacts, and if I want to do a realease because I have changed one of them, I must release all the artifacts.

How can I deploy only the artifacts that have been changed, and not all of them?


Solution

  • There isn't a straight forward way to do that.

    The only thing I can think of is that you can write a script to call the build or pipeline run REST API to retrieve the source version of the pervious build or pipeline run, then compare the source version with current build/pipeline run (use the predefined variable Build.SourceVersion for current build) to check if they are the same source version (same commit for Git or changeset for TFVC).

    If it has the same source version with previous build/pipeline run, then fail the current build/pipeline, so that the CI/CD process will be stopped. Otherwise, build the artifact and deploy to your environment.

    UPDATE:

    The following Yaml for your reference: (Add a PowerShell task as the first task in your pipeline to run the script to compare current source version with the last succeeded build source version.)

    steps:
    - task: PowerShell@2
      displayName: Compare the source versions to fail or pass the CI build process
      inputs:
        targetType: 'inline'
        script: |
          # Get the last succeeded build source version
          $url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/builds?definitions=$env:SYSTEM_DEFINITIONID&resultFilter=succeeded&statusFilter=completed&api-version=6.0"
          $lastbuild = (Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(system.accesstoken)"}).value | Select-Object -First 1
          $pervioussourceversion = $lastbuild.sourceVersion
          Write-Host "The last successful build source version:$pervioussourceversion"
          
          # Current build source version
          $currentsourceversion = "$(Build.SourceVersion)"
          Write-Host "Current build source version            :$currentsourceversion"
          
          # Compare the source versions to fail or pass the CI build process
          if($currentsourceversion -eq $pervioussourceversion) {
              # make pipeline to fail
              Write-Host "Current source version:$currentsourceversion is the same as the last successful build:$(Build.BuildId), fail this step to stop current build pipeline."
              exit 1
          }
          else {
              # make pipeline to succeed
              Write-Host "Current source version:$currentsourceversion is different from the last successful build:$(Build.BuildId) with source version:$pervioussourceversion."
              Write-Host "Continue the pipeline to build a new artifact to deploy."
              exit 0
          }
      env:
        SYSTEM_ACCESSTOKEN: $(system.accesstoken)
    - task: PowerShell@2
      inputs:
        targetType: 'inline'
        script: |
          # Do something here.
          Write-Host "Add subsequent tasks to build your artifacts"
      condition: succeeded()
    

    Fail the artifact pipeline if the source version is same as previous one: enter image description here

    Continue the CI build process if a new version triggered: enter image description here

    UPDATE2: PowerShell script

    # Get the last succeeded build source version
    $url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/builds?definitions=$env:SYSTEM_DEFINITIONID&resultFilter=succeeded&statusFilter=completed&api-version=6.0"
    $lastbuild = (Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(system.accesstoken)"}).value | Select-Object -First 1
    $pervioussourceversion = $lastbuild.sourceVersion
    Write-Host "The last successful build source version:$pervioussourceversion"
          
    # Current build source version
    $currentsourceversion = "$(Build.SourceVersion)"
    Write-Host "Current build source version------------:$currentsourceversion"
          
    # Compare the source versions to fail or pass the CI build process
    if($currentsourceversion -eq $pervioussourceversion) {
       # make pipeline to fail
       Write-Host "Current source version:$currentsourceversion is the same as the last successful build:$(Build.BuildId), fail this step to stop current build pipeline."
       exit 1
    }
    else {
       # make pipeline to succeed
       Write-Host "Current source version:$currentsourceversion is different from the last successful build:$(Build.BuildId) with source version:$pervioussourceversion."
       Write-Host "Continue the pipeline to build a new artifact to deploy."
       exit 0
    }