Skip to content

ci: skip downstream jobs when their area is unchanged#89

Merged
ntatschner merged 1 commit into
nextfrom
chore/ci-path-filters
May 23, 2026
Merged

ci: skip downstream jobs when their area is unchanged#89
ntatschner merged 1 commit into
nextfrom
chore/ci-path-filters

Conversation

@ntatschner
Copy link
Copy Markdown
Collaborator

Summary

  • New changed job uses dorny/paths-filter@v3 to emit per-area booleans (rust / web / tray / openapi / tauri).
  • Each downstream job's if: now ANDs the existing should-run gate with needs.changed.outputs.<area> == 'true', so unchanged areas skip entirely.
  • Every filter group includes .github/workflows/ci.yml itself, so a workflow tweak never silently skips its own validation.
  • Filter scope honours your monorepo realities: crates/starstats-core is shared by both openapi and tauri filters; apps/tray-ui is in both tray and tauri (the latter because tauri::generate_context! validates frontendDist exists at compile time, per the project CLAUDE.md note); packages/api-client-ts is in web + openapi only (tray-ui talks to Rust via Tauri invoke, not the generated TS schema); packages/** is included broadly for web/tray so future shared packages don't need a CI rev.

Why

Stacks with the existing concurrency cancel-chain (per the CLAUDE.md "Build & Test cancel-chain on main" note) — small bursts of bookkeeping commits to main/next (release-manifest auto-commits, docs catch-ups, fmt-fixes) no longer burn Rust/Tauri matrix minutes on no-op work. The current should-run gate already drops bot-bookkeeping commits; this generalises the cost-saving to any human commit that's scoped to a single subsystem.

Why per-job filter (not workflow-level on: paths:)

Workflow-level path filters skip the entire run, which leaves required status checks missing rather than green — breaks merges once you wire up the branch-protection snippet in docs/RELEASING.md. The per-job pattern keeps every job name reporting (skipped counts as concluded for required-check purposes), so this change is forward-safe.

Test plan

  • First push to this branch lands the changed job in CI; verify all 6 downstream jobs run (the workflow file itself changed, which matches every filter group).
  • Open a docs-only follow-up commit (README.md or docs/**); verify rust / web / tray / openapi / tauri all skip while should-run + changed still run.
  • Open a crates/starstats-server/** change; verify rust + openapi-drift + tauri-client run, web / web-e2e / tray-ui skip.
  • Open an apps/web/** change; verify web + web-e2e run, rust / tray-ui / tauri-client / openapi-drift skip.
  • Open an apps/tray-ui/** change; verify tray-ui + tauri-client run, rust / web / web-e2e / openapi-drift skip.

Add a 'changed' job using dorny/paths-filter@v3 that emits per-area
booleans (rust/web/tray/openapi/tauri). Each downstream job gates
itself via 'if: needs.changed.outputs.<area> == true' on top of the
existing should-run commit-message gate.

Docs-only commits, single-area changes (e.g. web-only docs sweep),
and tree-touching commits that miss a particular workload (e.g. a
crates/starstats-server change skips tray-ui + tauri-client) now
avoid spinning up the unaffected jobs. Stacks with the existing
concurrency cancel-chain so small bursts of commits to next/main
don't burn Rust/Tauri matrix minutes on no-op work.

Job names still report in every run (skipped, not absent), so this
is forward-safe for required-status-check branch protection.
@ntatschner ntatschner merged commit cfc10d6 into next May 23, 2026
10 checks passed
@ntatschner ntatschner deleted the chore/ci-path-filters branch May 23, 2026 23:31
ntatschner pushed a commit that referenced this pull request May 23, 2026
Decouples the Tauri tray installer cadence from the server + web
container image cadence. Each track now has its own version number,
its own tag schema, its own auto-alpha trigger, and ships through its
own workflow:

- tray:     tag tray-vX.Y.Z[-channel.N] -> release.yml
            version in crates/starstats-client/Cargo.toml + tauri.conf.json
            updater manifest at release-manifests/tray-{channel}.json
- platform: tag vX.Y.Z[-channel.N] -> release-images.yml (unchanged)
            version in workspace [workspace.package], inherited by
            starstats-core + starstats-server
            no auto-update manifest (homelab pulls floats via Komodo)

Glob non-overlap: GitHub's 'v*' anchors at start, so 'tray-v*' never
fires release-images.yml. No tags-ignore needed.

Web-only changes no longer churn the tray's signed MSI / channel
manifest. Tray bug fixes no longer force a server redeploy.

Key changes:
- scripts/release-promote.mjs: every prerelease/live subcommand now
  takes a <tray|platform> track argument. New pure helpers tagPrefix,
  parseTrackTag, bumpClientCargo. latestSemverFromTags accepts an
  optional track filter. 49 new unit tests cover the track plumbing
  (67 total, all green).
- crates/starstats-client/Cargo.toml: switched from
  'version.workspace = true' to literal 'version = "1.8.4"' so the
  client floats independently. starstats-client -> starstats-core dep
  is a path dep so version skew is irrelevant.
- release.yml: trigger 'tray-v*', validate-tag strips the prefix,
  manifest path is release-manifests/tray-<channel>.json. New step
  generates a per-component changelog (git log filtered to tray paths
  since the previous tray-v* tag) and injects into the GH Release body
  via body_path instead of GH's auto-generated notes (which would
  otherwise pick the literal previous tag — possibly a platform vX.Y.Z
  — and leak platform-only commits into the tray release body).
- promote.yml: new detect-tracks setup job. workflow_dispatch takes a
  track input (tray|platform|both). Push-to-next auto-alpha uses
  dorny/paths-filter@v3 to bump only the tracks whose files changed;
  docs-only pushes tag nothing. starstats-core triggers both tracks.
  Self-bump commits are skipped to break the loop (mirrors ci.yml).
- ci.yml: should-run skip list adds 'chore: bump tray to ' and
  'chore: bump platform to ' for the new bot-commit message format.
- release-manifests/{alpha,beta,rc,live}.json renamed to
  release-manifests/tray-{alpha,beta,rc,live}.json (git mv, history
  preserved). Tray client manifest_url() + tauri.conf.json updater
  endpoint updated to match.
- apps/web: platform version surfaced in a sub-footer chip on both
  signed-in + marketing layouts. Build-time inlined via next.config.mjs
  env block, sourced from workspace Cargo.toml.
- CLAUDE.md branch model section + docs/RELEASING.md quick-reference
  table updated. Full design spec at
  docs/superpowers/specs/2026-05-23-release-tracks-split.md.

Migration: one-time. Old in-the-wild tray installers point at
release-manifests/<channel>.json which now 404s; users re-download
+ re-pair from the latest GH release. Acceptable per internal/dogfood
deployment posture.

Out of scope (future PRs): platform GH releases with their own
changelog; release-notes/<track>/<version>.md narrative summaries;
roadmap-emit track-aware slugs.

Depends on PR #89 (ci.yml path filters) for the ci.yml conflict — if
this lands first, #89 rebases trivially on top.

See docs/superpowers/specs/2026-05-23-release-tracks-split.md.
ntatschner added a commit that referenced this pull request May 24, 2026
)

Decouples the Tauri tray installer cadence from the server + web
container image cadence. Each track now has its own version number,
its own tag schema, its own auto-alpha trigger, and ships through its
own workflow:

- tray:     tag tray-vX.Y.Z[-channel.N] -> release.yml
            version in crates/starstats-client/Cargo.toml + tauri.conf.json
            updater manifest at release-manifests/tray-{channel}.json
- platform: tag vX.Y.Z[-channel.N] -> release-images.yml (unchanged)
            version in workspace [workspace.package], inherited by
            starstats-core + starstats-server
            no auto-update manifest (homelab pulls floats via Komodo)

Glob non-overlap: GitHub's 'v*' anchors at start, so 'tray-v*' never
fires release-images.yml. No tags-ignore needed.

Web-only changes no longer churn the tray's signed MSI / channel
manifest. Tray bug fixes no longer force a server redeploy.

Key changes:
- scripts/release-promote.mjs: every prerelease/live subcommand now
  takes a <tray|platform> track argument. New pure helpers tagPrefix,
  parseTrackTag, bumpClientCargo. latestSemverFromTags accepts an
  optional track filter. 49 new unit tests cover the track plumbing
  (67 total, all green).
- crates/starstats-client/Cargo.toml: switched from
  'version.workspace = true' to literal 'version = "1.8.4"' so the
  client floats independently. starstats-client -> starstats-core dep
  is a path dep so version skew is irrelevant.
- release.yml: trigger 'tray-v*', validate-tag strips the prefix,
  manifest path is release-manifests/tray-<channel>.json. New step
  generates a per-component changelog (git log filtered to tray paths
  since the previous tray-v* tag) and injects into the GH Release body
  via body_path instead of GH's auto-generated notes (which would
  otherwise pick the literal previous tag — possibly a platform vX.Y.Z
  — and leak platform-only commits into the tray release body).
- promote.yml: new detect-tracks setup job. workflow_dispatch takes a
  track input (tray|platform|both). Push-to-next auto-alpha uses
  dorny/paths-filter@v3 to bump only the tracks whose files changed;
  docs-only pushes tag nothing. starstats-core triggers both tracks.
  Self-bump commits are skipped to break the loop (mirrors ci.yml).
- ci.yml: should-run skip list adds 'chore: bump tray to ' and
  'chore: bump platform to ' for the new bot-commit message format.
- release-manifests/{alpha,beta,rc,live}.json renamed to
  release-manifests/tray-{alpha,beta,rc,live}.json (git mv, history
  preserved). Tray client manifest_url() + tauri.conf.json updater
  endpoint updated to match.
- apps/web: platform version surfaced in a sub-footer chip on both
  signed-in + marketing layouts. Build-time inlined via next.config.mjs
  env block, sourced from workspace Cargo.toml.
- CLAUDE.md branch model section + docs/RELEASING.md quick-reference
  table updated. Full design spec at
  docs/superpowers/specs/2026-05-23-release-tracks-split.md.

Migration: one-time. Old in-the-wild tray installers point at
release-manifests/<channel>.json which now 404s; users re-download
+ re-pair from the latest GH release. Acceptable per internal/dogfood
deployment posture.

Out of scope (future PRs): platform GH releases with their own
changelog; release-notes/<track>/<version>.md narrative summaries;
roadmap-emit track-aware slugs.

Depends on PR #89 (ci.yml path filters) for the ci.yml conflict — if
this lands first, #89 rebases trivially on top.

See docs/superpowers/specs/2026-05-23-release-tracks-split.md.

Co-authored-by: Nigel Tatschner <n Tatschner@gmail.com>
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