ci: slash GitHub Actions minutes via paths-ignore + consolidation + caching #126

Merged
varutasu merged 1 commit from slash-ci-minutes into main 2026-06-04 17:40:37 -04:00
varutasu commented 2026-06-04 17:32:59 -04:00 (Migrated from github.com)

Why

GitHub Actions on PRs #124 + #125 hit a billing block today ("recent account payments have failed or your spending limit needs to be increased"). Per the user's max-savings preference, this PR aggressively reduces minute usage so CI doesn't hit the limit again on the rest of the in-flight convoy work.

What changed

1. `paths-ignore` on `ci.yml` + `preview-smoke.yml` (biggest win)

Doc-only PRs now trigger ZERO GitHub Actions jobs. Both workflows skip when ALL changed files match:

```yaml
paths-ignore:

  • '.convoys/**'
  • '**/*.md'
  • 'docs/**'
  • 'AGENTS.md'
  • '.cursor/**'
  • 'README.md'
    ```

Vercel still builds and Vercel comments still fire — Vercel is not on the Actions billing.

`visual-diff.yml` unchanged — it was already cost-conscious via a positive `paths:` allowlist (`pages/`, `components/`, `styles/**`, etc.).

2. Consolidate 6 grep-only forbidden-* jobs into 1

Previously 6 jobs × ~3s `actions/checkout` = ~18s of redundant checkout per PR. Merged into a single `forbidden-patterns` job with 6 sequential `::group::` sections, one FAIL flag at the bottom. All 6 checks still surface every violation in one run — same diagnostic behavior, per-file `::error file=...::msg` annotations preserved.

Removed top-level job names:

  • `forbidden-endpoints`
  • `forbidden-cors-headers`
  • `forbidden-client-side-llm-keys`
  • `forbidden-modal-shell-without-primitive`
  • `forbidden-deprecated-color-aliases`
  • `forbidden-stale-strings`

`pr-health-rollup.yml` only looks up `Lint` and `Schema map up to date` by name — unaffected.

3. Cache `node_modules` + Playwright browsers

  • `node_modules` cache (lint / test / migrate / preview-smoke / visual-diff): keyed by `package-lock.json` hash. Cuts `npm ci` from ~30-45s to 3-5s on cache hit. `setup-node@v4`'s built-in `cache: npm` (caches `/.npm`) stays layered above this.
  • Playwright browsers cache (preview-smoke / visual-diff): keyed by the resolved `@playwright/test` version from `package-lock.json`. Cache invalidates on any version bump. On cache hit, only `npx playwright install-deps chromium` runs — saves ~15-25s/run.

Files

File Diff
`.github/workflows/ci.yml` +130 / -107
`.github/workflows/preview-smoke.yml` +35 / -3
`.github/workflows/visual-diff.yml` +27 / -3
`AGENTS.md` +5 / -3

Estimated savings

PR type Before After Reduction
Doc-only PR ~6-7 min Actions 0 min 100%
Code-touching PR (cache hit) ~6-7 min ~3-4 min ~40-50%
Code-touching PR (cache miss, e.g. new dep) ~6-7 min ~5-6 min ~10-15%
Weighted (typical convoy mix: ~30% docs) ~50-60%

This is short of the 70-80% I floated in chat — the real ceiling is limited by lint / vitest / migrate / Playwright runtime itself, all of which are kept on code-touching PRs (they're high-signal).

Verification

  • All 3 workflow YAMLs parse (`python3 yaml.safe_load`).
  • `npm run lint` passes (1 pre-existing unrelated warning).
  • `npm run test:run`: 118/118 tests pass.
  • `forbidden-patterns` logic is byte-equivalent to the 6 original jobs' bash bodies. Differences: per-check `::group::`/`::endgroup::` framing, shared FAIL flag instead of per-job `exit 1`, and renamed local arrays (`FOUND` → `LLM_FOUND` / `MODAL_FOUND` / `STRING_FOUND`) to avoid scope clobbering in one big bash step.

Test plan

This PR itself will be the canary — it touches `.github/workflows/**` so:

  • The new `Forbidden patterns (6 checks)` check appears (not the 6 old ones).
  • `Lint` / `Unit tests (vitest)` / `Migrations apply (node-pg-migrate)` all hit the new node_modules cache miss on first run, hit on subsequent runs.
  • `Playwright smoke` runs because this PR touches workflow files (not in the paths-ignore list).
  • On a follow-up doc-only PR (e.g. a `.convoys/**` edit), confirm ALL ci.yml jobs + the Playwright smoke job DO NOT appear in the checks list. Vercel still posts.

Pipeline directive

Made with Cursor

## Why GitHub Actions on PRs #124 + #125 hit a billing block today (\"recent account payments have failed or your spending limit needs to be increased\"). Per the user's max-savings preference, this PR aggressively reduces minute usage so CI doesn't hit the limit again on the rest of the in-flight convoy work. ## What changed ### 1. \`paths-ignore\` on \`ci.yml\` + \`preview-smoke.yml\` (biggest win) Doc-only PRs now trigger ZERO GitHub Actions jobs. Both workflows skip when ALL changed files match: \`\`\`yaml paths-ignore: - '.convoys/**' - '**/*.md' - 'docs/**' - 'AGENTS.md' - '.cursor/**' - 'README.md' \`\`\` Vercel still builds and Vercel comments still fire — Vercel is not on the Actions billing. \`visual-diff.yml\` unchanged — it was already cost-conscious via a positive \`paths:\` allowlist (\`pages/**\`, \`components/**\`, \`styles/**\`, etc.). ### 2. Consolidate 6 grep-only forbidden-* jobs into 1 Previously 6 jobs × ~3s \`actions/checkout\` = ~18s of redundant checkout per PR. Merged into a single \`forbidden-patterns\` job with 6 sequential \`::group::\` sections, one FAIL flag at the bottom. **All 6 checks still surface every violation in one run** — same diagnostic behavior, per-file \`::error file=...::msg\` annotations preserved. Removed top-level job names: - \`forbidden-endpoints\` - \`forbidden-cors-headers\` - \`forbidden-client-side-llm-keys\` - \`forbidden-modal-shell-without-primitive\` - \`forbidden-deprecated-color-aliases\` - \`forbidden-stale-strings\` \`pr-health-rollup.yml\` only looks up \`Lint\` and \`Schema map up to date\` by name — unaffected. ### 3. Cache \`node_modules\` + Playwright browsers - **\`node_modules\` cache** (lint / test / migrate / preview-smoke / visual-diff): keyed by \`package-lock.json\` hash. Cuts \`npm ci\` from ~30-45s to ~3-5s on cache hit. \`setup-node@v4\`'s built-in \`cache: npm\` (caches \`~/.npm\`) stays layered above this. - **Playwright browsers cache** (preview-smoke / visual-diff): keyed by the resolved \`@playwright/test\` version from \`package-lock.json\`. Cache invalidates on any version bump. On cache hit, only \`npx playwright install-deps chromium\` runs — saves ~15-25s/run. ## Files | File | Diff | | - | - | | \`.github/workflows/ci.yml\` | +130 / -107 | | \`.github/workflows/preview-smoke.yml\` | +35 / -3 | | \`.github/workflows/visual-diff.yml\` | +27 / -3 | | \`AGENTS.md\` | +5 / -3 | ## Estimated savings | PR type | Before | After | Reduction | | - | - | - | - | | Doc-only PR | ~6-7 min Actions | **0 min** | 100% | | Code-touching PR (cache hit) | ~6-7 min | ~3-4 min | ~40-50% | | Code-touching PR (cache miss, e.g. new dep) | ~6-7 min | ~5-6 min | ~10-15% | | **Weighted (typical convoy mix: ~30% docs)** | — | — | **~50-60%** | This is short of the 70-80% I floated in chat — the real ceiling is limited by lint / vitest / migrate / Playwright runtime itself, all of which are kept on code-touching PRs (they're high-signal). ## Verification - [x] All 3 workflow YAMLs parse (\`python3 yaml.safe_load\`). - [x] \`npm run lint\` passes (1 pre-existing unrelated warning). - [x] \`npm run test:run\`: 118/118 tests pass. - [x] \`forbidden-patterns\` logic is byte-equivalent to the 6 original jobs' bash bodies. Differences: per-check \`::group::\`/\`::endgroup::\` framing, shared FAIL flag instead of per-job \`exit 1\`, and renamed local arrays (\`FOUND\` → \`LLM_FOUND\` / \`MODAL_FOUND\` / \`STRING_FOUND\`) to avoid scope clobbering in one big bash step. ## Test plan This PR itself will be the canary — it touches \`.github/workflows/**\` so: - [ ] The new \`Forbidden patterns (6 checks)\` check appears (not the 6 old ones). - [ ] \`Lint\` / \`Unit tests (vitest)\` / \`Migrations apply (node-pg-migrate)\` all hit the new node_modules cache miss on first run, hit on subsequent runs. - [ ] \`Playwright smoke\` runs because this PR touches workflow files (not in the paths-ignore list). - [ ] On a follow-up doc-only PR (e.g. a \`.convoys/**\` edit), confirm ALL ci.yml jobs + the Playwright smoke job DO NOT appear in the checks list. Vercel still posts. ## Pipeline directive <!-- pipeline: skip visual --> Made with [Cursor](https://cursor.com)
vercel[bot] commented 2026-06-04 17:33:05 -04:00 (Migrated from github.com)

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tcg-vault Ready Ready Preview, Comment Jun 4, 2026 9:33pm

Request Review

[vc]: #CoDpLXHEZIIdum84+yhd5B+YmpvLhIProa+hrUJk6dk=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJ0Y2ctdmF1bHQiLCJwcm9qZWN0SWQiOiJwcmpfRjZXOEVvRkd3Y0g3aWVGcnRvRlNlOXdVVkFhNSIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJ0Y2ctdmF1bHQtZ2l0LXNsYXNoLWNpLW1pbnV0ZXMtcmFuZGFsbC1zdGlsbHdlbGxzLXByb2plY3RzLnZlcmNlbC5hcHAifSwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3JhbmRhbGwtc3RpbGx3ZWxscy1wcm9qZWN0cy90Y2ctdmF1bHQvRmk0UmIyVWhIdUZXQmlmYzExcWVkaXB6MWNSQSIsInByZXZpZXdVcmwiOiJ0Y2ctdmF1bHQtZ2l0LXNsYXNoLWNpLW1pbnV0ZXMtcmFuZGFsbC1zdGlsbHdlbGxzLXByb2plY3RzLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQifV0sInJlcXVlc3RSZXZpZXdVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vdmVyY2VsLWFnZW50L3JlcXVlc3QtcmV2aWV3P293bmVyPXZhcnV0YXN1JnJlcG89dGNnLXZhdWx0JnByPTEyNiJ9 The latest updates on your projects. Learn more about [Vercel for GitHub](https://vercel.link/github-learn-more). | Project | Deployment | Actions | Updated (UTC) | | :--- | :----- | :------ | :------ | | [tcg-vault](https://vercel.com/randall-stillwells-projects/tcg-vault) | ![Ready](https://vercel.com/static/status/ready.svg) [Ready](https://vercel.com/randall-stillwells-projects/tcg-vault/Fi4Rb2UhHuFWBifc11qedipz1cRA) | [Preview](https://tcg-vault-git-slash-ci-minutes-randall-stillwells-projects.vercel.app), [Comment](https://vercel.live/open-feedback/tcg-vault-git-slash-ci-minutes-randall-stillwells-projects.vercel.app?via=pr-comment-feedback-link) | Jun 4, 2026 9:33pm | <a href="https://vercel.com/vercel-agent/request-review?owner=varutasu&repo=tcg-vault&pr=126" rel="noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://agents-vade-review.vercel.sh/request-review-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://agents-vade-review.vercel.sh/request-review-light.svg"><img src="https://agents-vade-review.vercel.sh/request-review-light.svg" alt="Request Review"></picture></a>
Sign in to join this conversation.
No description provided.