Skip to content

chore(ci): tier B of the CI audit — the release cache pair and the site-node composite - #968

Merged
IvanWng97 merged 8 commits into
mainfrom
worktree-ci-cache-tier-b
Sep 1, 2026
Merged

chore(ci): tier B of the CI audit — the release cache pair and the site-node composite#968
IvanWng97 merged 8 commits into
mainfrom
worktree-ci-cache-tier-b

Conversation

@IvanWng97

Copy link
Copy Markdown
Owner

Tier B of the CI audit (items 8-11). Was #967, stacked on #966; that PR closed permanently when the merged base branch was deleted, so this is the same branch re-targeted at main (tier-A content arrives via a merge of the squash, auto-resolved).

What

  • Release cache pair — the build and deb jobs rebuild the one shared target (aarch64-unknown-linux-gnu, identical flags since chore(ci): tier A of the CI audit — composites, caches, and one-authority pins #966's target-derived --no-default-features) into per-job caches; both now use shared-key: release-<target>. Honest scope, per review: a fresh tag still pays both cold (the jobs start together; tag caches are tag-scoped) — the wins are same-tag re-runs of a failed deb leg and one cache entry instead of two (cache is currently over the 10 GB ceiling).
  • setup-site-node composite — pages.yml and site.yml shared ~20 verbatim lines of Node/npm/Playwright setup; the composite owns them. The Node major is a composite input (default 26) — one authority feeding setup-node and an output pages.yml forwards to withastro/action (which runs its own Node setup and would otherwise pick a different major). The ci-obs pin follows the moved step: the composite must keep the exact pinned npm install, and each workflow must call the composite un-conditioned exactly once. Both workflows' paths: lists now include the composite (review-caught: a composite-only change previously got zero runtime exercise).

Dispositions of the audit's items 9-10

  • Item 9 (cache pressure) — the shared-key halves release's footprint; the broader levers (Linux job shared-key/save-if consolidation) need restore-rate measurement first — most main-branch jobs build with different flag sets, and forcing a shared key across them thrashes. Surfaced with that caveat.
  • Item 10 (non-Rust PR skips) — the CodeQL half is REFUTED by mechanism: main.rego pins on.pull_request to exact-null ("any filter lets some PR merge unanalyzed"); changing that is a security-policy decision, not a cleanup. The ci.yml step-level skip design (~400 runner-min/week) remains available but wants its own design-gated PR: a changes-filter job + if: on expensive steps, inverted default, aggregators and policy untouched. Say the word and it becomes PR 3.

Review (two-lens gate)

3 lenses (correctness / design / whole-file comment audit): APPROVE-WITH-NITS ×2, REQUEST-CHANGES ×1 (both its HIGHs fixed — one on the parent branch as #966's round 2, one here). Fold ec88fdd4. Probe highlights: rust-cache shared-key semantics fetched from its README; every policy mutation fires the right deny (install deleted, call deleted, if: added — both levels); zizmor parses and still suppresses inside the composite; the deleted-outputs case is actionlint-caught while the input-shaped authority removes the dangling-id case structurally.

Deploy-watch note: withastro/action + the output forwarding live only in pages.yml, which never runs on PRs — watch the first main-push pages run's "setup node" step resolve Node 26 before trusting the chain end-to-end.

Surfaced: a bootstrap-before-npm ci ordering rule inside the composite (new gate — needs its own small PR if wanted); lighthouse_workflow_path naming debt (13 uses, site.yml's check job is 1-of-10 lighthouse).

🤖 Generated with Claude Code

https://claude.ai/code/session_01K6LG4b2iq2tRHvJ3AhFXDU

IvanWng97 and others added 8 commits August 31, 2026 18:33
… job aggregators

setup-alsa: 11 bare apt-get copies (4 comment variants, none retried) become
one composite carrying the #633 WHY and the smoke job's mirror-retry envelope
— the flake class that costs a full re-run per occurrence. require-jobs: the
three byte-identical jq aggregators become one composite (ci.yml's gate keeps
its policy-pinned per-group env reads). The hygiene job's five Go tools cache
on a key derived from this workflow file, so a version bump can never serve a
stale binary (148s of a 189s job was compiling them). codspeed gains the
standard concurrency block and loses a duplicate permissions grant; the
Chromium-before-check comment moves onto the step it describes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6LG4b2iq2tRHvJ3AhFXDU
The Linux --no-default-features flag derives inside build-target from the
target (it was a byte-identical expression + comment at both call sites and a
third telling in the recipe); `just workspace-version` owns the Cargo.toml
version parse (release tag validation and `just bump` both read it;
packaging-build keeps its just-free inline form); the cargo-public-api pin
becomes API_PUBLIC_API, asserted at run time by _api-nightly so a divergence
between ci-lint's installer and the goldens fails loud instead of churning.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6LG4b2iq2tRHvJ3AhFXDU
…vocation helper

ci-supplemental.yml was deleted in #956; subtracting a name that no longer
exists is a no-op a green gate can never surface, so the exemption, its
clause, its fixture row, and its test go. The behavior test's seven publisher
blocks share run_publisher, varying only the review body and head pair.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6LG4b2iq2tRHvJ3AhFXDU
…ck, and honest prose

Lens dispositions (3 lenses, all APPROVE-WITH-NITS/REQUEST-CHANGES on
in-scope items):
- FIXED require-jobs passing vacuously on a missing results input (probe:
  actionlint accepts the omission; jq exits 0 on empty) — in-composite guard.
- FIXED the deny message + test literal still saying "non-advisory" after the
  advisory class was deleted (paired edit, the message now names what it pins).
- FIXED workspace-version stealing build's comment block (the string-anchor
  class again) and its doc overclaiming "one authority" while packaging-build
  keeps a deliberate just-free parse (now said in prose at the recipe).
- FIXED codspeed losing the workflow-level read floor (the concurrency edit
  had replaced it; the cited job-scoping precedent is about called workflows).
- FIXED the go-tools bin dir being derived in one step and spelled in the
  cache path (a hit could restore off-PATH); one literal spelling + the WHY.
- FIXED _api-nightly → _api-toolchain (it now asserts AND provisions), its
  absent-tool message parsing in both branches, and the API pin story moving
  onto API_PUBLIC_API with the echo homes trimmed to references.
- FIXED comment rot the diff introduced: lychee comment back on its step,
  "warm rebuild" → cold reinstall, mutants' DEFAULT-features WHY restored,
  smoke's ffmpeg comment now references the composite envelope, the publish
  job keeps only its stranding consequence, the unsupported "drifted once
  already" history claim dropped, the unquoted-$flags constraint stated.
- REFUTED the ALSA guard-home question: the one polymorphic caller is where
  the guard already lived; macOS no-op is correct (CoreAudio).
- SURFACED (PR body): packaging-build's independent version parse, the bare
  musl-tools install on the tag path, the aggregators' new checkout network
  dependency, and the tag-time-only surfaces exercised locally instead.
plan-miss: the workspace-version insertion point — the known string-anchor
trap, caught by two lenses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6LG4b2iq2tRHvJ3AhFXDU
d32afcb deleted the middle line of a three-sentence comment, leaving
"default features pull" dangling; the rodio -> cpal -> ALSA chain was not
relocated anywhere (setup-alsa names only alsa-sys). Revert-shaped: the
original meaning returns in full.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6LG4b2iq2tRHvJ3AhFXDU
The build and deb jobs rebuild the same aarch64 target with the same flags
into per-job caches, so every tag paid a second cold cross build; both now
share release-<target>. pages.yml and site.yml carried ~20 verbatim lines of
Node/npm/Playwright setup; the setup-site-node composite owns them, exposes
the Node major for withastro, and the ci-obs pin follows the moved step: the
composite must keep the exact pinned install, and each workflow must call it
un-conditioned exactly once (the same protection, one authority).

CodeQL paths-ignore was attempted and REVERTED: main.rego deliberately pins
on.pull_request to exact-null ("any filter lets some PR merge unanalyzed").

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6LG4b2iq2tRHvJ3AhFXDU
…rity, and the honest cache claim

Lens dispositions:
- FIXED both site workflows' paths lists omitting the new composite — a
  composite-only change got zero runtime exercise and no redeploy, falsifying
  pages.yml's own "every input the build reads" invariant.
- FIXED the dangling-step-id class structurally: the Node major is now a
  composite INPUT (default 26) feeding setup-node and the output — no step id
  to rename out from under outputs.value (the proposed detection rule became
  unnecessary; 1,218 published action.yml files use the inputs-in-outputs
  form). The deploy still deserves one watched pages.yml run — noted in the PR.
- FIXED the shared-key comment overclaiming: build and deb start together and
  tag caches are tag-scoped (GitHub docs, fetched), so a fresh tag pays both
  cold either way; the honest wins are same-tag re-runs and one cache entry
  instead of two — the second sentence now guards against a future
  needs:-build "fix" that would serialize the release.
- FIXED the composite's comments: version-neutral npm prose, the chromium
  ordering stated as the composite's own constraint, the withastro WHY on the
  output; the rego comment split onto the helper each half constrains; the
  conditioned-call test uses the constant so a ref rename cannot green it.
- SURFACED, not folded: a bootstrap-before-npm-ci ordering rule (a NEW gate —
  the pre-change policy never pinned ordering either, and fix rounds do not
  add gates); lighthouse_workflow_path naming (pre-existing, 13 uses).
- REFUTED (was SURFACED): CodeQL path-filtering — main.rego pins
  on.pull_request to exact-null with the WHY; the mechanism decides unless the
  owner changes the policy itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6LG4b2iq2tRHvJ3AhFXDU
# Conflicts:
#	.github/workflows/pages.yml
@IvanWng97 IvanWng97 added the needs-human-verify AI-authored: automated checks green; awaiting a human's visual/manual verification before merge label Sep 1, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

Claude Security Review

Head: 370aafbf55a801c5efef1010f2b3fc0a59b55a42

Findings: 0 — No findings

This diff only refactors CI workflow/action YAML and OPA policy for the site build pipeline; it touches none of the defined trust boundaries (hook shim, socket/pipe transport, settings/config writes, path/home/process/credential handling, or transcript/hook/JSONL/pack ingestion), so there are no security-relevant changes.


Automated read-only review by Claude Code

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

Claude Review

Head: 370aafbf55a801c5efef1010f2b3fc0a59b55a42

Findings: 0 — No findings

Clean CI-only refactor: dedupes the site's Node/npm/Playwright bootstrap from pages.yml and site.yml into a new .github/actions/setup-site-node composite, updates trigger paths, and rewrites the corresponding OPA rego rules and tests to match (github_workspace/pinned_npm_setup_steps cleanly replaced with site_node_action_installs/site_node_call_steps, no dangling references). Verified the composite's step order, working directories, node-version output propagation, and the release.yml rust-cache shared-key change (correctly scoped to the one target — aarch64-unknown-linux-gnu — both build and deb jobs actually share); no architecture-invariant, correctness, or DRY violations found.


Automated read-only review by Claude Code

@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.73%. Comparing base (b37590c) to head (370aafb).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #968   +/-   ##
=======================================
  Coverage   95.72%   95.73%           
=======================================
  Files         197      197           
  Lines       58303    58303           
=======================================
+ Hits        55811    55814    +3     
+ Misses       2492     2489    -3     
Components Coverage Δ
pixtuoid-core 97.67% <ø> (+0.01%) ⬆️
pixtuoid-scene 95.40% <ø> (ø)
pixtuoid 94.19% <ø> (ø)
pixtuoid-hook 96.54% <ø> (ø)
pixtuoid-web 95.78% <ø> (ø)
see 2 files with indirect coverage changes
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@IvanWng97
IvanWng97 merged commit 76c25bc into main Sep 1, 2026
48 checks passed
@IvanWng97
IvanWng97 deleted the worktree-ci-cache-tier-b branch September 1, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human-verify AI-authored: automated checks green; awaiting a human's visual/manual verification before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant