Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-72713

checkout scm in loop seems async

XMLWordPrintable

      Hi,

      I need to poll hundreds of (fat) Git repos for changes and I can't use webhooks for that.

      The problem: Using 'dir() + checkout scmGit' inside a loop gives an unexpected result because for a given iteration, the previous iteration may not have finished, so the .git inside the current iteration is polluted with information from the previous iteration. Each checkout seems to run asynchronously.

      Consequence: using 'trigger pollscm', at the next build changes are detected as the last builds revisions in each dir/git repo are fulfilled with wrong data.

      This problem doesn't occur using parallel as each checkout runs in a separate thread/stage, but it's not an option right now for me.

       

      Code sample:

      stage('Checkout repos') {
          steps {
              script {
                  int size = reposMap.size()
      
                  reposMap.eachWithIndex {name, branches, index ->
                      println("\n######\n>> Checkout [${index}/${size}]: ${name}\nBranches:${branches}\n######")
      
                      for (branch in branches) {
                          println(">>> Starting Checkout of ${name} on ${branch}")
                          dir("${TOP_DIR}/${name}/${branch}") {
                              checkout scmGit(
                                  [
                                      branches: [[name: branch]],
                                      extensions: [
                                          cloneOption(depth: 1, noTags: true, shallow: true),
                                          pruneStaleBranch(),
                                          pruneTags(true)
                                      ],
                                      userRemoteConfigs: [[url: "${BASE_URL}/${name}", credentialsId: CRED_ID]]
                                  ]
                              )
                          }
                          println(">>> Ending Checkout of ${name} on ${branch}")
                      }
                  }
              }
          }
      } 

       

      And the output with comments

      ######
      >> Checkout [7/118]: my_project/my_repo_B
      Branches:[my_branch_B]
      ######
      [Pipeline] echo
      >>> Starting Checkout of my_project/my_repo_B on my_branch_B
      [Pipeline] dir
      Running in /opt/jenkins/workspace/test_poll_error/my_project/my_repo_B/my_branch_B
      [Pipeline] {
      [Pipeline] checkout
      The recommended git tool is: NONE
      using credential integration
      Cloning the remote Git repository
      Using shallow clone with depth 1
      Avoid fetching tags
      Avoid second fetch
      Checking out Revision c34c9426ff31a1832829b0ceda6df3d575ce3f0a (origin/my_branch_B)
      Commit message: "<BLANK>"
      First time build. Skipping changelog.
      [Pipeline] }
       > git config remote.origin.url https://my_server.com/scm/my_project/my_repo_A # timeout=10  // Here the previous iteration A writes in the current dir of B  
       > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
       > git rev-parse origin/my_branch_A^{commit} # timeout=10
       > git config core.sparsecheckout # timeout=10
       > git checkout -f 7f4423aabd9865ad2bdfd9708d31ef115ce8b239 # timeout=10  // Wrong revision for B
      [Pipeline] // dir
      [Pipeline] echo
      >>> Ending Checkout of my_project/my_repo_B on my_branch_B
      [Pipeline] echo
      
      ######
      >> Checkout [8/118]: my_project/my_repo_C
      Branches:[my_branch_C]
      ######
      [Pipeline] echo
      >>> Starting Checkout of my_project/my_repo_C on my_branch_C
      [Pipeline] dir
      Running in /opt/jenkins/workspace/test_poll_error/my_project/my_repo_C/my_branch_C
      [Pipeline] {
      [Pipeline] checkout
      The recommended git tool is: NONE
      using credential integration
      Cloning the remote Git repository
      Using shallow clone with depth 1
      Avoid fetching tags
      Cloning repository https://my_server.com/scm/my_project/my_repo_B     // Here the previous iteration B writes in the current iteration C 
       > git init /opt/jenkins/workspace/test_poll_error/my_project/my_repo_B/my_branch_B # timeout=10
      Fetching upstream changes from https://my_server.com/scm/my_project/my_repo_B
       > git --version # timeout=10
       > git --version # 'git version 2.25.1'
      using GIT_ASKPASS to set credentials
       > git fetch --no-tags --force --progress --depth=1 -- https://my_server.com/scm/my_project/my_repo_B +refs/heads/*:refs/remotes/origin/* # timeout=10
       > git config remote.origin.url https://my_server.com/scm/my_project/my_repo_B # timeout=10
       > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
       > git rev-parse origin/my_branch_B^{commit} # timeout=10
       > git config core.sparsecheckout # timeout=10
       > git checkout -f c34c9426ff31a1832829b0ceda6df3d575ce3f0a # timeout=10
      Cloning repository https://my_server.com/scm/my_project/my_repo_C
       > git init /opt/jenkins/workspace/test_poll_error/my_project/my_repo_C/my_branch_C # timeout=10
      Fetching upstream changes from https://my_server.com/scm/my_project/my_repo_C
       > git --version # timeout=10
       > git --version # 'git version 2.25.1'
      using GIT_ASKPASS to set credentials
       > git fetch --no-tags --force --progress --depth=1 -- https://my_server.com/scm/my_project/my_repo_C +refs/heads/*:refs/remotes/origin/* # timeout=10
      Avoid second fetch
      Checking out Revision 6b299692657347e89b3249303cc3ad644a306400 (origin/my_branch_C)
       > git config remote.origin.url https://my_server.com/scm/my_project/my_repo_C # timeout=10
       > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
       > git rev-parse origin/my_branch_C^{commit} # timeout=10
       > git config core.sparsecheckout # timeout=10
       > git checkout -f 6b299692657347e89b3249303cc3ad644a306400 # timeout=10
      Commit message: "<BLANK>"
      First time build. Skipping changelog.
      [Pipeline] }
      [Pipeline] // dir
      [Pipeline] echo
      >>> Ending Checkout of my_project/my_repo_C on my_branch_C
      [Pipeline] echo
      

       

            Unassigned Unassigned
            lnlrbr Lionel
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: