Skip to content

test(parity): retry parity sides on transient docker build flakes#11

Merged
aledbf merged 2 commits into
mainfrom
test/parity-retry-transient-build-flakes
Jul 22, 2026
Merged

test(parity): retry parity sides on transient docker build flakes#11
aledbf merged 2 commits into
mainfrom
test/parity-retry-transient-build-flakes

Conversation

@aledbf

@aledbf aledbf commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Problem

The runtime parity lane (task parity:runtime, PARITY_STRICT=true) turned red on unrelated changes — dependabot PRs #9 and #10, plus the main daily run on 2026-07-14 — all on up.dotfiles-local* cases. None were product regressions:

These are transient docker/BuildKit failures on contended CI runners. Under PARITY_STRICT=true there is no classification that makes them green — an inconclusive skip also fails the strict gate — so the only correct fix is to make the affected side actually succeed via a bounded retry.

Change

  • runParityCLI now wraps each side's CLI invocation in runWithInfraRetry (up to parityInfraRetries = 2 attempts). The original body is runParityCLIOnce.
  • Retry is gated on new isRetryableFailure, deliberately broader than isInfraError (adds the container-setup / docker build wrapper). Used only to decide a retry — the narrow isInfraError/classifyParitySide oracle-usability path is unchanged, so no real divergence is masked as a skip.
  • Retrying is safe by construction: a deterministic product failure reproduces on every attempt and still goes red. The retry stops early on success, on a non-retryable failure, or once the context is done (never runs past the per-case timeout).

Tests (parity_retry_test.go, no docker required)

Validation

  • go test ./internal/cli -run 'TestIsRetryableFailure|TestRunWithInfraRetry' → 12 passed
  • go test ./internal/cli -run 'TestClassifyParitySide|TestParityReport|TestStrictParityError|...' → 8 passed (existing helpers unaffected)
  • task lint (go vet) → pass

Not run: task parity:runtime (needs Docker + containerd image store, ~60 min); the flake can't be reproduced deterministically locally, so coverage is unit-level over the retry decision and loop where the regression lives.

🤖 Generated with Claude Code

The runtime parity lane's docker builds flake on contended CI runners
(BuildKit "failed to solve", a registry hiccup, or a container-setup
failure surfaced as `Command failed: docker build`). A flake on one
side while the other succeeds shows up as a false TS-vs-Go divergence
and fails the job under PARITY_STRICT=true, where an inconclusive skip
is red too. This turned unrelated dependabot PRs (#9, #10) and a main
daily run red on up.dotfiles-local* cases.

Wrap each side's CLI invocation in a bounded retry (2 attempts) gated
on isRetryableFailure, a predicate deliberately broader than
isInfraError. Retrying is safe: a deterministic product failure
reproduces on the next attempt and still goes red. The narrow
isInfraError/classifyParitySide oracle-usability path is unchanged, so
no real divergence is masked as a skip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 22, 2026 02:57
@github-code-quality

Copy link
Copy Markdown

Code Coverage Overview

Languages: Go

Go / code-coverage/go

The overall coverage in commit f58a494 in the test/parity-retry-tr... branch remains at 53%, unchanged from commit a99f1d3 in the main branch.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the runtime parity test harness against transient Docker/BuildKit flakes by retrying each parity “side” invocation when failures match known infra signatures, reducing false TS-vs-Go divergences in task parity:runtime under PARITY_STRICT=true.

Changes:

  • Wrap parity CLI execution in a bounded retry loop (runWithInfraRetry) keyed off a new isRetryableFailure classifier (broader than isInfraError, but used only for retry decisions).
  • Introduce parityInfraRetries to cap total attempts per side.
  • Add unit tests covering retry classification and retry-loop behavior without requiring Docker.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
internal/cli/parity_matrix_test.go Adds bounded infra retry around parity side execution and introduces isRetryableFailure.
internal/cli/parity_retry_test.go Adds focused unit tests for retryability classification and retry-loop behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/cli/parity_matrix_test.go
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Manuel Alejandro de Brito Fontes <aledbf@gmail.com>
Copilot AI review requested due to automatic review settings July 22, 2026 04:05
@aledbf
aledbf merged commit e9e7e10 into main Jul 22, 2026
1 of 2 checks passed
@aledbf
aledbf deleted the test/parity-retry-transient-build-flakes branch July 22, 2026 04:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment on lines +1258 to +1273
func isRetryableFailure(stdout, stderr string) bool {
if isInfraError(stdout, stderr) {
return true
}
combined := strings.ToLower(stdout + stderr)
retryablePatterns := []string{
"an error occurred setting up the container",
"command failed: docker build",
}
for _, p := range retryablePatterns {
if strings.Contains(combined, p) {
return true
}
}
return false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants