ci(#6216): retry transient errors in after-scenario cleanup hooks - #6217
ci(#6216): retry transient errors in after-scenario cleanup hooks#6217fullsend-ai-coder[bot] wants to merge 1 commit into
Conversation
After-scenario cleanup operations (closing issues, deleting branches, deleting repos, clearing dummy scripts) now retry on transient API errors before falling back to log-and-continue. This prevents flaky merge queue ejections caused by transient GCP 503 or GitHub 5xx errors during cleanup, while non-transient errors (401, 404, 422) are still logged immediately without retry. Changes: - Add forge.IsTransient() to detect transient errors via a transientReporter interface, timeout detection, io.EOF checks, and ErrNonFastForward race conditions - Add IsTransient() method to GitHub, GitLab, and Jira APIError types (true for HTTP 429 and 500-504) - Wrap all API operations in CleanupScenario with a cleanupRetry helper that retries up to 3 times with exponential backoff for transient errors, then logs the final error and continues - Add comprehensive tests for forge.IsTransient, APIError.IsTransient, cleanupRetry helper, and end-to-end retry in CleanupScenario Closes #6216
|
🤖 Finished Review · ✅ Success · Started 11:02 PM UTC · Completed 11:18 PM UTC Commit: |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
ReviewFindingsMedium
Low
Labels: PR modifies forge error handling infrastructure (internal/forge/) and behaviour test cleanup hooks (pkg/behaviourtest/) |
There was a problem hiding this comment.
See the review comment for full details.
Note: The following inline comments could not be posted on the diff (GitHub returned 422) and are included here instead:
internal/forge/forge.go:124: [medium] logic error
IsTransient classifies context.DeadlineExceeded as transient because it implements Timeout() bool returning true. The comment says 'HTTP client timeout (distinct from context cancellation)' but the code does not actually distinguish them. In the cleanup path this is harmless (context.Background() is used), and the existing isTimeoutError in the same codebase follows the same pattern, but IsTransient is a public function and could surprise future callers with deadline-bound contexts.
Suggested fix: Add a guard before the Timeout() check: if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { return false }
pkg/behaviourtest/steps/cleanup_test.go(file-level): Line 619 · [low] race condition
speedUpCleanupRetries modifies the package-level cleanupBaseDelay variable without synchronization while tests run with t.Parallel(). In practice all tests write the same value (1ms) so the race is benign, but the -race detector would flag it.
Suggested fix: Remove t.Parallel() from tests that modify package-level variables, or pass delay/attempts as parameters to cleanupRetry.
Summary
forge.IsTransient()transient error detection for forge API errors, timeouts, EOF, and race conditionsIsTransient()method to GitHub, GitLab, and JiraAPIErrortypes (HTTP 429 and 500–504)CleanupScenariowith acleanupRetryhelper: retries transient errors up to 3 times with exponential backoff, then logs and continuesContext
After-scenario cleanup hooks in the behaviour test suite perform API operations (closing issues/PRs, deleting branches/repos, clearing dummy scripts) that are not part of the test assertion itself. When these cleanup calls hit transient infrastructure errors (GCP IAM 503, GitHub 5xx), the cleanup fails and can leave orphaned resources. This change adds retry resilience to prevent transient errors from disrupting cleanup, while keeping non-transient errors visible through logging.
Also addresses the broader pattern described in #5774 (422 Tree SHA race) by detecting
ErrNonFastForwardas a transient error worthy of retry at the cleanup level.Testing
forge.IsTransient()covering all error types (nil, sentinels, transient reporter, timeout, EOF, non-transient)APIError.IsTransient()across all HTTP status codescleanupRetryhelper: immediate success, transient-then-success, exhausted retries, non-transient no-retryCleanupScenarioretries transientCloseIssueandCommitFileerrorsCloses #6216
Post-script verification
agent/6216-cleanup-transient-retry)fcd4702368c74d517911b177f7ee7eca1634865b..HEAD)