diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 3eb7a29..e44902e 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -23,6 +23,11 @@ permissions: contents: write pull-requests: write +# Cancel previous runs on the same ref (force-push during PR iteration). +concurrency: + group: benchmark-${{ github.ref }} + cancel-in-progress: true + jobs: benchmark: name: Run Benchmarks diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 76b7703..3d4cb8f 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -7,6 +7,18 @@ on: # lints introduced by Rust toolchain updates. pull_request: branches: [ "main" ] + # Positive filter: clippy only matters when Rust source or build + # configuration changes. The .yml itself is included so workflow + # tweaks still validate. test.yml's lint job also runs clippy as + # part of the broader PR gate; this workflow's SARIF upload is the + # value-add over that — keep it firing whenever .rs / Cargo.toml / + # build.rs / rust-toolchain changes. + paths: + - '**/*.rs' + - '**/Cargo.toml' + - 'build.rs' + - 'rust-toolchain.toml' + - '.github/workflows/clippy.yml' push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' @@ -15,6 +27,11 @@ on: - cron: '17 20 * * 0' workflow_dispatch: +# Cancel previous runs on the same ref (force-push during PR iteration). +concurrency: + group: clippy-${{ github.ref }} + cancel-in-progress: true + jobs: rust-clippy-analyze: name: Run rust-clippy analyzing diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 6f8553d..2de1f96 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -7,6 +7,19 @@ on: # not running it on every merge saves significant runner time. pull_request: branches: [ "main" ] + # Positive filter: coverage signal only matters when source / tests / + # dep manifests change. Doc-only / config-only / examples-only PRs + # don't shift the coverage number, and the workflow takes ~10 min + # of Linux quota per run. Keeps the PR-time coverage gate but skips + # the runs that would have produced an identical number. + paths: + - 'src/**' + - 'crates/**' + - 'tests/**' + - 'benches/**' + - 'build.rs' + - 'Cargo.toml' + - '.github/workflows/coverage.yml' push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' @@ -16,6 +29,11 @@ on: permissions: contents: read +# Cancel previous runs on the same ref (force-push during PR iteration). +concurrency: + group: coverage-${{ github.ref }} + cancel-in-progress: true + env: CARGO_TERM_COLOR: always RUST_BACKTRACE: 1 diff --git a/.github/workflows/e2e-cross-platform.yml b/.github/workflows/e2e-cross-platform.yml index a2aa24a..732ddfc 100644 --- a/.github/workflows/e2e-cross-platform.yml +++ b/.github/workflows/e2e-cross-platform.yml @@ -1,24 +1,29 @@ # PRD-038: Hybrid Cross-Platform E2E Testing Harness # # This workflow tests Jarvy tool installations across multiple platforms: -# - GitHub-hosted runners (FREE): macOS, Ubuntu, Windows +# - GitHub-hosted runners: Ubuntu (free) + macOS / Windows (paid) # - AWS EC2 Spot (future): Fedora, Arch, Alpine, FreeBSD # -# Cost: ~$0/month (GitHub-hosted runners are free for public repos) +# Correction to a prior comment claim: macOS and Windows runners are NOT +# free for public repos — only ubuntu-* is. macOS is the priciest at +# $0.062/min (10x Linux). Nightly cadence × 3 OSes × ~10min/run was +# burning ~$15-20/month from this workflow alone. name: E2E Cross-Platform Tests on: - # E2E cross-platform runs are heavy (multi-OS install matrix). The - # nightly cron below produces the canonical signal that main is - # green; per-push and per-PR runs were redundant and routinely added - # ~30 min of runner time without finding bugs the nightly missed. + # E2E cross-platform runs are heavy (multi-OS install matrix). Weekly + # cadence is sufficient — the registered tools surface changes on the + # order of days/weeks, not hours, and the nightly cadence rarely caught + # a regression the next weekly run wouldn't have. Tag pushes still get + # the full matrix via release.yml + tool-e2e.yml so cuts are validated + # at release time regardless of the weekly cron schedule. # workflow_dispatch covers ad-hoc validation when a PR touches the # tools registry or install scripts and the author wants pre-merge # confirmation. schedule: - # Nightly at 2 AM UTC - - cron: '0 2 * * *' + # Weekly on Sunday at 2 AM UTC + - cron: '0 2 * * 0' workflow_dispatch: inputs: tier: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 075d71d..ea76c88 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,14 +1,31 @@ name: Test on: - # Validation runs on PRs (pre-merge gate) and on release tags - # (post-merge integration check). The push-to-main trigger was - # removed because every PR is already validated and the merge - # commit is identical to the validated PR head — re-running the - # same suite on the merge duplicates effort. Tag push covers the - # integrated state when a release is cut. + # PR gate: Linux only. Public-repo Linux minutes are free; macOS + Windows + # are not (macOS is 10x Linux per-minute). Cross-OS validation lives on + # the release-tag matrix below + the nightly e2e-cross-platform run. + # Doc-only / CI-only / examples-only PRs skipped via paths-ignore so a + # README tweak doesn't fire the test suite. + # + # Tag push: full matrix (Linux + macOS + Windows). Release-cut is the + # canonical integration check — full cross-OS validation here catches + # regressions before the artifact build runs in release.yml. pull_request: branches: [ "main" ] + # Positive filter: PR test runs only fire when source / tests / dep + # manifests / build config change. Excludes doc-only, CI-only, + # example-only, lint-config PRs that can't shift the test outcome. + # Inverted from paths-ignore for predictability — easier to reason + # about "what triggers a run" than "what does NOT trigger". + paths: + - 'src/**' + - 'crates/**' + - 'tests/**' + - 'benches/**' + - 'build.rs' + - 'Cargo.toml' + - 'rust-toolchain.toml' + - '.github/workflows/test.yml' push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' @@ -18,6 +35,14 @@ on: permissions: contents: read +# Cancel previous runs on the same ref. Force-pushes during PR iteration +# previously stacked 2-3 in-flight matrix runs per branch — each one +# burned its macOS + Windows slot before being cancelled by branch +# protection. +concurrency: + group: test-${{ github.ref }} + cancel-in-progress: true + env: CARGO_TERM_COLOR: always RUST_BACKTRACE: 1 @@ -49,7 +74,11 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-latest, ubuntu-latest, windows-latest] + # PR runs (free Linux minutes) get ubuntu-latest only. + # Tag pushes add macos-latest + windows-latest for the + # integration check. github.event_name is evaluated at + # matrix-expansion time so this composes cleanly. + os: ${{ github.event_name == 'pull_request' && fromJSON('["ubuntu-latest"]') || fromJSON('["macos-latest", "ubuntu-latest", "windows-latest"]') }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tool-e2e.yml b/.github/workflows/tool-e2e.yml index ca47772..068b4b5 100644 --- a/.github/workflows/tool-e2e.yml +++ b/.github/workflows/tool-e2e.yml @@ -1,13 +1,23 @@ name: Tools E2E on: - # Tools E2E exercises the full multi-OS install matrix; running on - # every push to every branch was burning ~13 min × N pushes/day. - # Restrict to PR validation (pre-merge gate) and release tags - # (post-merge integration check). workflow_dispatch covers ad-hoc - # validation when working on the tools registry. + # Tools E2E exercises the full multi-OS install matrix and was + # burning ~13 min × N pushes/day across mac+win+6-distro-linux. + # Restrict to PRs that actually touch the tools registry / install + # scripts / tools-related tests (everything else can't regress this + # surface). Release tags still run the full matrix as the canonical + # post-merge integration check. workflow_dispatch covers ad-hoc runs. pull_request: branches: [main] + paths: + - 'src/tools/**' + - 'crates/jarvy-templates/**' + - 'tests/cli_*.rs' + - 'tests/e2e_*.rs' + - 'tests/tools_*.rs' + - 'dist/scripts/install.*' + - 'Cargo.toml' + - '.github/workflows/tool-e2e.yml' push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' @@ -54,6 +64,12 @@ jobs: native-host: name: Native host (brew on macOS, winget on Windows) + # macOS minutes are $0.062/min (10x Linux) and Windows is $0.01/min. + # PR-time native-host runs were the second-largest macOS consumer + # behind release.yml. PRs get Linux-only (linux-testcontainers above); + # native-host fires on release tags + workflow_dispatch so cross-OS + # install verification still gates the canonical artifact builds. + if: github.event_name != 'pull_request' strategy: fail-fast: false matrix: