ci: cache cleanup, duration reporting, extension waste fix, composite setup action - #7379
Merged
Conversation
… 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.
Contributor
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. 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
Flags with carried forward coverage won't be shown. Click here to find out more. |
18 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-usenode_modulescaches 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 byrefnot key string) the moment it closes. Usespull_request_target(needed since deleting a cache requiresactions: write, and a fork-triggeredpull_requestrun 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 whetherci.ymlis trending slower over time. Reports p50/p95 wall-clock duration and failure rate for the trailing week, split bypushvspull_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.ymlbuilding@loopover/ui-miner. It ran the fullui:buildaggregate, which also builds a full separate Vite app this workflow never uploads or deploys. Swapped to the same turbo-routed buildci.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 acrossvalidate-code,validate-tests, andvalidate-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 localuses: ./pathaction needs the repo already on disk to find its ownaction.yml, so each call site keeps its ownactions/checkout(fetch-depth varies) immediately before invoking this action.Doc fixes. Surfaced Codecov Test Analytics (already auto-enabled from the JUnit uploads
ci.ymlalready sends, just never linked from anywhere) and fixed two stale claims in the contributing skill: "the single required status check isvalidate" (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
actionlintwrapper (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
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlint(the real workflow-file check; see the known-gap note above for what it doesn't cover)yamlparser for structural correctness (runs.using: composite, everyrun:step has an explicitshell:, 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.ref) was dry-run against this repo's real, already-closed PRs viagh apibefore 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.mjsrun 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).ui-preview.ymlfix verified locally: ran the exact replacement command sequence, confirmedapps/loopover-ui/distbuilds correctly andapps/loopover-miner-ui/distis never created.test/unitsuite (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 dedicatedci-composite-setup-workspace.test.tsrather than weakened.npm run typecheck/npm run test:coverage— not run in full; this PR touches nosrc/**file except the newscripts/ci-duration-report.mjs(a standalone.mjsscript, 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
cache-cleanup.yml'spull_request_targetuse is deliberately scoped to the minimum needed (actions: writeonly, 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.UI Evidencesection — N/A, no visible/UI change.Notes
.github/workflows/**(a guarded path), so it'll be held for manual owner review rather than auto-merged.