Warm tip: This article is reproduced from serverfault.com, please click

How to get only changed files using Azure devops pipelines

发布于 2020-12-01 10:06:55

I have folder structure this way in source code. f1 f2 f3 f4

I have added gitcopy diff task in my pipeline which lists and copies files which are modified to a destination folder. Now, I want to have a conditional loop as powershell script to only zip those folders which have modified files with a particular names for example if files from f1 are modified..I want particular steps to be performed and so on.. How can I do it as a loop? edit: I have written my pipeline in this way. But its failing in publish step with errors as listed.

yaml: trigger:

none

pool:
  vmImage: 'windows-latest'

variables:
  FR1PHPPRDAPP1VFlag: false
  FR1PHPPRDAPP4VFlag: false
  FR1PHPPRDAPP5VFlag: false
  FR1PHPPRDSRE1VFlag: false
  FR1PHPPRDAPP7VFlag: false
  stages:
  -stage: Zipping modified folders
steps:

- powershell: |

      ## get the changed files
      $files=$(git diff HEAD HEAD~ --name-only)
      $temp=$files -split ' '
      $count=$temp.Length
      echo "Total changed $count files"
      For ($i=0; $i -lt $temp.Length; $i++)
        {
          
          $name=$temp[$i]
          echo "this is $name file"
          if ($name -like 'FR1PHPPRDAPP1V/*') 
          {
            cd $(Build.ArtifactStagingDirectory)
            mkdir Output -force
           
          Compress-Archive -Path $(system.defaultworkingdirectory)/FR1PHPPRDAPP1V -DestinationPath $(Build.ArtifactStagingDirectory)/Output/APP1V.zip
          
          ##set the flag variable FR1PHPPRDAPP1VFlag to true
          Write-Host "##vso[task.setvariable variable=FR1PHPPRDAPP1VFlag]true"
          }
          if ($name -like 'FR1PHPPRDAPP4V/*')
          {
            cd $(Build.ArtifactStagingDirectory)
            mkdir Output -force
            ##achive folder FR1PHPPRDAPP4V if it is changed.
          Compress-Archive -Path $(system.defaultworkingdirectory)/FR1PHPPRDAPP4V -DestinationPath $(Build.ArtifactStagingDirectory)/Output/APP4V.zip
          ##set the flag variable FR1PHPPRDAPP4VFlag to true
          Write-Host "##vso[task.setvariable variable=FR1PHPPRDAPP4VFlag]True"
          }
           if ($name -like 'FR1PHPPRDAPP5V/*')
          {
            cd $(Build.ArtifactStagingDirectory)
            mkdir Output -force
            ##achive folder FR1PHPPRDAPP5V if it is changed.
          Compress-Archive -Path $(system.defaultworkingdirectory)/FR1PHPPRDAPP5V -DestinationPath $(Build.ArtifactStagingDirectory)/Output/APP5V.zip
          ##set the flag variable FR1PHPPRDAPP5VFlag to true
          Write-Host "##vso[task.setvariable variable=FR1PHPPRDAPP5VFlag]True"
          }
            if ($name -like 'FR1PHPPRDSRE1V/*')
          {
            cd $(Build.ArtifactStagingDirectory)
            mkdir Output -force
            ##achive folder FR1PHPPRDSRE1V if it is changed.
          Compress-Archive -Path $(system.defaultworkingdirectory)/FR1PHPPRDSRE1V -DestinationPath $(Build.ArtifactStagingDirectory)/Output/SRE1V.zip
          ##set the flag variable FR1PHPPRDSRE1VFlag to true
          Write-Host "##vso[task.setvariable variable=FR1PHPPRDSRE1VFlag]True"
          }
            if ($name -like 'FR1PHPPRDAPP7V/*')
          {
            cd $(Build.ArtifactStagingDirectory)
            mkdir Output -force
            ##achive folder FR1PHPPRDAPP7V if it is changed.
          Compress-Archive -Path $(system.defaultworkingdirectory)/FR1PHPPRDAPP7V -DestinationPath $(Build.ArtifactStagingDirectory)/Output/APP7V.zip
          ##set the flag variable FR1PHPPRDAPP7VFlag to true
          Write-Host "##vso[task.setvariable variable=FR1PHPPRDAPP7VFlag]True"
          }
        }
- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)/Output'
    ArtifactName: 'scripts-f2p'
    publishLocation: 'Container'
  condition: and(succeeded(), or(eq(variables.FR1PHPPRDAPP1VFlag, true),eq(variables.FR1PHPPRDAPP4VFlag, true),eq(variables.FR1PHPPRDAPP5VFlag, true),eq(variables.FR1PHPPRDSRE1VFlag, true),eq(variables.FR1PHPPRDAPP7VFlag, true)))
Questioner
priya
Viewed
0
Levi Lu-MSFT 2020-12-03 14:40:14

You can directly run below git commands in the powershell task to check the changed files. It is much easier than Rest api.

git diff-tree --no-commit-id --name-only -r $(Build.SourceVersion)

When you get the changed files, you can use the zip the changed folders directly in the powershell task using Compress-Archive command: See below example:

Compress-Archive -Path C:\f1 -DestinationPath f1.zip

If you want some particular steps to be performed based on the the changed folders. You can define the flag variables and using the logging commands in the powershell scripts to set the flags to true. And then use the condtions for the following steps.

See below full example scripts:

##set flag variables to indicate if the folder is changed.

variables:
  f1Flag: false
  f2Flag: false
  f3Flag: false
  
steps:

- powershell: |
      ## get the changed files
      $files=$(git diff-tree --no-commit-id --name-only -r $(Build.SourceVersion))
      $temp=$files -split ' '
      $count=$temp.Length
      echo "Total changed $count files"
     
      For ($i=0; $i -lt $temp.Length; $i++)
      {
        $name=$temp[$i]
        echo "this is $name file"
        if ($name -like 'f1/*')  #if f1 is a subfolder under a folder use "- like '*/f1/*'"
        { 
          ##achive folder f1 if it is changed.
          ##Compress-Archive -Path $(system.defaultworkingdirectory)/f1 -DestinationPath $(Build.ArtifactStagingDirectory)/f1.zip
          
          ##set the flag variable f1Flag to true
          Write-Host "##vso[task.setvariable variable=f2Flag]true"
        }
        if ($name -like 'f2/*')
        {
          ##achive folder f2 if it is changed.
          ##Compress-Archive -Path $(system.defaultworkingdirectory)/f2 -DestinationPath $(Build.ArtifactStagingDirectory)/f2.zip
          ##set the flag variable f2Flag to true
          Write-Host "##vso[task.setvariable variable=f2Flag]True"
        }
      }
      ## create a temp folder to hold the changed files
      New-Item -ItemType directory -Path $(system.defaultworkingdirectory)\temp

      foreach($file in $temp){
        if(Test-Path -path $file){
        Copy-Item -Path $file -Destination $(system.defaultworkingdirectory)\temp
        }
      }
      ## zip the temp folder which only have the changed files
      Compress-Archive -Path $(system.defaultworkingdirectory)\temp\* -DestinationPath $(Build.ArtifactStagingDirectory)\changedfiles.zip

Then you can use the condition for some particular steps just as Krzysztof mentioned

condition: and(succeeded(), or(eq(variables.f1Flag, true),eq(variables.f2Flag, true),eq(variables.f3Flag, true)))

See the answer to this thread for more information.

Update:

steps:

- powershell: |
     #get the changed files
     ....

        
- task: PublishBuildArtifacts@1
  inputs:
     PathtoPublish: '$(Build.ArtifactStagingDirectory)/Output'
     ArtifactName: 'drop'
     publishLocation: 'Container'
  condtion: and(succeeded(), or(eq(variables.f1Flag, true),eq(variables.f2Flag, true),eq(variables.f3Flag, true)))