Skip to content

ci: cache cleanup, duration reporting, extension waste fix, composite setup action - #7379

Merged
JSONbored merged 1 commit into
mainfrom
claude/ci-improvements-batch
Jul 19, 2026
Merged

ci: cache cleanup, duration reporting, extension waste fix, composite setup action#7379
JSONbored merged 1 commit into
mainfrom
claude/ci-improvements-batch

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

Six independent items from the "is everything 100% optimized" follow-up audit — bundled since each is small, isolated, and none conflict.

Clean up dead fork-PR caches (cache-cleanup.yml, new). Live cache usage was at ~10.7GB of the 10GB budget, 87% of it single-use node_modules caches from contributor PRs that auto-close one-shot under this repo's gate and can never be restored again. Deletes a PR's own cache entries (any prefix, scoped by ref not key string) the moment it closes. Uses pull_request_target (needed since deleting a cache requires actions: write, and a fork-triggered pull_request run is always capped to a read-only token) but never checks out or executes anything from the PR's own code — only reads the trusted PR number GitHub itself populates.

Weekly CI duration report (ci-duration-report.yml + scripts/ci-duration-report.mjs, new). Nothing currently tracks whether ci.yml is trending slower over time. Reports p50/p95 wall-clock duration and failure rate for the trailing week, split by push vs pull_request, excluding cancelled runs from both (confirmed live: ~9% of recent runs are cancelled — almost always a rapid re-push superseding its predecessor, not CI breaking). Purely additive, read-only, can't fail a PR.

Stop ui-preview.yml building @loopover/ui-miner. It ran the full ui:build aggregate, which also builds a full separate Vite app this workflow never uploads or deploys. Swapped to the same turbo-routed build ci.yml's own "UI build" step already uses, minus the wasted half.

Extracted .github/actions/setup-workspace, a composite action covering the neutralize-npmrc/Setup-Node/restore-install-save-node_modules sequence hand-copied identically across validate-code, validate-tests, and validate-tests-merge — the same kind of drift that caused a real cache-key mismatch bug this repo already hit once this session (two jobs' Turborepo cache pair silently diverged when one was edited and the other wasn't). It deliberately does not include the checkout step: a local uses: ./path action needs the repo already on disk to find its own action.yml, so each call site keeps its own actions/checkout (fetch-depth varies) immediately before invoking this action.

