Skip to content

ci: fold single-grep jobs into steps, call named pnpm scripts - #1465

Merged
thymikee merged 5 commits into
mainfrom
claude/affectionate-fermi-owp5ov
Jul 28, 2026
Merged

ci: fold single-grep jobs into steps, call named pnpm scripts#1465
thymikee merged 5 commits into
mainfrom
claude/affectionate-fermi-owp5ov

Conversation

@thymikee

@thymikee thymikee commented Jul 28, 2026

Copy link
Copy Markdown
Member

Closes #1462.

Summary

  • Folded ios-runner-swift-compat and no-test-di-seams — each just checkout + one rg assertion — into two named steps of a new static-checks job, each keeping its own failure message. This removes two job-scheduling/checkout overheads and two PR status-check lines while keeping the same signal.
  • In layering-guard, replaced the inlined byte-copies of check:layering and depgraph:test with the named pnpm scripts (pnpm check:layering, pnpm depgraph:test), removing the silent-drift risk between the workflow and package.json.
  • affected-selector now calls pnpm check:affected:test — no longer inlined. R8's zero-dep-job closure check (scripts/layering/zero-dep-jobs.ts) used to discover a job's entry scripts by matching literal scripts/**/*.test.ts paths inside the run: block, which a bare pnpm <script> name has none of. zeroDepJobs now also resolves a pnpm <name> invocation against package.json's own scripts and scans the resolved command for entry paths — recursively, so a resolved script that itself calls another named script still has its entries found, with a per-chain visited set so an alias cycle terminates instead of hanging. Covered by new tests: direct resolution, chained aliases, cycle safety, and "a pnpm word that names no real script resolves to nothing" (so pnpm install etc. can't be mistaken for a script name).
  • git grep'd every workflow for other run: blocks duplicating a package.json script body and fixed each one to call it by name instead, keeping each job's own CI-specific trailing flags (retries, artifact paths, etc. — verified pnpm forwards these through unchanged): conformance-differential.yml, conformance-regenerate.yml, linux.yml, macos.yml, perf-nightly.yml (×2), replays-nightly.yml (×4), size.yml (×2).

What was deliberately left alone

  • publish-mcp-registry.yml's node scripts/sync-mcp-metadata.mjs --check (matches check:mcp-metadata) stays inlined: that job provisions Node via plain actions/setup-node, never the repo's ./.github/actions/setup-node-pnpm, so pnpm is never installed there — calling the pnpm script would fail before publishing on a real release. Commented in the workflow so it isn't "fixed" again.

⚠️ Needs a human: branch protection

I don't have visibility into this repo's branch protection settings from here. If iOS Runner Swift Compatibility or No test-only DI seams are configured as required status checks, those check names will disappear once this merges (replaced by a single Static Checks job), and PRs could get stuck unable to satisfy an unsatisfiable required check. Please verify in Settings → Branches, and if either name is required, update the required-checks list to Static Checks before or right after merging this.

Verification

  • pnpm check:layering — passes locally (R1–R9, including R8 zero-dep-job closure, 34 tests).
  • pnpm depgraph:test, pnpm check:affected:test — pass.
  • pnpm format:check, pnpm lint — clean.
  • All edited workflow YAML files parse correctly.
  • Full CI green on this PR (Static Checks, Layering Guard, Affected-check Selector, and every other job).

Generated by Claude Code

- Merge ios-runner-swift-compat and no-test-di-seams (each just
  checkout + one rg assertion) into steps of a new static-checks job,
  keeping each step's own failure message. Removes two job-scheduling/
  checkout overheads and two PR status-check lines.
- Replace the layering-guard job's inlined copies of check:layering and
  depgraph:test with the named pnpm scripts, removing the silent-drift
  risk between the workflow and package.json.
- Fix the same drift in conformance-regenerate.yml, which inlined
  maestro:conformance:regenerate byte-for-byte.
- Leave affected-selector's inline node invocation as-is: R8's zero-dep
  closure check (scripts/layering/zero-dep-jobs.ts) finds a job's entry
  scripts by matching literal paths in the run: block, so switching to
  `pnpm check:affected:test` would zero out its entries and make R8
  fail closed. Documented inline why this one stays inlined.
- Leave publish-mcp-registry.yml's sync-mcp-metadata --check alone: that
  job never runs the setup-node-pnpm action, so pnpm isn't provisioned
  there at all.

Refs #1462
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 1.87 MB 1.87 MB 0 B
JS gzip 602.0 kB 602.0 kB 0 B
npm tarball 719.9 kB 719.9 kB 0 B
npm unpacked 2.52 MB 2.52 MB 0 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 28.3 ms 27.9 ms -0.4 ms
CLI --help 57.7 ms 58.2 ms +0.5 ms

Top changed chunks: no changes in the largest emitted chunks.

@thymikee

Copy link
Copy Markdown
Member Author

Blocking architecture cleanup at ffd37a2758457832bedaf450ed499e4b45fa5d76: affected-selector still needs an inline Node invocation because R8 discovers entries by regexing literal test paths from workflow text. That hidden parser coupling is the workaround this PR should remove. Teach R8 entry discovery to resolve the named package script (or consume explicit typed entry metadata), cover that resolution, then switch the workflow to pnpm check:affected:test and delete the explanatory paragraph.

…nline copy

