From b8eff30fc2399691401235de7e4f798ba2bf1535 Mon Sep 17 00:00:00 2001 From: t Date: Wed, 22 Jul 2026 14:08:01 -0500 Subject: [PATCH 1/6] chore: sync Cargo.lock with the 0.6.0 manifests --- Cargo.lock | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5dd2903d..09577ae1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3300,7 +3300,7 @@ dependencies = [ [[package]] name = "git-remote-gitlawb" -version = "0.5.1" +version = "0.6.0" dependencies = [ "anyhow", "gitlawb-core", @@ -3312,7 +3312,7 @@ dependencies = [ [[package]] name = "gitlawb-attest" -version = "0.5.1" +version = "0.6.0" dependencies = [ "base64", "ed25519-dalek", @@ -3329,7 +3329,7 @@ dependencies = [ [[package]] name = "gitlawb-core" -version = "0.5.1" +version = "0.6.0" dependencies = [ "anyhow", "base64", @@ -3356,7 +3356,7 @@ dependencies = [ [[package]] name = "gitlawb-node" -version = "0.5.1" +version = "0.6.0" dependencies = [ "alloy", "anyhow", @@ -3412,10 +3412,11 @@ dependencies = [ [[package]] name = "gl" -version = "0.5.1" +version = "0.6.0" dependencies = [ "alloy", "anyhow", + "base64", "chrono", "clap", "dirs", From 52a8f010b71a9225c3199b1138b695f9bf5e2ead Mon Sep 17 00:00:00 2001 From: t Date: Wed, 22 Jul 2026 14:08:01 -0500 Subject: [PATCH 2/6] ci: lock-sync the release PR and build --locked so lock drift fails loudly (#242) --- .github/workflows/pr-checks.yml | 10 ++++----- .github/workflows/release.yml | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index d08c163e..069531bb 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -46,7 +46,7 @@ jobs: run: cargo fmt --all -- --check - name: cargo clippy - run: cargo clippy --workspace --all-targets -- -D warnings + run: cargo clippy --locked --workspace --all-targets -- -D warnings test: name: test (${{ matrix.toolchain }}) @@ -94,7 +94,7 @@ jobs: - name: cargo test env: DATABASE_URL: postgres://postgres:postgres@localhost:5432/gitlawb_test - run: cargo test --workspace + run: cargo test --locked --workspace build-release: name: build --release @@ -117,7 +117,7 @@ jobs: key: release - name: cargo build --release - run: cargo build --release --workspace + run: cargo build --locked --release --workspace audit: name: cargo audit @@ -199,7 +199,7 @@ jobs: key: msrv - name: cargo check on MSRV - run: cargo check --workspace --all-targets + run: cargo check --locked --workspace --all-targets docker-build: name: Docker build smoke test @@ -246,7 +246,7 @@ jobs: key: windows - name: cargo test (shipped Windows crates) - run: cargo test -p gl -p git-remote-gitlawb + run: cargo test --locked -p gl -p git-remote-gitlawb # gitlawb-core is embedded by every consumer (gl, git-remote-gitlawb, the node # daemon), so it must stay lean. This gate fails if gitlawb-core's normal diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dbc7f852..44eed181 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,6 +41,7 @@ jobs: release_created: ${{ steps.release.outputs.release_created }} tag_name: ${{ steps.release.outputs.tag_name }} version: ${{ steps.release.outputs.version }} + pr: ${{ steps.release.outputs.pr }} steps: - name: Run release-please id: release @@ -48,6 +49,41 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} + # The release PR bumps the workspace crate versions in the Cargo.tomls but + # release-please cannot update Cargo.lock, so without this job every release + # merge ships a tag whose lockfile disagrees with its manifests (a --locked + # build from the tag fails, and pr-checks builds --locked). Sync the lock on + # the release branch so the tagged tree is internally consistent. Runs only + # while a release PR is open (the pr output is unset on the merge push that + # creates the release). + sync-release-lock: + name: Sync Cargo.lock on the release PR + needs: release-please + if: ${{ needs.release-please.outputs.pr }} + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout release branch + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ fromJSON(needs.release-please.outputs.pr).headBranchName }} + + - name: Sync workspace crate versions into Cargo.lock + run: cargo update --workspace + + - name: Commit and push when the lock changed + run: | + if git diff --quiet Cargo.lock; then + echo "Cargo.lock already in sync" + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add Cargo.lock + git commit -m "chore: sync Cargo.lock with the release version bump" + git push + # Each architecture builds NATIVELY (amd64 on ubuntu-latest, arm64 on # ubuntu-24.04-arm) and pushes by digest; docker-manifest below stitches the # digests into the tagged multi-arch image. No QEMU: emulating the arm64 From b605b2269a1067602d5b39f00c34612900e252f5 Mon Sep 17 00:00:00 2001 From: t Date: Wed, 22 Jul 2026 18:21:50 -0500 Subject: [PATCH 3/6] ci: dispatch pr-checks on the release branch so GITHUB_TOKEN pushes still get validated --- .github/workflows/pr-checks.yml | 7 +++ .github/workflows/release.yml | 82 +++++++++++++++++++++++++++++++-- 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 069531bb..851f0385 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -6,6 +6,13 @@ on: # result before it lands. Guards against semantic merge races where two # individually-green PRs break main in combination (#113 + #145 → #229). merge_group: + # Release-branch heads are created and pushed by GITHUB_TOKEN (release-please + # and the lock-sync job), and GitHub's recursion guard means those pushes + # trigger no workflow runs. workflow_dispatch is the documented carve-out that + # GITHUB_TOKEN CAN trigger, so the release flow dispatches this workflow at + # the release branch to attach check runs to its head. Read-only workflow + # (contents: read), so the dispatch surface adds no privilege. + workflow_dispatch: push: branches: - main diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 44eed181..4f0b37db 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,26 +53,64 @@ jobs: # release-please cannot update Cargo.lock, so without this job every release # merge ships a tag whose lockfile disagrees with its manifests (a --locked # build from the tag fails, and pr-checks builds --locked). Sync the lock on - # the release branch so the tagged tree is internally consistent. Runs only - # while a release PR is open (the pr output is unset on the merge push that - # creates the release). + # the release branch so the tagged tree is internally consistent. + # + # Runs on every push-triggered release run, not only when release-please + # reports the PR: the `pr` output is set only on runs that CREATE or UPDATE + # the release PR, so gating on it would leave an already-open release PR + # (opened before this job existed, or untouched by a non-releasable push) + # permanently without the sync and without check runs. The resolve step + # discovers any open release-please PR itself and no-ops when there is none. sync-release-lock: name: Sync Cargo.lock on the release PR needs: release-please - if: ${{ needs.release-please.outputs.pr }} + if: ${{ !cancelled() && github.repository == 'Gitlawb/node' && github.event_name != 'workflow_dispatch' }} runs-on: ubuntu-latest permissions: contents: write + pull-requests: read + # actions: write lets the final step dispatch pr-checks on the release + # branch. Note this grant is repo-wide dispatch rights (GitHub cannot + # scope it to one workflow); acceptable here because reaching this job's + # steps already requires write to main. Needed because every push to the + # release branch (release-please's and the lock sync below) is made with + # GITHUB_TOKEN, which triggers no workflow runs, so without an explicit + # dispatch the release PR's head carries no check runs and the --locked + # gate never validates it. + actions: write steps: + # Prefer the fresh `pr` output when this run just created/updated the + # release PR; otherwise fall back to querying for an open release-please + # branch (prefix match: the branch carries `--components--` suffixes). + - name: Resolve the open release PR branch + id: resolve + env: + GH_TOKEN: ${{ github.token }} + BRANCH_FROM_OUTPUT: ${{ needs.release-please.outputs.pr && fromJSON(needs.release-please.outputs.pr).headBranchName || '' }} + run: | + branch="$BRANCH_FROM_OUTPUT" + if [ -z "$branch" ]; then + branch=$(gh pr list --repo "$GITHUB_REPOSITORY" --state open \ + --json headRefName \ + --jq '[.[].headRefName | select(startswith("release-please--"))][0] // empty') + fi + if [ -z "$branch" ]; then + echo "no open release PR; nothing to sync" + fi + echo "branch=$branch" >> "$GITHUB_OUTPUT" + - name: Checkout release branch + if: ${{ steps.resolve.outputs.branch != '' }} uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: - ref: ${{ fromJSON(needs.release-please.outputs.pr).headBranchName }} + ref: ${{ steps.resolve.outputs.branch }} - name: Sync workspace crate versions into Cargo.lock + if: ${{ steps.resolve.outputs.branch != '' }} run: cargo update --workspace - name: Commit and push when the lock changed + if: ${{ steps.resolve.outputs.branch != '' }} run: | if git diff --quiet Cargo.lock; then echo "Cargo.lock already in sync" @@ -84,6 +122,40 @@ jobs: git commit -m "chore: sync Cargo.lock with the release version bump" git push + # Every push to the release branch is made with GITHUB_TOKEN (release- + # please's own pushes and the lock sync above), and events created by + # GITHUB_TOKEN start no workflow runs. workflow_dispatch is the documented + # exception GITHUB_TOKEN may trigger, so dispatch pr-checks at the release + # branch to attach check runs to its current head. Unconditional (also on + # the already-in-sync path) because the branch's ORIGINAL head has the + # same no-runs problem. Loud on failure by design: a silent fallback + # would recreate the checkless-head problem, and a job rerun is safe + # (sync no-ops, dispatch retries). Loop-safe: pr-checks is read-only and + # dispatches nothing. Runs after the push ack, so the dispatched ref tip + # is the sync commit. Merge-queue note: this validates the branch tip; + # the enforced merge queue's merge_group run still re-validates the true + # merged result before landing. + - name: Dispatch PR checks on the release branch + if: ${{ steps.resolve.outputs.branch != '' }} + env: + GH_TOKEN: ${{ github.token }} + BRANCH: ${{ steps.resolve.outputs.branch }} + run: | + # A release branch cut before pr-checks gained its workflow_dispatch + # trigger 422s ("does not have a workflow_dispatch trigger" reported + # against the dispatched ref's copy of the file). That is the one + # tolerated failure: it self-heals when release-please next rewrites + # the branch from current main. Anything else fails the job loudly. + out=$(gh api "repos/${GITHUB_REPOSITORY}/actions/workflows/pr-checks.yml/dispatches" \ + -f "ref=$BRANCH" 2>&1) && exit 0 + if echo "$out" | grep -qi "does not have a workflow_dispatch trigger"; then + echo "release branch predates the dispatch trigger; checks attach after release-please next rebases it" + echo "$out" + exit 0 + fi + echo "$out" + exit 1 + # Each architecture builds NATIVELY (amd64 on ubuntu-latest, arm64 on # ubuntu-24.04-arm) and pushes by digest; docker-manifest below stitches the # digests into the tagged multi-arch image. No QEMU: emulating the arm64 From f2f99c668474b9d3da9aaa9e59db86beebc32c4e Mon Sep 17 00:00:00 2001 From: t Date: Mon, 27 Jul 2026 18:28:00 -0500 Subject: [PATCH 4/6] chore: regenerate Cargo.lock for the 0.7.0 manifests after rebase The branch forked before v0.7.0 merged, so the rebase left main's 0.7.0 manifests against workspace lock records still at 0.6.0. That state fails the gate this PR adds: `cargo metadata --locked` exits 101 with "cannot update the lock file because --locked was passed". Regenerated with `cargo update --workspace`, the same command the new sync-release-lock job runs. Only the 5 workspace crates move 0.6.0 -> 0.7.0; all 252 external dependencies are unchanged, so this is a version resync and not a dependency bump. `cargo metadata --locked` now exits 0. --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09577ae1..75cb5550 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3300,7 +3300,7 @@ dependencies = [ [[package]] name = "git-remote-gitlawb" -version = "0.6.0" +version = "0.7.0" dependencies = [ "anyhow", "gitlawb-core", @@ -3312,7 +3312,7 @@ dependencies = [ [[package]] name = "gitlawb-attest" -version = "0.6.0" +version = "0.7.0" dependencies = [ "base64", "ed25519-dalek", @@ -3329,7 +3329,7 @@ dependencies = [ [[package]] name = "gitlawb-core" -version = "0.6.0" +version = "0.7.0" dependencies = [ "anyhow", "base64", @@ -3356,7 +3356,7 @@ dependencies = [ [[package]] name = "gitlawb-node" -version = "0.6.0" +version = "0.7.0" dependencies = [ "alloy", "anyhow", @@ -3412,7 +3412,7 @@ dependencies = [ [[package]] name = "gl" -version = "0.6.0" +version = "0.7.0" dependencies = [ "alloy", "anyhow", From 5091f2dba0f6957d6d9eb456e5f4270a0cc045e9 Mon Sep 17 00:00:00 2001 From: t Date: Mon, 27 Jul 2026 18:34:28 -0500 Subject: [PATCH 5/6] ci: fail the release-lock job on a failed dispatch, and scope release-PR discovery Two review findings on the sync-release-lock job. Fail on every dispatch failure. The step tolerated the 422 a release branch cut before pr-checks gained its workflow_dispatch trigger returns, on the theory that release-please would rewrite the branch and heal it. A rewrite only happens when a later releasable commit lands, so an open release PR nobody touches is never rewritten, and the tolerated path left the lock-sync commit this job had just pushed on the release head with no --locked validation. That is the exact state the job exists to prevent. No release PR is open today, and after this lands every release branch is cut from a main that already carries the trigger, so the tolerance protects nothing. Scope the fallback discovery. `gh pr list` includes fork PRs and a fork's headRefName is bare, so matching on the `release-please--` prefix alone let any fork nominate the branch this job checks out, commits to, and dispatches on: actions/checkout then cannot resolve that fork-only ref here, failing the job and leaving the real release PR unsynced and unchecked. Discovery now requires the head repo to be this repository and the author to be the release-please app, and selects the highest PR number instead of relying on gh's undocumented default ordering. Verified the new filter against the hostile inputs, using the jq program as extracted from the parsed YAML: a fork lookalike, a fork PR claiming the app author, and a same-repo human branch named `release-please--*` are all rejected; the real release PR is still selected when listed after a fork and when a second component release PR is present; an empty listing yields empty. The previous expression selected the fork's branch on all three hostile cases. --- .github/workflows/release.yml | 50 ++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4f0b37db..2392d001 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -86,13 +86,28 @@ jobs: id: resolve env: GH_TOKEN: ${{ github.token }} + OWNER: ${{ github.repository_owner }} BRANCH_FROM_OUTPUT: ${{ needs.release-please.outputs.pr && fromJSON(needs.release-please.outputs.pr).headBranchName || '' }} run: | branch="$BRANCH_FROM_OUTPUT" if [ -z "$branch" ]; then + # The branch name alone is not a trust signal. `gh pr list` includes + # fork PRs, and a fork's headRefName is bare (no owner prefix), so a + # prefix match by itself lets any fork nominate the branch this job + # checks out, commits to, and dispatches checks on. Require the head + # repo to be THIS repository and the author to be the release-please + # app, so neither a fork nor a same-repo human branch named + # `release-please--*` can be selected. Then take the highest PR + # number: `[0]` depended on gh's default ordering, which is not a + # documented guarantee, and picking a stable one keeps a second + # (component) release PR from making the choice flap between runs. branch=$(gh pr list --repo "$GITHUB_REPOSITORY" --state open \ - --json headRefName \ - --jq '[.[].headRefName | select(startswith("release-please--"))][0] // empty') + --json headRefName,headRepositoryOwner,number,author \ + --jq '[ .[] + | select(.headRepositoryOwner.login == env.OWNER) + | select(.author.login == "app/github-actions") + | select(.headRefName | startswith("release-please--")) + ] | max_by(.number).headRefName // empty') fi if [ -z "$branch" ]; then echo "no open release PR; nothing to sync" @@ -141,20 +156,23 @@ jobs: GH_TOKEN: ${{ github.token }} BRANCH: ${{ steps.resolve.outputs.branch }} run: | - # A release branch cut before pr-checks gained its workflow_dispatch - # trigger 422s ("does not have a workflow_dispatch trigger" reported - # against the dispatched ref's copy of the file). That is the one - # tolerated failure: it self-heals when release-please next rewrites - # the branch from current main. Anything else fails the job loudly. - out=$(gh api "repos/${GITHUB_REPOSITORY}/actions/workflows/pr-checks.yml/dispatches" \ - -f "ref=$BRANCH" 2>&1) && exit 0 - if echo "$out" | grep -qi "does not have a workflow_dispatch trigger"; then - echo "release branch predates the dispatch trigger; checks attach after release-please next rebases it" - echo "$out" - exit 0 - fi - echo "$out" - exit 1 + # Every dispatch failure fails the job, including the 422 a release + # branch cut before pr-checks gained its workflow_dispatch trigger + # returns ("does not have a workflow_dispatch trigger", reported + # against the dispatched ref's copy of the file). An earlier revision + # tolerated exactly that 422 on the theory that release-please would + # rewrite the branch and heal it, but a rewrite only happens when a + # later releasable commit lands: an open release PR nobody touches is + # never rewritten. Tolerating it therefore left the lock-sync commit + # this job had just pushed sitting on the release head with no + # --locked validation, which is the precise state this workflow exists + # to prevent. The tolerance is also no longer needed: once this lands, + # every release branch is cut from a main that already carries the + # trigger, so the only branch that could 422 is one open at merge time + # (there is none), and a job rerun after a manual rebase is safe (the + # sync no-ops, the dispatch retries). + gh api "repos/${GITHUB_REPOSITORY}/actions/workflows/pr-checks.yml/dispatches" \ + -f "ref=$BRANCH" # Each architecture builds NATIVELY (amd64 on ubuntu-latest, arm64 on # ubuntu-24.04-arm) and pushes by digest; docker-manifest below stitches the From ebfe89d1c9c9a9d3b87df2d0c008b9932f8bf8ac Mon Sep 17 00:00:00 2001 From: t Date: Tue, 28 Jul 2026 16:13:39 -0500 Subject: [PATCH 6/6] ci: declare the lock-sync toolchain and extend --locked to the shipping builds sync-release-lock ran cargo update --workspace on whatever Rust the ubuntu-latest image shipped, so the lock it wrote for the release PR came off an undeclared input. Install the same stable toolchain the other cargo jobs use. This does not make resolution identical (stable moves, and the MSRV gate checks the same lock on 1.91), it just removes the runner image from the equation. The release-binaries build, both Dockerfiles and the darwin path of build-bins.sh also resolved without --locked, so a lockfile disagreeing with the manifests was caught on the PR gates but not where artifacts are actually produced. Add --locked to all five. Two of those five cannot reach resolution today and are hardened for when they can: the Dockerfile dep-cache layer at line 24 copies four of the workspace's six member manifests, so cargo dies at workspace load and || true swallows it, and Dockerfile.bins pins rust:1.85 against a 1.91 MSRV. Both are pre-existing and left alone here. The live coverage comes from release.yml, Dockerfile:37 and build-bins.sh. The gitlawb-core dependency-purity gate still resolves without --locked on purpose, but its comment justified that by saying the build and test jobs do the same, which stopped being true when those jobs gained --locked. Restate the real reason: a stale lock would red that gate for something unrelated to the dependency closure it checks. --- .github/workflows/release.yml | 14 +++++++++++++- Dockerfile | 4 ++-- Dockerfile.bins | 2 +- scripts/build-bins.sh | 2 +- scripts/check-gitlawb-core-deps.sh | 14 +++++++++----- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2392d001..750737c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -120,6 +120,18 @@ jobs: with: ref: ${{ steps.resolve.outputs.branch }} + # Resolve on a declared toolchain instead of whatever Rust the runner + # image happens to ship, so the lock this job writes comes off the same + # stable channel the other cargo jobs use. Not a claim of identical + # resolution: `stable` still moves between runs, and the MSRV gate + # checks this same lock on 1.91 (pr-checks.yml). It only removes the + # runner image as an undeclared input. + - name: Install Rust toolchain + if: ${{ steps.resolve.outputs.branch != '' }} + uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # stable + with: + toolchain: stable + - name: Sync workspace crate versions into Cargo.lock if: ${{ steps.resolve.outputs.branch != '' }} run: cargo update --workspace @@ -434,7 +446,7 @@ jobs: set -euo pipefail args="" for b in $BINS; do args="$args -p $b"; done - cargo build --release --target ${{ matrix.target }} $args + cargo build --release --locked --target ${{ matrix.target }} $args # Run each packaged binary's --version so a broken release artifact fails the # build instead of shipping. Every target builds on a matching-arch runner, diff --git a/Dockerfile b/Dockerfile index 55ef0c15..e5bbed8f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN mkdir -p crates/gitlawb-core/src crates/gitlawb-node/src crates/gl/src crate echo 'fn main() {}' > crates/gl/src/main.rs && \ echo 'fn main() {}' > crates/git-remote-gitlawb/src/main.rs && \ echo '' > crates/gitlawb-core/src/lib.rs && \ - cargo build --release -p gitlawb-node -p gl -p git-remote-gitlawb || true + cargo build --release --locked -p gitlawb-node -p gl -p git-remote-gitlawb || true # Now copy real sources and build for real. # Force-bump mtimes so cargo's fingerprint check rebuilds — without this, @@ -34,7 +34,7 @@ RUN find crates -name "*.rs" -exec touch {} + && \ rm -rf target/release/.fingerprint/gitlawb-node-* \ target/release/.fingerprint/gl-* \ target/release/.fingerprint/git-remote-gitlawb-* && \ - cargo build --release -p gitlawb-node -p gl -p git-remote-gitlawb && \ + cargo build --release --locked -p gitlawb-node -p gl -p git-remote-gitlawb && \ strip target/release/gitlawb-node target/release/gl target/release/git-remote-gitlawb # ── Runtime stage ─────────────────────────────────────────────────────────── diff --git a/Dockerfile.bins b/Dockerfile.bins index c2110b17..924c402e 100644 --- a/Dockerfile.bins +++ b/Dockerfile.bins @@ -23,7 +23,7 @@ COPY crates/ crates/ # Configure cross-linker for aarch64 ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-gnu-gcc -RUN cargo build --release --target "$TARGET" -p gl -p git-remote-gitlawb +RUN cargo build --release --locked --target "$TARGET" -p gl -p git-remote-gitlawb FROM debian:bookworm-slim ARG TARGET diff --git a/scripts/build-bins.sh b/scripts/build-bins.sh index 06911e17..a8783b5e 100755 --- a/scripts/build-bins.sh +++ b/scripts/build-bins.sh @@ -46,7 +46,7 @@ build_darwin_arm64() { echo "==> Building darwin-arm64 (native cargo)..." cd "$ROOT" export PATH="$HOME/.cargo/bin:$PATH" - cargo build --release -p gl -p git-remote-gitlawb + cargo build --release --locked -p gl -p git-remote-gitlawb cp target/release/gl "$OUT/gl-darwin-arm64" cp target/release/git-remote-gitlawb "$OUT/git-remote-gitlawb-darwin-arm64" chmod +x "$OUT/gl-darwin-arm64" "$OUT/git-remote-gitlawb-darwin-arm64" diff --git a/scripts/check-gitlawb-core-deps.sh b/scripts/check-gitlawb-core-deps.sh index e9c114ca..5580dd6a 100755 --- a/scripts/check-gitlawb-core-deps.sh +++ b/scripts/check-gitlawb-core-deps.sh @@ -23,11 +23,15 @@ if [ ! -f "$ALLOW" ]; then exit 1 fi -# `cargo tree` resolves like the build/test jobs (no --locked): the committed -# Cargo.lock can lag the manifests, and --locked would red this gate for -# lock-staleness reasons unrelated to gitlawb-core's dependencies. Resolving can -# refresh Cargo.lock as a side effect, so snapshot and restore it — this check -# must never leave the working tree dirty when run locally. +# `cargo tree` resolves WITHOUT --locked on purpose, unlike the blocking cargo +# jobs in pr-checks. This gate answers one question, whether gitlawb-core's +# dependency closure gained something unallowlisted, and a stale Cargo.lock +# would red it for a reason that has nothing to do with that closure. Lock +# staleness is already caught by the --locked cargo jobs, so it does not need a +# second gate here. +# +# Resolving can refresh Cargo.lock as a side effect, so snapshot and restore +# it: this check must never leave the working tree dirty when run locally. lock_backup="$(mktemp)" cp "$ROOT/Cargo.lock" "$lock_backup" restore_lock() { cp "$lock_backup" "$ROOT/Cargo.lock"; rm -f "$lock_backup"; }