From 5c8075996f251f86947a3da0f34dfdcb9160f9fc Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 13 Jul 2026 10:50:22 -0400 Subject: [PATCH] fix(TST-25): serialize the CI bootstrap fetch/checkout under the worktree lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acceptance-check finding (concurrency): the worktree lock in windev-worker-ci.ps1 guarded the build stage, but run-windev-ci.sh's bootstrap did git fetch + git checkout on the shared C:\build\mxaccessgw-ci clone BEFORE that lock was taken. Two concurrent runs therefore collided on .git/index.lock at the bootstrap stage (the second failed 'Another git process seems to be running', exit 1) instead of the second waiting — defeating the lock's purpose for manual/degraded-mode overlap or a future second runner. (The single Gitea runner serializes jobs, so CI pushes never actually overlapped; this is defense-in-depth being restored.) Fix: the bootstrap now acquires the same mkdir worktree lock around its fetch/ checkout and exports MXGW_CI_LOCK_HELD; windev-worker-ci.ps1 re-uses that lock (skips re-acquire/release) when the env is set, and still self-locks for a standalone/manual run. Now the second concurrent run waits at the bootstrap. --- scripts/ci/run-windev-ci.sh | 42 ++++++++++++++++++++++++++------- scripts/ci/windev-worker-ci.ps1 | 29 +++++++++++++++-------- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/scripts/ci/run-windev-ci.sh b/scripts/ci/run-windev-ci.sh index 7d52fff..08b1072 100755 --- a/scripts/ci/run-windev-ci.sh +++ b/scripts/ci/run-windev-ci.sh @@ -80,16 +80,42 @@ fi echo "run-windev-ci: mode=$MODE sha=$CI_SHA target=${WINDEV_SSH_USER}@${WINDEV_SSH_HOST}" # Remote PowerShell bootstrap: fetch + checkout enough to load the versioned CI script, then -# hand off to it. Not Stop around git (stderr progress). windev-worker-ci.ps1 re-fetches and -# re-checks-out under a lock, so this checkout only needs to load the right script version. +# hand off to it. Not Stop around git (stderr progress). +# +# The bootstrap fetch/checkout mutates the shared clone's git index, so it MUST hold the +# worktree lock — otherwise two concurrent runs collide on .git/index.lock before either +# reaches windev-worker-ci.ps1's lock (the exact race the lock exists to prevent). We take the +# same mkdir lock here (atomic; retry to a 20-min deadline) and export MXGW_CI_LOCK_HELD so the +# handed-off script re-uses this lock instead of re-acquiring/releasing it. A standalone/manual +# run of windev-worker-ci.ps1 (degraded mode) has no such env and self-locks as before. read -r -d '' BOOTSTRAP <