fix(ci): propagate Playwright exit code through tee pipe - #57
Conversation
Without pipefail, `cmd | tee file` returns tee's exit status (always 0), so a Playwright run with failures silently exits 0 and the job goes green. Adding `set -o pipefail` makes the pipeline return Playwright's exit code. The grep-based "no tests ran" guard is preserved for the zero-test case. Fixes false-green seen on fluffyx/billiedoby-scheduling PR #194 (shard 1 reported 1 failed but the GH job was marked successful). Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughMultiple GitHub Actions workflows were modified. Several steps now enable Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
ApprovabilityVerdict: Approved CI/CD workflow changes only - adds You can customize Macroscope's approvability policy. Learn more. |
…2e steps Five more instances of the same bug fixed in #57: a pipe to tee swallows the left-side exit code, causing audit tools and Playwright to report success even when they fail. The audit steps (ci-gem, ci-rails, ci-rails-svelte, ci-svelte) were especially broken: the continue-on-error + outcome == 'failure' pattern depended on the audit command's exit code propagating, but tee always wins the pipeline. Real vulnerabilities would silently pass. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Dismissing prior approval to re-evaluate eddf401
Each e2e shard only runs one suite but previously installed dependencies, Playwright browsers, and ran codegen for every frontend*/ directory. On billiedoby-scheduling (frontend + frontend-book, 2 shards), this wasted ~46s per shard because the unused suite's install triggered prepare scripts for private git-branch packages. Hoist SUITE to job-level env so all steps can reference it, then replace the three for-dir-in-frontend*/ loops with direct pnpm --dir "$SUITE" calls. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Dismissing prior approval to re-evaluate bd089ce
Both cache keys previously hashed all frontend*/pnpm-lock.yaml files, causing spurious cache misses when the non-tested suite's lockfile changed. Scope them to matrix.suite so each shard only invalidates on its own deps. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Dismissing prior approval to re-evaluate 9346057
…cripts setup-node's implicit pnpm cache wasn't persisting the store across runs (visible in PR #194 logs — prepare ran on every install for git-ref deps like @fluffyx/fx-glass and @fluffyx/fx-core-svelte, costing ~46s/shard). Replace the implicit cache: pnpm on setup-node with an explicit cache step keyed on all frontend*/pnpm-lock.yaml files. The pnpm store is content- addressable so both suites share it naturally; cross-suite key means a store warm for frontend also benefits frontend-book shards and vice versa. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Dismissing prior approval to re-evaluate 7a8a12a
There was a problem hiding this comment.
🧹 Nitpick comments (1)
.github/workflows/ci-e2e.yml (1)
188-189: ⚡ Quick winInclude architecture in Playwright cache key.
Line 188 currently keys cache by OS + suite + lockfile, but Playwright browser artifacts are architecture-specific. Add
runner.archto avoid cross-arch cache collisions.Proposed change
- key: playwright-${{ runner.os }}-${{ matrix.suite }}-${{ hashFiles(format('{0}/pnpm-lock.yaml', matrix.suite)) }} - restore-keys: playwright-${{ runner.os }}-${{ matrix.suite }}- + key: playwright-${{ runner.os }}-${{ runner.arch }}-${{ matrix.suite }}-${{ hashFiles(format('{0}/pnpm-lock.yaml', matrix.suite)) }} + restore-keys: playwright-${{ runner.os }}-${{ runner.arch }}-${{ matrix.suite }}-
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 4799a07d-6c15-48d2-a438-4da3a219e53a
📒 Files selected for processing (1)
.github/workflows/ci-e2e.yml
Cross-suite key caused spurious invalidations: a lockfile bump in one suite would bust the store cache for the other. Per-suite key means each shard is independently warm/cold on its own lockfile, consistent with all other suite-scoped caches in this job. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Dismissing prior approval to re-evaluate 1d18d0c
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Dismissing prior approval to re-evaluate ec78f60
…-aware Per-suite install broke consumer repos where bin/dev-e2e starts both Vite servers in parallel (billiedoby-scheduling frontend-book shards timed out at "Wait for dev server" because frontend/node_modules was never installed). Revert install and codegen back to the for-dir-in-frontend*/ loop. The pnpm store cache makes this fast on warm runs — prepare scripts on git-ref packages are skipped when the store is populated. Switch pnpm store cache key to union over all lockfiles so all four shards share one cache entry (each shard installs both frontends, so both lockfiles contribute to the same store). Fix latent bug in wait-for-server: frontend-book shards now poll book.lvh.me instead of app.lvh.me, matching the host their Playwright config targets. Playwright install and cache remain scoped to $SUITE — only the suite under test needs browsers, and suites can pin different versions. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Replace hardcoded consumer-specific hostnames (app.lvh.me, book.lvh.me) with the bin/wait-for-e2e convention. The workflow calls the consumer's script with $SUITE as $1 if it exists, otherwise falls back to polling localhost:$DEV_PORT. This follows the repo's existing pattern — every other consumer-specific concern is already a bin/ script. Consumer repos with multi-frontend Caddy setups (like billiedoby) provide their own bin/wait-for-e2e with the hostname mapping. Single-frontend repos need no script — the fallback works. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Dismissing prior approval to re-evaluate ab05aad
Summary
Fix 1: Propagate Playwright/audit exit codes through
teepipes (6 files)cmd | tee filereturnstee's exit code (always 0), masking failures from the left side.set -ealone doesn't help — bash evaluates the pipeline exit code.set -o pipefailfixes this.Playwright (false-green test runs):
ci-e2e.yml— the original, reported influffyx/billiedoby-schedulingPR #194ci-svelte-e2e.yml— same pattern, same fixAudit tools (silent security bypasses):
ci-gem.yml,ci-rails.yml,ci-rails-svelte.yml,ci-svelte.yml—bundler-audit/pnpm audit/bin/audit-frontendpiped toteewithcontinue-on-error: true. The follow-up "Classify audit result" step checksoutcome == 'failure', butoutcomewas alwayssuccessbecauseteewon the pipeline. Real vulnerabilities silently passed CI.Fix 2: Scope e2e setup to the matrix suite only (
ci-e2e.yml)Each shard runs one suite (
cd "$SUITE" && npx playwright test), but three setup steps looped over allfrontend*/directories. Onbilliedoby-scheduling(two suites × 2 shards = 4 jobs), this wasted ~46s/shard because the unused suite'spnpm installtriggeredpreparescripts for private git-branch packages.Changed:
SUITEhoisted to job-level env; the threefor dir in frontend*/loops in Install dependencies, Install Playwright browsers, and Generate GraphQL types replaced with directpnpm --dir "$SUITE"calls.Blast radius (Fix 1)
After landing, repos pinned to
@mainwill start correctly failing when Playwright has failures or audit tools find real vulnerabilities. Expect previously-hidden failures to surface.Reproducer
fluffyx/billiedoby-schedulingPR #194 (commit47e46cc8): shard 1 showed1 failed, 8 did not run, 8 passedbut the GitHub Actions job was green.Test plan
==> Installing— each shard should only show its own suite🤖 Generated with Claude Code
Summary by CodeRabbit
Note
Propagate exit codes through
teepipes in CI workflows usingpipefailset -o pipefailto audit and test steps across multiple CI workflows so that failures in commands piped toteeare correctly surfaced instead of being masked bytee's exit code.SUITEat job level, use explicit pnpm store caching keyed by suite, install Playwright only for the selected suite, and conditionally wait for dev readiness viabin/wait-for-e2e "$SUITE"with a fallback to pollinglocalhost:${DEV_PORT:-4100}.bin/wait-for-e2escript in README.md and notes the hardcodedDEV_PORTfallback in TODOS.md.Macroscope summarized ab05aad.