R8's zero-dep-job entry scan matched literal script paths in a run: block,
so a bare `pnpm <script>` invocation found zero entries and R8 failed
closed — the reason affected-selector kept an inline node command instead
of calling pnpm check:affected:test (#1462). zeroDepJobs now also resolves
a pnpm script name against package.json and scans the resolved command for
entry paths, so affected-selector can call the named script like every
other job.

Also replaced the other workflows' inlined copies of named package.json
scripts (test:replay:*, perf, perf:android, maestro:conformance:differential,
check:mcp-metadata, size) with their pnpm names, keeping each job's
CI-specific trailing flags — found via a repo-wide sweep for any run: block
whose text duplicates a scripts entry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L67kDSTAJwaoLCwANEJFRM

Copy link
Copy Markdown
Member Author

Done in fdc6132: zeroDepJobs in scripts/layering/zero-dep-jobs.ts now also resolves a bare pnpm <script> invocation against package.json's own scripts and scans the resolved command for entry paths, instead of requiring a literal path in the workflow text. affected-selector now calls pnpm check:affected:test like every other job, and the explanatory paragraph is gone. Added coverage for the resolution (including the "pnpm install isn't a script" case) and confirmed pnpm check:layering still passes with 932 source files / R8 green.

While auditing, I also swept every workflow for other run: blocks that duplicate a named package.json script and switched those to their pnpm <name> form too (test:replay:*, perf, perf:android, maestro:conformance:differential, check:mcp-metadata, size), keeping each job's own trailing CI flags (retries, artifact paths, etc.) — verified pnpm forwards those through unchanged.


Generated by Claude Code

…ermi-owp5ov

# Conflicts:
#	.github/workflows/ci.yml
@thymikee

Copy link
Copy Markdown
Member Author

Two blockers remain on the current head:

  1. Release workflow regression: .github/workflows/publish-mcp-registry.yml now runs pnpm check:mcp-metadata, but that job only uses actions/setup-node; it never provisions pnpm. The release/manual publication path will therefore fail before publishing. Keep the direct Node invocation or provision the repository-pinned pnpm toolchain in this job.

  2. R8 still has a hidden alias boundary: the new resolver expands only the first package-script command. If that resolved command invokes another pnpm script, the nested script’s entry files are not added to the zero-dependency closure; a dependency-bearing nested entry can remain invisible to R8. Recursively resolve package-script aliases with a visited set and cycle tests, or fail closed whenever a resolved script contains a nested alias.

The direct pnpm check:affected:test case and current CI are green, but neither exercises these two paths.

…solution

publish-mcp-registry.yml's job only provisions Node via actions/setup-node,
never the repo's setup-node-pnpm action, so pnpm is never installed there —
the earlier sweep's `pnpm check:mcp-metadata` would have broken the release
path. Reverted to the direct node invocation with a comment explaining why,
matching the PR's own stated rationale for leaving it alone.

zeroDepJobs' pnpm-alias resolution only expanded one level: a resolved
script that itself invoked another named pnpm script had its entries
silently dropped from R8's closure. resolveRunEntries now recurses through
chained aliases with a per-chain visited set, so a nested alias's entries
are found and a cycle stops re-expanding a repeated name instead of
recursing forever. Added coverage for both the chained and cyclic cases.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L67kDSTAJwaoLCwANEJFRM

Copy link
Copy Markdown
Member Author

Both confirmed and fixed in f95e307:

  1. Reverted publish-mcp-registry.yml back to node scripts/sync-mcp-metadata.mjs --check — that job only runs actions/setup-node, never ./.github/actions/setup-node-pnpm, so pnpm check:mcp-metadata would indeed have failed before publishing on a real release. My earlier sweep overrode this PR's own stated rationale for leaving it inlined; added a comment so it doesn't get "fixed" again.
  2. resolveRunEntries in scripts/layering/zero-dep-jobs.ts now recurses through chained pnpm aliases (a per-chain visited set stops it re-expanding a name it's already walked, so a cycle terminates instead of hanging) — a resolved script that itself calls another named script no longer drops that script's entries from R8's closure. Added tests for both the chained case and a two-script cycle.

pnpm check:layering (34 tests, R8 green), depgraph:test, check:affected:test, format:check, and lint all pass locally.


Generated by Claude Code

@thymikee

Copy link
Copy Markdown
Member Author

Re-reviewed exact head f95e307: both prior code findings are fixed with effective regression coverage, and all checks are green. One readiness item remains: please update the PR body, which still says affected-selector was left inline and understates the final multi-workflow scope. The code is clean; the review description should match what will ship.

Copy link
Copy Markdown
Member Author

Updated the PR body to match f95e307: affected-selector is now correctly described as calling pnpm check:affected:test (not left inline), and the summary itemizes the full multi-workflow sweep (conformance-differential.yml, conformance-regenerate.yml, linux.yml, macos.yml, perf-nightly.yml, replays-nightly.yml, size.yml) alongside the R8 recursive-alias-resolution work.


Generated by Claude Code

…ermi-owp5ov

# Conflicts:
#	.github/workflows/replays-nightly.yml

Copy link
Copy Markdown
Member Author

Merged latest main (216502e) — a new commit there ("expand simulator e2e coverage", #1408) added a --udid flag and three new steps to the same "Run iOS simulator replay suite" step in replays-nightly.yml that this PR simplified. Resolved by keeping main's new steps/flag and applying the pnpm test:replay:ios name-swap to the updated command. All other conflicting files (ci.yml, conformance-differential.yml, macos.yml, perf-nightly.yml, scripts/layering/check.ts) auto-merged cleanly.

pnpm check:layering (34 tests, R8 green, 933 source files), depgraph:test, check:affected:test, format:check, lint all pass on the merged tree.


Generated by Claude Code

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Jul 28, 2026
@thymikee

Copy link
Copy Markdown
Member Author

Re-reviewed exact head 216502e. The main merge and sole replay-workflow conflict resolution are clean: the iOS simulator UDID and expanded fixture-backed E2E from main are preserved, while Android, iOS simulator/device, and macOS still route through the intended named pnpm scripts with their CI retry and artifact flags intact. Exact-head checks are green. Code review is clean and ready for human review; the documented branch-protection check-name update remains maintainer-owned follow-up.

@thymikee
thymikee merged commit 255deb6 into main Jul 28, 2026
27 checks passed
@thymikee
thymikee deleted the claude/affectionate-fermi-owp5ov branch July 28, 2026 18:56
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-28 18:56 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: fold two single-grep jobs into steps and call named pnpm scripts instead of inlined copies

2 participants