Background
vibe dominates the account's metered Actions usage (gross ~$104/mo in the May billing view). For a public repo this is currently fully offset by the included-usage discount (net $0), so this is hygiene / not a billing emergency — but the CI does a lot of redundant work on the expensive runners, and the gross figure is what would bill if the repo ever went private or the discount policy changed.
Problem
ci.yml triggers on both push: [main, develop] and pull_request: [main, develop]:
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
Because the project mandates PRs (no direct pushes to main/develop), every merge re-runs the same full matrix the PR already validated — so the expensive cross-platform build runs ~2× per change.
The costly runners live in three matrix jobs:
| Job |
Costly runners |
build-binaries |
macos-latest ×2 (darwin x64/arm64), ubuntu-24.04-arm |
build-native |
macos-latest ×2, ubuntu-24.04-arm |
e2e-test |
macos-latest |
ci.yml also has no concurrency group, so pushing several commits to a PR leaves superseded runs going (other workflows like docs.yml / release.yml already use concurrency).
A release day (e.g. v1.7.0 → flake fixes → v1.7.1) multiplies this: each release/merge PR + its merge-push + the release/publish-* workflows all spin full matrices.
Proposed optimizations (rough effort order)
- Remove the push/PR duplication. Drop
push: from ci.yml (rely on PR CI + release.yml/nix.yml), or keep push: [main] only for the badge and gate the expensive macos/arm64 matrix entries to pull_request only.
- Add
concurrency with cancel-in-progress: true to ci.yml, e.g. group: ci-${{ github.workflow }}-${{ github.ref }}.
- Gate the costly cross-platform jobs by changed paths (e.g. only run the full
build-binaries/build-native matrix when native/build files change; skip for docs/chore-only changes).
- (Optional, ops) Configure Budgets and alerts in account billing as a backstop.
Acceptance criteria
- A typical PR-merge no longer runs the full macOS/arm64 matrix twice for the same commit.
- Superseded PR runs are auto-cancelled.
- All existing checks (lint/typecheck/test/e2e/nix-build/build-*) still gate merges to
develop.
- No reduction in release-asset coverage (
release.yml matrix unchanged).
Notes
- Verify whether
pull_request alone keeps required status checks satisfiable on branch settings before dropping push:.
release.yml / publish-*.yml matrices are intentionally full and out of scope here.
Background
vibedominates the account's metered Actions usage (gross ~$104/mo in the May billing view). For a public repo this is currently fully offset by the included-usage discount (net $0), so this is hygiene / not a billing emergency — but the CI does a lot of redundant work on the expensive runners, and the gross figure is what would bill if the repo ever went private or the discount policy changed.Problem
ci.ymltriggers on bothpush: [main, develop]andpull_request: [main, develop]:Because the project mandates PRs (no direct pushes to
main/develop), every merge re-runs the same full matrix the PR already validated — so the expensive cross-platform build runs ~2× per change.The costly runners live in three matrix jobs:
build-binariesmacos-latest×2 (darwin x64/arm64),ubuntu-24.04-armbuild-nativemacos-latest×2,ubuntu-24.04-arme2e-testmacos-latestci.ymlalso has noconcurrencygroup, so pushing several commits to a PR leaves superseded runs going (other workflows likedocs.yml/release.ymlalready useconcurrency).A release day (e.g. v1.7.0 → flake fixes → v1.7.1) multiplies this: each release/merge PR + its merge-push + the
release/publish-*workflows all spin full matrices.Proposed optimizations (rough effort order)
push:fromci.yml(rely on PR CI +release.yml/nix.yml), or keeppush: [main]only for the badge and gate the expensivemacos/arm64matrix entries topull_requestonly.concurrencywithcancel-in-progress: truetoci.yml, e.g.group: ci-${{ github.workflow }}-${{ github.ref }}.build-binaries/build-nativematrix when native/build files change; skip for docs/chore-only changes).Acceptance criteria
develop.release.ymlmatrix unchanged).Notes
pull_requestalone keeps required status checks satisfiable on branch settings before droppingpush:.release.yml/publish-*.ymlmatrices are intentionally full and out of scope here.