6

I have both server side (web api using c#) and client side (angular) code in same branch. I have created separate stage for both server side and client side code to build, and one more stage to deploy. If I check in code in either of client side or server side the all the 3 stages run. To avoid this I am looking for ways to add conditions at stage level so that if there are server side changes then only Server stage will run, if the checked in code has only client side code then only Client stage will run. I don't understand how I can check which files are checked in. I found similar kind of questions while searching but the solutions are given using git. I have my code in azure-repos. Is there any way so that I can check based on folder if there are changes and further use it in conditions in stage. Something like this:

stages: 
- stage: 'Server'
 condition: 

- stage: 'Client'
 condition: 

Thanks in advance.

Ang_Dev
  • 342
  • 1
  • 3
  • 17
  • azure-repos also using git, so you're using git. – Shayki Abramczyk Oct 28 '20 at 12:48
  • @ShaykiAbramczyk I was referring to the solution mentioned in https://stackoverflow.com/questions/53227343/triggering-azure-devops-builds-based-on-changes-to-sub-folders?rq=1. It doesn't seems working for me. – Ang_Dev Oct 28 '20 at 12:57
  • Link given by @ShaykiAbramczyk is your way. There is no path filter per stage. If you want to simplify this you need to create sperate pipelines for client and server with different path filters on trigger. – Krzysztof Madej Oct 28 '20 at 16:49

3 Answers3

5

The solution mentioned in this thread should work for you. I will share more details about this workaround.

1, Add another stage ChangedFolders on top of stage Server, In stage ChangedFolders, add a single job with a single powershell task. (You do not need to create variables for server folder and client folder. )

2, In the powershell taslk, run the scripts mentioned in above thread. And set output variables via scripts. See document here for more information.

See below example:

stages: 
- stage: ChangedFolders
  jobs:
  - job: preCheck
    steps:
    - powershell: |
        $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 'ServerFolder/*')  #if ServerFolder is a subfolder under a folder use "- like '*/ServerFolder/*'"
          {
            Write-Host "##vso[task.setvariable variable=severFolder;isOutput=true]True"
          }
          if ($name -like 'ClientFolder/*')
          {
            Write-Host "##vso[task.setvariable variable=clientFolder;isOutput=true]True"
          }
        }
      name: taskVariable
    
- stage: 'Server'
 condition: 

- stage: 'Client'
 condition: 

3, Then you can add dependency and conditions for sever and client stage. See document here. Check below yaml example:

The format to refer to the output variable in condtion is like this : dependencies.dependOnStageName.outputs['jobName.taskName.variableName']

- stage: ChangedFolders
  jobs:
  - job: preCheck
    steps:
    - powershell: |
        ...
      name: taskVariable

- stage: 'Server'
  dependsOn: preCheck
  condition: eq(dependencies.ChangedFolders.outputs['preCheck.taskVariable.serverFolder'], 'True')

- stage: 'Client'
  dependsOn: preCheck
  condition: eq(dependencies.ChangedFolders.outputs['preCheck.taskVariable.clientFolder'], 'True')

Please let me know if you have any questions.

Levi Lu-MSFT
  • 27,483
  • 2
  • 31
  • 43
4

I am posting the solution that worked for me. I have 3 stages Server, Client and Deploy. I have separated the stages in two pipelines on same branch. Now I have Server and Deploy stage in one and Client and Deploy stage in another pipeline. Additionally I have used the following code in server side(Web Api) pipeline

 paths:
  exclude:
  - folder Path for Client side /*

 stages: 

 - stage: 'Server'
  #  steps for building server side code
 - stage: 'Deploy'
  #  steps for Deploying server side code

and the following code in client side pipeline

  paths:
   include:
   - folder Path for Client side/*   

stages: 

   - stage: 'Client'
   #  steps for building client side code
   - stage: 'Deploy'
   #  steps for Deploying client side code

Now it triggers respective pipeline and deploys respective builds.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Ang_Dev
  • 342
  • 1
  • 3
  • 17
  • How do you manage order of pipeline execution after splitting into two separate pipelines? Assume changes occured in both Server and Client folders and in this case you should deploy Server app first and then Client app. – kamilz Oct 04 '22 at 16:43
0

First, we cannot set the file path filter in the stage condition, so this method is not feasible.

As a workaround, you can try the method mentioned in the link. Use custom boolean variables as the running conditions of the stages.

  1. Create variables with the values "False"

  2. Get the changed files through the tf diff command

  3. Determine which folder the modified file is under by script

  4. Change the corresponding variable value to "True" according to the folder name

  5. Add custom stage conditions: condition: eq(variables['RunProjectA'], 'True')

The filter script sample is given in the link, since you are using tfvc version control, you can change the git diff command to tf diff command.

Besides, as suggested by Krzysztof Madej, it is also a good choice to create separate pipelines and set separate path filter trigger for each pipeline.

Hugh Lin
  • 17,829
  • 2
  • 21
  • 25