Some checks failed
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Meridian Harness / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Meridian Harness / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Meridian Harness / Publish rolling release (push) Has been cancelled
Meridian Harness / Publish tagged release (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Isolated DB Gate (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Admin Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Server Cross-Compile (push) Has been cancelled
CI / Server Cross-Compile-1 (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
deploy/AGENTS.md has said it plainly for a long time: "Bump `Chart.yaml` `version` on any chart change. ArgoCD tracks chart versions; an unbumped chart deploys stale templates." Nothing checked it. helm lint does not, helm unittest does not, check-alert-runbooks does not, and the failure is both silent and remote -- the chart renders, the suite passes, CI is green, and the cluster keeps serving the previous templates. Commitb6443a823is the worked example. It added the entire meridian-relay.bus-reachability group plus MeridianBusPeersUnreachable to templates/prometheusrule.yaml and left Chart.yaml at 0.1.13, so a new alert was doubly unreachable: no promtool case proving it could fire, and a chart version that did not contain it. A human reading two files caught it three commits later (meridian-8s3s). The contract is differential -- "this changed without that changing" -- which is unusual here, because every other guard in scripts/ reads the current tree. Two diff-shaped placements were considered and rejected: - a merge-base diff inside `just check`. There is no trustworthy baseline. The root contract forbids branches, so work lands directly on a constantly-rebased `main`; a merge-base with origin/main is not a release boundary, and in a fresh or shallow checkout it does not exist at all. A guard that invents its baseline reports whatever the local ref happens to be. - a CI-only diff against the PR base. The baseline is real there, but it is only real on pull_request, and this repo pushes to main. It would also be invisible to `just ci` and to the pre-push hook, which is where this repo prefers to catch things -- and helm-chart.yml, the one workflow that already touches charts, is `paths`-filtered on pull_request, which is precisely the conditional gate that does not run when it matters. So the baseline is checked in instead, the same shape as scripts/n-minus-one-pins.json and .settings/stellar/snapshot.json: scripts/chart-version-manifest.json records, per chart, the sha256 of every file that renders into a cluster against the version they were last recorded at. Any edit to templates/, crds/, values*.yaml|json, Chart.yaml or Chart.lock moves a digest, and a moved digest without a higher `version` is a hard failure naming the file. No diff, no baseline branch, works in `just check` and in a shallow clone. Two normalizations make the guard say what it means. Chart.yaml is hashed with its top-level `version:` line removed, so a bump with no template change stays silent while an edit to `dependencies:` or `appVersion` still demands one; Chart.lock is hashed without `generated:`, which `helm dependency build` rewrites without changing what deploys. tests/, ci/, examples/ and README.md are deliberately outside the set -- none of them reach a cluster, and demanding a bump for a test-only edit teaches people to bump reflexively, which is the same failure wearing a hat. `--write` is not an escape hatch: it refuses to record a chart whose rendered files moved while `version` did not, printing the same message the check does. The only route to a green tree is the bump. Wired three ways, because a guard in one place is a guard someone skips: `just check` (via check-chart-version-bump), the ci.yml guards job, and a new lefthook pre-push entry -- before which a `deploy/charts/**`-only push matched no glob at all and ran zero local hooks, which is howb6443a823got out. scripts/test-chart-version-bump-guard.sh is the "prove it fires" half. It asserts the exit codes rather than the prose: refused with exit 1 on a template edit and on a values.yaml edit, `--write` refusing to launder either, exit 0 on a Chart.yaml-only bump and on a tests/ edit, every chart under deploy/charts/ actually present in the manifest, and -- when history is deep enough to reach it --b6443a823replayed against its own parent's baseline and refused for the unbumped 0.1.13. Covers all three charts: meridian@0.1.14, meridian-control-plane@0.1.1, meridian-push-gateway@0.1.0, 50 rendered files. No file under deploy/charts/ is touched by this commit. Refs: meridian-8s3s Signed-off-by: Joshua Belke <joshua@innovationhub-act.org>
138 lines
7.9 KiB
YAML
138 lines
7.9 KiB
YAML
# Glob patterns below mirror the `changes` job's dorny/paths-filter groups in
|
|
# .github/workflows/ci.yml — keep the two in sync. Deliberate deviations:
|
|
# - The `pre-commit` fix commands narrow their globs to the extensions their
|
|
# formatter accepts (`crates/**/*.rs`, not `crates/**`), because they pass the
|
|
# matched paths straight to the formatter. Widening one back to a directory
|
|
# glob hands `rustfmt` a `Cargo.toml`. CI parity lives in the `pre-push`
|
|
# globs, which still mirror the filter groups directly.
|
|
# - The `.github/workflows/ci.yml` path CI adds to its `rust`/`mobile` filters
|
|
# is omitted; a CI-workflow-only edit doesn't need a local test run.
|
|
# - `desktop-check`/`desktop-test` don't trigger on `rust` changes, though CI's
|
|
# Desktop Core job does. Those commands are pure TS (biome + node:test) with
|
|
# no Rust dependency, so the extra trigger would be spurious locally.
|
|
# - Deletion-only surface changes do not trigger local hooks: lefthook 2.1.x
|
|
# drops deleted paths from push-file discovery (`extractFiles` existence
|
|
# check, repository.go). CI's dorny/paths-filter catches deletions.
|
|
# Deliberate — accepted, not worked around.
|
|
# - `commit-msg` has no glob: it rewrites the commit message, not files. Note
|
|
# Git only runs it for `git commit` and `git merge` — other flows need their own
|
|
# flag: `git rebase --signoff`, `git cherry-pick -s`.
|
|
#
|
|
# EVERY fix command below is scoped to `{staged_files}`, and that is load-bearing
|
|
# rather than an optimisation. The whole-tree variants (`just fmt`,
|
|
# `just desktop-fix`, …) rewrite files the author never staged, and `stage_fixed`
|
|
# then adds them to the commit: on 2026-08-07 commit `2c2eb9153` carried seven of
|
|
# another agent's in-flight files despite the author staging three paths
|
|
# explicitly (bead meridian-jejg, finding F077). This branch is shared by
|
|
# construction — the root contract forbids branching so parallel agents
|
|
# interleave on `main` — so a formatter with tree-wide reach is a cross-agent
|
|
# write, not a tidy-up. Keep the file list in every `run:`; a command that
|
|
# formats `.` re-opens the defect.
|
|
#
|
|
# The whole-tree recipes stay right where they are, for `just fix-all` and CI,
|
|
# where formatting the whole tree is the intent.
|
|
pre-commit:
|
|
parallel: true
|
|
commands:
|
|
# rustfmt directly rather than `cargo fmt`: `cargo fmt -- <file>` still
|
|
# formats every crate root, so the file list would not scope anything.
|
|
# Edition mirrors `[workspace.package] edition` in Cargo.toml; there is no
|
|
# rustfmt.toml, so the remaining settings are rustfmt's defaults either way.
|
|
rust-fmt:
|
|
glob: ["crates/**/*.rs", "examples/countdown-bot/**/*.rs"]
|
|
run: rustfmt --edition 2021 {staged_files}
|
|
stage_fixed: true
|
|
desktop-tauri-fmt:
|
|
glob: ["REMAPPING/meridian-desktop/src-tauri/**/*.rs"]
|
|
run: rustfmt --edition 2021 {staged_files}
|
|
stage_fixed: true
|
|
# `root:` keeps the working directory at `REMAPPING/meridian-desktop/`, so biome resolves
|
|
# `REMAPPING/meridian-desktop/biome.json` exactly as `just desktop-fix` does. Running biome from
|
|
# the repo root would pick up the root `biome.json` instead and reformat
|
|
# against the wrong ruleset.
|
|
desktop-fix:
|
|
root: "REMAPPING/meridian-desktop/"
|
|
glob: ["*.{ts,tsx,js,jsx,mjs,cjs,json,jsonc,css}"]
|
|
# `*.generated.json` mirrors the `includes` deny-list in `REMAPPING/meridian-desktop/biome.json`.
|
|
# Since the formatters started taking `{staged_files}`, a commit whose only
|
|
# desktop file is a generated artifact handed biome one path that biome's own
|
|
# config ignores; biome then processed zero files and exited 1. That is a
|
|
# normal commit — `just check-mips --write` produces exactly it — so the two
|
|
# ignore lists have to agree or the workflow is unlandable.
|
|
exclude: ["src-tauri/**", "**/*.generated.json"]
|
|
# `check:file-sizes` takes the staged set too. It is a "what am I about
|
|
# to publish" check, and running it over the whole tree in a hook means
|
|
# one agent mid-way through splitting a large module blocks every other
|
|
# agent from committing anything — observed live, two files at once.
|
|
# CI and `just check` still scan the whole project, which is what
|
|
# actually protects `main`.
|
|
run: pnpm exec biome check --write {staged_files} && pnpm check:file-sizes {staged_files}
|
|
stage_fixed: true
|
|
web-fix:
|
|
root: "REMAPPING/meridian-web/"
|
|
glob: ["*.{ts,tsx,js,jsx,mjs,cjs,json,jsonc,css}"]
|
|
# `check:file-sizes` stays whole-project here, unlike desktop above: only
|
|
# the desktop wrapper reads a path list so far, and `REMAPPING/meridian-web/` has not
|
|
# produced a cross-agent block. Unscoped is the safer default — scope it
|
|
# when it actually gets in someone's way, not pre-emptively.
|
|
run: pnpm exec biome check --write {staged_files} && pnpm check:file-sizes
|
|
stage_fixed: true
|
|
# Split from the analyzer: `dart format` takes the staged file list, while
|
|
# `flutter analyze` is whole-project and read-only, so it cannot stage
|
|
# anything and needs no scoping.
|
|
mobile-fmt:
|
|
root: "REMAPPING/meridian-mobile/"
|
|
glob: ["*.dart"]
|
|
run: unset GIT_DIR GIT_WORK_TREE && dart format {staged_files}
|
|
stage_fixed: true
|
|
mobile-analyze:
|
|
root: "REMAPPING/meridian-mobile/"
|
|
glob: ["*"]
|
|
run: unset GIT_DIR GIT_WORK_TREE && flutter analyze
|
|
|
|
# Appends the DCO Signed-off-by trailer the required "DCO Check" enforces.
|
|
# `--if-exists doNothing` makes it idempotent and preserves an existing
|
|
# sign-off (including `git commit -s` and a different signer's trailer).
|
|
commit-msg:
|
|
commands:
|
|
signoff:
|
|
run: 'git interpret-trailers --if-exists doNothing --trailer "Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed ''s/ [0-9]* [+-][0-9]*$//'')" --in-place {1}'
|
|
|
|
pre-push:
|
|
parallel: true
|
|
commands:
|
|
branch-skew:
|
|
run: ./scripts/check-branch-skew.sh
|
|
rust-tests:
|
|
glob: ["crates/**", "migrations/**", "schema/**", "Cargo.toml", "Cargo.lock", "rust-toolchain.toml", "deny.toml", "scripts/run-tests.sh", "justfile"]
|
|
run: just test-unit
|
|
desktop-check:
|
|
glob: ["REMAPPING/meridian-desktop/**", "pnpm-lock.yaml"]
|
|
exclude: ["REMAPPING/meridian-desktop/src-tauri/**"]
|
|
# `desktop-check` is biome + guards only; `tsc` is a separate recipe.
|
|
# Without it here a type error survives every local gate and first
|
|
# surfaces in CI's `desktop-build`.
|
|
run: just desktop-check && just desktop-typecheck
|
|
desktop-test:
|
|
glob: ["REMAPPING/meridian-desktop/**", "pnpm-lock.yaml"]
|
|
exclude: ["REMAPPING/meridian-desktop/src-tauri/**"]
|
|
run: just desktop-test
|
|
desktop-tauri-checks:
|
|
# Keep local lint parity with Desktop Core CI for every path that can
|
|
# affect the Tauri crate or its path dependencies. Run clippy and tests
|
|
# serially so parallel pre-push hooks do not contend for Cargo's lock.
|
|
glob: ["REMAPPING/meridian-desktop/src-tauri/**", "crates/**", "migrations/**", "schema/**", "Cargo.toml", "Cargo.lock", "rust-toolchain.toml", "deny.toml", "scripts/run-tests.sh", "justfile"]
|
|
run: just desktop-tauri-clippy && just desktop-tauri-test
|
|
mobile-test:
|
|
glob: ["REMAPPING/meridian-mobile/**"]
|
|
run: just mobile-test
|
|
# A chart-only change matches no other glob above, so before this entry a
|
|
# `deploy/charts/**` push ran ZERO local hooks. That is how b6443a823
|
|
# reached main with an alert group added at Chart.yaml 0.1.13: ArgoCD tracks
|
|
# chart versions, so the cluster kept the previous templates and nothing
|
|
# anywhere said so. Cheap (node, no toolchain) and state-based, so it needs
|
|
# no diff. `scripts/**` is in the glob because the manifest and the guard
|
|
# itself live there.
|
|
chart-version-bump:
|
|
glob: ["deploy/charts/**", "scripts/chart-version-manifest.json", "scripts/check-chart-version-bump*.mjs", "scripts/test-chart-version-bump-guard.sh"]
|
|
run: just check-chart-version-bump
|