From 17d93758be67d6dcf7ff019347780bd665bd960b Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 24 Nov 2021 20:24:06 -0300 Subject: [PATCH] Jenkins: Switch strategy for polled commit detection --- .ci/Jenkinsfile | 83 ++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 46 deletions(-) diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index a53c461c7..53504ef50 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -81,24 +81,29 @@ def presetFlags = [ def anyFailure = false def gitClone(repository, branch) { - /* Read git tag from environment or set the default one. */ - if (env.GIT_COMMIT == null) - env.GIT_COMMIT = "*/$branch" - println "[-] Using git tag [${env.GIT_COMMIT}]" - /* Clean workspace. */ cleanWs() /* Use stashes to avoid performing multiple clones. */ if (env.GIT_STASHED != 'true') { /* Perform clone/checkout. */ - def scmVars = checkout poll: false, + def scmVars = checkout poll: true, changelog: true, scm: [$class: 'GitSCM', - branches: [[name: env.GIT_COMMIT]], - extensions: [[$class: 'LocalBranch', localBranch: branch]], + branches: [[name: branch]], userRemoteConfigs: [[url: repository]]] - env.GIT_COMMIT = scmVars.GIT_COMMIT + + if (env.GIT_COMMIT == null) { + /* Save the current HEAD commit. */ + env.GIT_COMMIT = scmVars.GIT_COMMIT + } else { + /* Checkout the commit read from the polling log. */ + if (isUnix()) + sh "git checkout ${env.GIT_COMMIT} || exit 0" + else + bat "git checkout ${env.GIT_COMMIT} || exit /b 0" + } + println "[-] Using git commit [${env.GIT_COMMIT}]" /* Stash data and mark it as stashed. */ stash name: 'git' @@ -147,46 +152,32 @@ pipeline { steps { script { - /* Hack to extract the current HEAD commit from this build's git polling - log. This avoids a race condition where HEAD changes in the time period - between Jenkins polling the git repository and the first build node - performing the first git clone once ready. (See issue JENKINS-20518) */ - if (env.GIT_COMMIT == null) { - /* This must run on the master node to read the polling log. */ - node('master') { - /* Ignore exceptions as this is not really critical. */ - try { - /* Switch to this build's directory. */ - dir("${env.JENKINS_HOME}/jobs/${env.JOB_NAME}/builds/${env.BUILD_NUMBER}") { - /* Parse polling log. */ - def pollingLog = readFile file: 'polling.log' - def match = pollingLog =~ /Latest remote head revision on [^ ]+ is: ([a-zA-Z0-9]+)/ - if (match && match[0]) { - env.GIT_COMMIT = match[0][1] - println "[-] Read git tag [${env.GIT_COMMIT}] from polling log" - } + /* Extract the polled commit from the polling log, so that git checkout can be used + to avoid JENKINS-20518 race conditions caused by two pushes too close together. */ + node('master') { /* must run on master node to read polling log */ + /* Ignore exceptions as this is not really critical. */ + try { + /* Switch to this build's directory. */ + dir("${env.JENKINS_HOME}/jobs/${env.JOB_NAME}/builds/${env.BUILD_NUMBER}") { + /* Parse polling log. */ + def pollingLog = readFile file: 'polling.log' + def match = pollingLog =~ /Latest remote head revision on [^ ]+ is: ([a-zA-Z0-9]+)/ + if (match && match[0]) { + env.GIT_COMMIT = match[0][1] + println "[-] Read git commit [${env.GIT_COMMIT}] from polling log" } - } catch (e) {} - } + } + } catch (e) {} + } - /* Perform a git clone on any node to save polling data and, - if polling log parsing failed, get the current HEAD commit. */ - node { - /* Clean workspace. */ - cleanWs() + /* Adding to the above, run a git clone as soon as possible on any node + to further avoid race conditions caused by busy node executor delays. */ + node { + /* Run git clone. */ + gitClone(repository, branch) - /* Perform clone/checkout. */ - def scmVars = checkout poll: true, - changelog: false, - scm: [$class: 'GitSCM', - branches: [[name: branch]], - userRemoteConfigs: [[url: repository]]] - if (env.GIT_COMMIT == null) - env.GIT_COMMIT = scmVars.GIT_COMMIT - - /* Clean workspace again. */ - cleanWs() - } + /* Clean workspace, in case this is running in a non-build node. */ + cleanWs() } /* Create source tarball. */