0

I have a main solution and N other solutions in different repositories. Each time main solution builds I have to build N others and create an artifact of main solution containing others. My current build pipeline looks like this.

  • [Stage 1]

    • [Job 1] Build Main solution -> publish pipeline artifact (needed for other solutions) [agent folder 1]

    • [Job 2..N] Checkout Solution "n" -> build -> publish pipeline artifact [agent folders 2..N]

  • [Stage 2] - After all jobs succeded
    • [Job 1] - Download main artifact -> download other artifacts -> put them in one artifact -> publish [Agent folder N + 1]

My problem is that next time this pipeline runs, my agent recycles the last folder and the others are there waisting a lot of memory. Is there a way to tell the pipeline to run each job in the same agent working directory? Or to reuse the first directory created (the one for building main solution)?

EDIT: Here is the code of my pipeline

resources:
  repositories:
  - repository: Repo.With.Templates
    type: git
    name: Repo.With.Templates
    ref: feature/templates

  - repository: Secondary.Repository.1
    type: git
    name: Secondary.Repository.1
    ref: f/refactor/cd

  - repository: Secondary.Repository.2
    type: git
    name: Secondary.Repository.2
    ref: f/refactor/cd

trigger:
  batch: true
  branches:
    include:
    - 'f/core/cd-updates'

pool: 'Example pool'

variables:
 solution: '**/*.sln'
 buildPlatform: 'Any CPU'
 buildConfiguration: 'Release'
 scriptSetBuildNumber: 'CI\SetBuildNumber.ps1'
 nugetConfigFile: '$(Build.SourcesDirectory)/NuGet.config'
 checkoutFolderRoot: '$(Build.SourcesDirectory)'

stages:
- stage: BuildingStage
  jobs:
  - job: Main_Solution_Build
    steps:
    - task: VSBuild@1
      displayName: 'Build'
      inputs:
        solution: '$(solution)'
        msbuildArgs: '
            /p:DefineConstants="TESTENV"
            /p:TreatWarningsAsErrors=true
            /p:DeployDefaultTarget=WebPublish
            /p:WebPublishMethod=FileSystem
            /p:DeleteExistingFiles=True
            /p:SkipInvalidConfigurations=false
            /p:VisualStudioVersion=11.0
            /p:publishUrl="$(Build.ArtifactStagingDirectory)\"
            '
        platform: '$(buildPlatform)'
        configuration: '$(buildConfiguration)'

    # Zip bin folder and move to artifact folder
    - task: ArchiveFiles@2
      name: 'MovingMainSolutionBinToArtifacts'
      inputs:
        rootFolderOrFile: '$(Build.SourcesDirectory)/MainSolution/bin'
        includeRootFolder: true
        archiveType: 'zip'
        archiveFile: '$(Build.ArtifactStagingDirectory)/Artifacts/MainSolution.zip'
        replaceExistingArchive: true

    - task: PublishPipelineArtifact@1
      name: PublishMainSolutionBinPipeArtifact
      inputs:
        targetPath: '$(Build.ArtifactStagingDirectory)\Artifacts\MainSolution.zip'
        artifact: 'MainSolutionBinDrop'
        publishLocation: 'pipeline'

  - job: SecondarySolution1
    dependsOn: Main_Solution_Build
    steps:
    - checkout: Secondary.Repository
    - template: build-service-template.yml@Repo.With.Templates
      parameters:
        serviceName: "SecondarySolution1"


## Stage for assembling MainSolution and all the services together
- stage: Assemble
  dependsOn: BuildingStage
  jobs:
  - job: AssembleArtifact
    steps:
    - checkout: none

    - task: DownloadPipelineArtifact@2
      name: "MainSolutionBinDrop"
      inputs:
        buildType: 'specific'
        project: 'a12e0163-b207-400d-ac93-fa47964d5010'
        definition: '2'
        buildVersionToDownload: 'latest'
        artifactName: 'MainSolutionBinDrop'
        targetPath: '$(Build.ArtifactStagingDirectory)/MainSolutionBinDrop'

    - task: DownloadBuildArtifacts@0
      name: "DownloadServicesDrop"
      inputs:
        buildType: 'specific'
        project: 'a12e0163-b207-400d-ac93-fa47964d5010'
        pipeline: '2'
        buildVersionToDownload: 'latest'
        downloadType: 'single'
        artifactName: 'ServicesDrop'
        downloadPath: '$(Build.ArtifactStagingDirectory)'

    # Tasks that produce one artifact out of Main artifact and all Secondary solution artifacts
    # .....
    # .....

      # Publish
    - task: PublishPipelineArtifact@1
      inputs:
        targetPath: '$(Build.ArtifactStagingDirectory)/MainWithSecondary.zip'
        artifact: 'MainWithSecondary'
        publishLocation: 'pipeline'

And the code of the template used to build N secondary solutions (in this example only one)

parameters:
- name: solution
  type: string
  default: '**/*.sln'

- name: buildPlatform
  type: string
  default: 'Any CPU'

- name: buildConfiguration
  type: string
  default: 'Release'

- name: nugetConfigFile
  type: string 
  default: '$(Build.SourcesDirectory)/NuGet.config'

- name: serviceName
  type: string

steps:

# Tasks that download main build artifact, build secondary solution and publishes secondary artifact
#
#

