desktop: commit Cargo.lock and gate CI on it (issue 2102)
The desktop crate is a binary, and binaries commit their lockfile. Without one every run re-resolved the graph: a tagged .deb/.AppImage/.exe couldn't be rebuilt from its tag, any semver-compatible upstream release landed automatically on the next build — the failure mode hardest to read, because the commit that broke it changed nothing relevant — and Renovate had no lockfile to bump, leaving Rust dependency movement invisible to the Dashboard. Generated with cargo generate-lockfile inside ci-tauri:1.97, the same image CI builds in, so the format and the picked versions are what CI would have chosen itself. That takes the artifact-upload round-trip the issue proposed off the table: ci-requirements.md already blesses the image for cargo fmt, and resolving a dependency graph is no more a build than formatting is. 503 packages. Enforcement goes on each job's FIRST cargo invocation rather than the bundle build: cargo clippy --locked on Linux, and its own cargo fetch --locked step on Windows, whose only crate-graph command is otherwise the cross-compile itself. Drift fails in the first thirty seconds instead of thirty minutes in, and everything after the gate in that job compiles the recorded versions anyway. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,12 +52,17 @@ jobs:
|
|||||||
run: npm ci && npm run build
|
run: npm ci && npm run build
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
|
|
||||||
|
# --locked on the FIRST cargo invocation of the job is the lockfile gate: it
|
||||||
|
# fails the run if Cargo.toml and the committed Cargo.lock disagree, instead
|
||||||
|
# of silently re-resolving. Everything after it in this job then compiles the
|
||||||
|
# exact versions recorded in the lockfile, so the flag isn't repeated on the
|
||||||
|
# bundle build (issue 2102).
|
||||||
- name: Clippy
|
- name: Clippy
|
||||||
run: cargo clippy --all-targets -- -D warnings
|
run: cargo clippy --locked --all-targets -- -D warnings
|
||||||
working-directory: desktop/src-tauri
|
working-directory: desktop/src-tauri
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: cargo test
|
run: cargo test --locked
|
||||||
working-directory: desktop/src-tauri
|
working-directory: desktop/src-tauri
|
||||||
|
|
||||||
# Deliberately AFTER clippy + test, not before.
|
# Deliberately AFTER clippy + test, not before.
|
||||||
@@ -244,6 +249,15 @@ jobs:
|
|||||||
run: cargo tauri icon app-icon.png
|
run: cargo tauri icon app-icon.png
|
||||||
working-directory: desktop/src-tauri
|
working-directory: desktop/src-tauri
|
||||||
|
|
||||||
|
# This lane's lockfile gate (the Linux job gets it from `cargo clippy
|
||||||
|
# --locked`). It has to be its own step here because the build is this job's
|
||||||
|
# only crate-graph command, and discovering the drift 30 minutes into a
|
||||||
|
# cross-compile is the expensive way to learn it. Fetching for the Windows
|
||||||
|
# target also pre-warms exactly the crates the build will want.
|
||||||
|
- name: Verify the lockfile and fetch dependencies
|
||||||
|
run: cargo fetch --locked --target x86_64-pc-windows-msvc
|
||||||
|
working-directory: desktop/src-tauri
|
||||||
|
|
||||||
# --runner cargo-xwin swaps cargo for the cross-compiling driver (it supplies
|
# --runner cargo-xwin swaps cargo for the cross-compiling driver (it supplies
|
||||||
# the MSVC CRT/SDK, pre-warmed into the image, and links with lld-link).
|
# the MSVC CRT/SDK, pre-warmed into the image, and links with lld-link).
|
||||||
# Frontend already built above; skip the beforeBuildCommand rebuild.
|
# Frontend already built above; skip the beforeBuildCommand rebuild.
|
||||||
|
|||||||
@@ -179,6 +179,36 @@ files behind; `CARGO_HOME` points somewhere writable for that user.
|
|||||||
exceed 100 characters and survive only because rustfmt cannot break a string
|
exceed 100 characters and survive only because rustfmt cannot break a string
|
||||||
literal — copying that shape caused one of the four failures.
|
literal — copying that shape caused one of the four failures.
|
||||||
|
|
||||||
|
## The desktop lockfile
|
||||||
|
|
||||||
|
`desktop/src-tauri/Cargo.lock` is **committed**, per Cargo's own guidance for
|
||||||
|
binary crates. Without it every CI run re-resolved the graph, which meant a
|
||||||
|
released `.deb`/`.AppImage`/`.exe` couldn't be rebuilt from its tag, a build
|
||||||
|
could break with no repo change, and Renovate had nothing to bump (issue 2102).
|
||||||
|
|
||||||
|
Enforced by `--locked` on each job's **first** cargo invocation — `cargo clippy
|
||||||
|
--locked` on Linux, a dedicated `cargo fetch --locked --target
|
||||||
|
x86_64-pc-windows-msvc` step on Windows. If the manifest and the lockfile
|
||||||
|
disagree, the run fails there instead of silently re-resolving; everything after
|
||||||
|
it in the same job then compiles the recorded versions, so the flag isn't
|
||||||
|
repeated on the bundle build. The Windows step exists separately because that
|
||||||
|
job's only crate-graph command is the cross-compile itself, and drift is cheaper
|
||||||
|
to learn in the first thirty seconds than thirty minutes in.
|
||||||
|
|
||||||
|
To regenerate it after a dependency change — same reasoning as `cargo fmt`
|
||||||
|
above, and resolution is neither a test run nor a build:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run --rm --user "$(id -u):$(id -g)" -e CARGO_HOME=/tmp/cargo \
|
||||||
|
-v "$PWD/desktop/src-tauri:/w" -w /w \
|
||||||
|
git.fabledsword.com/bvandeusen/ci-tauri:1.97 cargo generate-lockfile
|
||||||
|
```
|
||||||
|
|
||||||
|
Resolving inside the CI image rather than against some other cargo is what keeps
|
||||||
|
the lockfile format and the picked versions identical to what CI would have
|
||||||
|
chosen. Commit the result in the same change as the `Cargo.toml` edit — a
|
||||||
|
manifest change pushed without it fails the gate.
|
||||||
|
|
||||||
## Pushing: `dev` is both a branch and a tag
|
## Pushing: `dev` is both a branch and a tag
|
||||||
|
|
||||||
`git push origin dev` fails in this repo:
|
`git push origin dev` fails in this repo:
|
||||||
|
|||||||
Generated
+5311
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user