From 29b66f675bf8d4b011af3660a08db595e82e4534 Mon Sep 17 00:00:00 2001 From: Ralph Bean Date: Wed, 27 May 2026 14:33:53 -0400 Subject: [PATCH] fix(e2e): retry lock verification read to handle auto_init race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub's auto_init creates a default README.md asynchronously when a repo is created. Our CreateOrUpdateFile overwrites it, but GitHub's eventual consistency can briefly serve the stale auto_init content ("# e2e-lock") on subsequent reads. This caused tryCreateLock to think it lost the lock race when it had actually won — the verification read returned auto_init content instead of our run ID. Retry the verification read up to 5 times with linear backoff, logging each mismatch so the auto_init race is visible in CI logs. Signed-off-by: Ryan Bean Assisted-by: Claude Opus 4.6 Signed-off-by: Ralph Bean --- e2e/admin/lock.go | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/e2e/admin/lock.go b/e2e/admin/lock.go index 0abf2f5905..b203537729 100644 --- a/e2e/admin/lock.go +++ b/e2e/admin/lock.go @@ -148,15 +148,30 @@ func tryCreateLock(ctx context.Context, client forge.Client, org, runID string, } // Verify we actually got the lock (handle race between two creators). - content, err := client.GetFileContent(ctx, org, lockRepo, "README.md") - if err != nil { - return false, fmt.Errorf("verifying lock: %w", err) - } - if strings.TrimSpace(string(content)) == runID { - logf("[e2e-lock] Lock acquired (run: %s)", truncateUUID(runID)) - return true, nil + // Retry the read because GitHub's auto_init may serve stale default + // README content ("# e2e-lock") briefly after CreateOrUpdateFile succeeds. + for i := range 5 { + if i > 0 { + select { + case <-time.After(time.Duration(i+1) * time.Second): + case <-ctx.Done(): + return false, ctx.Err() + } + } + content, err := client.GetFileContent(ctx, org, lockRepo, "README.md") + if err != nil { + return false, fmt.Errorf("verifying lock: %w", err) + } + holder := strings.TrimSpace(string(content)) + if holder == runID { + logf("[e2e-lock] Lock acquired (run: %s)", truncateUUID(runID)) + return true, nil + } + logf("[e2e-lock] Verification read %d/5: got %q, expected %s (auto_init race?)", i+1, truncateUUID(holder), truncateUUID(runID)) } + // After retries, still not our content — genuinely lost the race. + content, _ := client.GetFileContent(ctx, org, lockRepo, "README.md") logf("[e2e-lock] Lost lock race for %s/%s (holder: %s)", org, lockRepo, truncateUUID(strings.TrimSpace(string(content)))) return false, nil }