Doc fixes. Surfaced Codecov Test Analytics (already auto-enabled from the JUnit uploads ci.yml already sends, just never linked from anywhere) and fixed two stale claims in the contributing skill: "the single required status check is validate" (Superagent Security Scan is also required — confirmed live via the branch protection API) and "CI shards into 2" (it's 6).

A known gap, called out rather than routed around: this repo's own actionlint wrapper (scripts/actionlint.mjs) only scans .github/workflows/**, not .github/actions/**, and I found the underlying tool doesn't auto-detect composite action files the way it detects workflows — I tried widening the glob, it produced false-positive "missing jobs/on section" errors treating the action file as a malformed workflow, so I reverted that attempt rather than ship a change that would break the required lint check for every future PR. The new composite action's YAML was hand-validated for syntax/structure instead (see Validation). This gap is real and worth closing properly in a follow-up, not silently absorbed here.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format.
  • This PR is focused — six items, but all CI/build-tooling hygiene, none touching backend/UI/MCP application code.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked a currently open issue this PR resolves — N/A, maintainer-initiated build-tooling work.

Validation

  • git diff --check
  • npm run actionlint (the real workflow-file check; see the known-gap note above for what it doesn't cover)
  • The composite action's YAML hand-validated via Node's yaml parser for structural correctness (runs.using: composite, every run: step has an explicit shell:, inputs/outputs match what call sites reference) since neither this repo's actionlint wrapper nor a local run can fully exercise a composite action outside real GitHub Actions.
  • The cache-cleanup workflow's core query logic (list caches scoped to a given PR's ref) was dry-run against this repo's real, already-closed PRs via gh api before writing the workflow — confirmed it correctly finds leftover cache entries (including non-node_modules ones) for a closed PR. The delete call itself was not executed against the live repo as part of this verification.
  • scripts/ci-duration-report.mjs run for real against this repo (--days=1) before and after refining the cancelled-run exclusion — confirmed it pulls real data and the failure-rate definition is now accurate (31% not 36% once cancelled runs are excluded from the denominator too).
  • The ui-preview.yml fix verified locally: ran the exact replacement command sequence, confirmed apps/loopover-ui/dist builds correctly and apps/loopover-miner-ui/dist is never created.
  • Ran the full local test/unit suite (978 files, 18,482 tests) after all changes — all passing. Two existing meta-tests (ci-dependency-cache.test.ts, observability-ci.test.ts) needed updates to match the composite-action extraction — moved to a new dedicated ci-composite-setup-workspace.test.ts rather than weakened.
  • npm run typecheck / npm run test:coverage — not run in full; this PR touches no src/** file except the new scripts/ci-duration-report.mjs (a standalone .mjs script, not part of the typechecked/coverage-graded backend).
  • npm audit --audit-level=moderate — not applicable; no dependency changes.

If any required check was skipped, explain why: this PR is CI/build-tooling configuration, not application source — the skipped commands aren't applicable, and every actually-relevant command (including hand-validation of the one piece no automated tool here covers) is listed above.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • cache-cleanup.yml's pull_request_target use is deliberately scoped to the minimum needed (actions: write only, no checkout, no execution of PR-controlled code) — the specific risk pattern this trigger type is usually flagged for doesn't apply here; explained in the Summary above.
  • Auth/cookie/CORS/GitHub App/Cloudflare/session changes include negative-path tests — N/A.
  • API/OpenAPI/MCP behavior updated and tested where needed — N/A.
  • UI changes use live API data or real empty/error/loading states — N/A, no UI behavior change.
  • Visible UI changes include a UI Evidence section — N/A, no visible/UI change.
  • Public docs/changelogs updated where needed; changelogs are only edited for release-prep PRs (none touched here).

Notes

  • Touches .github/workflows/** (a guarded path), so it'll be held for manual owner review rather than auto-merged.
  • The composite-action extraction is the one item here I'd most want watched closely on this PR's own CI run, since neither this repo's actionlint nor a local run can fully simulate a composite action outside real GitHub Actions execution — everything else in this PR was verified with real commands against the real repo.
  • Not included: duration-aware test sharding (the largest remaining item from the audit — shard 4 consistently runs slower than shard 5 across every sampled run). That needs a genuinely new script (bin-packing test files by historical duration) rather than a config change, so it's a separate follow-up rather than bundled here.

… setup action

Six independent CI hygiene/reliability improvements from the "is everything
100% optimized" follow-up audit, bundled since each is small and none
conflict:

- Clean up dead fork-PR caches (.github/workflows/cache-cleanup.yml): live
  cache usage was at ~10.7GB of the 10GB budget, 87% of it single-use
  node_modules caches from contributor PRs that auto-closed one-shot and
  can never be restored again. Deletes a PR's own cache entries (any
  prefix -- node_modules, Turborepo, tsbuildinfo -- scoped by ref, not key
  string) the moment it closes, via pull_request_target since deleting a
  cache needs actions:write and a fork-triggered pull_request run is
  always capped to a read-only token. Never checks out or executes
  anything from the PR's own code, only ever reads the trusted PR number
  GitHub itself populates.

- Weekly CI duration report (.github/workflows/ci-duration-report.yml +
  scripts/ci-duration-report.mjs): nothing currently tracks whether ci.yml
  is trending slower over time. Pulls p50/p95 wall-clock duration and
  failure rate for the trailing week, split by push vs pull_request since
  they run different amounts of work, excluding cancelled runs from both
  (confirmed live: ~9% of recent runs are cancelled, almost always a rapid
  re-push superseding its predecessor, not CI breaking -- counting them as
  failures would misrepresent the real rate). Purely additive, read-only,
  can't fail a PR.

- Stop ui-preview.yml building @loopover/ui-miner: it ran the full
  ui:build aggregate, which also builds a full separate Vite app this
  workflow never uploads or deploys. Swapped to the same turbo-routed
  build ci.yml's own "UI build" step already uses, minus the wasted half.

- Extracted .github/actions/setup-workspace, a composite action covering
  the neutralize-npmrc/Setup-Node/restore-install-save-node_modules
  sequence that was hand-copied identically across validate-code,
  validate-tests, and validate-tests-merge -- the same kind of drift that
  caused a real cache-key mismatch bug this repo already hit once this
  session (two jobs' Turborepo cache pair silently diverged when one was
  edited and the other wasn't). Does NOT include the checkout step itself:
  a local `uses: ./path` action needs the repo already on disk to find its
  own action.yml, so each call site keeps its own actions/checkout
  (fetch-depth varies) immediately before invoking this action.

- Surfaced Codecov Test Analytics (already auto-enabled from the JUnit
  uploads ci.yml already sends, just not linked from anywhere) and fixed
  two stale claims in the contributing skill docs: "the single required
  status check is validate" (Superagent Security Scan is also required,
  confirmed via the live branch protection API) and "CI shards into 2"
  (it's 6).

test/unit/ci-dependency-cache.test.ts's node_modules-cache assertions
moved to the new test/unit/ci-composite-setup-workspace.test.ts (now
checking the composite action's own content plus each call site's
invocation), since that logic no longer lives directly in ci.yml's step
list. test/unit/observability-ci.test.ts's incidental npmrc-step canary
check was swapped for a "Setup workspace" one serving the same
parse-sanity purpose.

Note: this repo's own actionlint wrapper (scripts/actionlint.mjs) only
scans .github/workflows/**, not .github/actions/**, and the underlying
tool doesn't auto-detect composite action files the way it does for
workflows (confirmed by trying and reverting a widen-the-glob attempt --
it produced false-positive "missing jobs/on section" errors). The new
composite action's YAML was hand-validated for syntax/structure instead;
this gap is real and worth closing properly in a future PR, not silently
routed around here.
@JSONbored JSONbored self-assigned this Jul 19, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.11%. Comparing base (814f5b8) to head (fca1486).
⚠️ Report is 5 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7379   +/-   ##
=======================================
  Coverage   91.11%   91.11%           
=======================================
  Files         714      714           
  Lines       72460    72460           
  Branches    19970    19970           
=======================================
  Hits        66019    66019           
  Misses       5401     5401           
  Partials     1040     1040           
Flag Coverage Δ
rees 88.56% <ø> (ø)
shard-1 41.61% <ø> (ø)
shard-2 35.50% <ø> (ø)
shard-3 31.65% <ø> (ø)
shard-4 31.77% <ø> (ø)
shard-5 30.43% <ø> (+<0.01%) ⬆️
shard-6 43.45% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

@JSONbored
JSONbored merged commit 6c834ab into main Jul 19, 2026
17 checks passed
@JSONbored
JSONbored deleted the claude/ci-improvements-batch branch July 19, 2026 23:13
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.

1 participant