#Download main solution artifact
- task: DownloadPipelineArtifact@2
  inputs:
    buildType: 'current'
    artifactName: 'MainSolutionDrop'
    targetPath: '$(Agent.BuildDirectory)/MainSolution'

- task: VSBuild@1
  displayName: 'Build'
  inputs:
    solution: '$(solution)'
    msbuildArgs: '
    /p:TreatWarningsAsErrors=true 
    /p:DeployOnBuild=true
    /p:SkipInvalidConfigurations=false'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

# Create artifact folder
- task: PowerShell@2
  name: "CreateArtifactFolder"
  inputs:
    targetType: 'inline'
    script: |
      if (!(Test-Path "$(Build.ArtifactStagingDirectory)\${{ parameters.serviceName }}" -PathType Container)) {    
                New-Item -ItemType Directory -Path "$(Build.ArtifactStagingDirectory)\${{ parameters.serviceName }}"
      }


- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'ServicesDrop'
    publishLocation: 'Container'
StackNet
  • 43
  • 1
  • 9
  • I've tried deleting the folders of Jobs 2..N in their last step but cant do that because of post-job checkout which requires source folder – StackNet Feb 23 '20 at 15:41

1 Answers1

1

Each job has its own default working directory and it is separate with other jobs, it is set the agent automatically and cannot be changed. So you cannot run each job in the same agent working directory.

There is a workaround to download the multiple repos under the same working folder and build them in a single job.

You can run git command in a powershell task to clone the multiple repos in the same working directory. And then set the build tasks point to each repo folder to build each solution. Check below example:

You will need to use PAT to anthenticate. Check here to generate PAT with Code read and write scope

- powershell: |
    git clone https://{PAT}@dev.azure.com/{org}/{proj}/_git/Repo1  #repo1 will be cloned into folder Repo1 under $(Build.SourcesDirectory)
    #cd Repo1 #cd the code folder

- powershell: |
    git clone https://{PAT}@dev.azure.com/{org}/{proj}/_git/Repo2  #repo1 will be cloned into folder Repo2 under $(Build.SourcesDirectory)
    #cd Repo2 #cd the code folder
  ....

- task: Build tasks1 #point the solution folder to $(Build.SourcesDirectory)/Repo1
    ...
- task: Build tasks2 #point the solution folder to $(Build.SourcesDirectory)/Repo2
    ...

#- task: Copy file task # copy the built artifacts to a specified folder.

- task: publish build artifacts task  #to publish repo1 artifacts
  ....
- task: publish build artifacts task  #to publish repo2 artifacts
  ....

You can also use Copy file task to move the built artifacts to different folders.

By using git clone command in the powershell task to clone the repos, you can combine your jobs and stages into just one job.

Update:

After checked above yaml pipeline and tested, I found the - checkout: Secondary.Repository caused new folders being created where rerun the pipeline.

The workaround is to use a powershell task to clone Secondary.Repository instead of using - checkout: Secondary.Repository. Please check out above workaround.

You can also report this issue to Microsoft by Reporting a problem(Click Report a problem and choose Azure devops)

Hope above helps.

Levi Lu-MSFT
  • 27,483
  • 2
  • 31
  • 43
  • Hi, thanks for the answer. I Understand that but I need to use multiple jobs (so I can re-run only failed jobs). What bothers me is that if I have only one job , agent creates a folder (i.e. _works/7) and if I re run the build pipeline he uses the same folder again (recycles it) and there are no copies. Can I have that behaviour with N jobs so each job that runs again (during another run of build pipeline) reuses the same folder – StackNet Feb 24 '20 at 09:10
  • I donot understand reusing the same folder? Do you mean you donot want to clean the previous contents and build results in the agent folders when the pipeline runs again. You can checkout [workspace](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#workspace) setting to override the clean behavior on the job. – Levi Lu-MSFT Feb 24 '20 at 15:41
  • Let's say I have a build definition with one job. Agent will create folder (i.e _work/17) with /s, /a etc. folders. If I run this build definition again (new build, same pipeline) agent will not create folder _work/18 but instead it will reuse the folder _work/17) and so there will not be a memory problem. If my build definition has 2 job, agent will create folders 17 and 18...and after I rerun the same build agent will not again reuse 17 and 18 but instead create folders 19 and 20, leaving the previous two on disk. Can I somehow change that so the behavior is same as having 1 job reuse17,18)? – StackNet Feb 24 '20 at 15:51
  • Can you share your pipeline? I have a test pipeline with two jobs, but I cannot reproduce your scenario. My pipeline always creates only one folder(i.e _work/1) on my local hosted agent. – Levi Lu-MSFT Feb 25 '20 at 03:20
  • Forgot to mention that pipeline has a repository resource to another azure pipeline and 1st job does checkout:self and 2nd job does checkout: "theOtherRepo" in that scenario agent creates multiple folders and does not reuse them during another pipeline run. I will share it soon sorry for the delay – StackNet Feb 25 '20 at 06:15
  • There, I edited my post and provided you with the pipeline and the template used for building all the N secondary solutions (in their own jobs) – StackNet Feb 25 '20 at 08:19
  • I tested and found `- checkout: Secondary.Repository` this step causes new folder being created each time. The workaround is described as above solution, run git clone in the powershell to checkout the repo's code. Check my update – Levi Lu-MSFT Feb 25 '20 at 14:18
  • Hi @StackNet Did you check out above update? Please try using git clone to download your source code instead of using `- checkout`. – Levi Lu-MSFT Mar 01 '20 at 14:55