feat(version): train-aware update check baked into the binary (FJ-15) #13

Merged
David merged 1 commit from feat/version-train-aware-check-fj-15 into main 2026-05-25 16:56:12 +02:00
Owner

What

Builds on FJ-14 to make fj version --check train-aware. The binary now bakes which publish train it came from (release vs the rolling latest) plus its git SHA, and the check follows that train: semver against the newest fork release for release, git-SHA against a published manifest for latest. A --train <release|latest> flag redirects the check at the other train for one invocation.

Resolves FJ-15.

Why

The latest train is rolling: every build under the latest package tag carries the same CARGO_PKG_VERSION, so semver cannot distinguish two latest builds. A per-build identity (the git SHA) is required, and the binary did not previously know its train or SHA (BUILD_TYPE / GIT_SHA were never baked).

Changes

  • crates/fj/build.rs: bake FJ_TRAIN (from FJ_TRAIN) and FJ_GIT_SHA (from GIT_SHA) as rustc-env, skipping empty values so a plain cargo build reads None; add rerun-if-env-changed for FJ_TRAIN and GIT_SHA.
  • oci-build/get-tags.nu: add --train, emitting release for an exact v* tag and latest otherwise.
  • oci-build/Dockerfile and Dockerfile.windows: add ARG FJ_TRAIN and expose FJ_TRAIN + GIT_SHA as ENV to the real-source cargo build (dummy-prime builds untouched).
  • .forgejo/workflows/build-binary.yml and build-binary-windows.yml: pass --build-arg FJ_TRAIN=<train> and, after uploading the binary to the latest package version, publish a per-arch manifest (version-linux-x86_64.json / version-windows-x86_64.json, separate filenames so the two workflows do not race) with train, tag, sha, built_at.
  • crates/fj/src/version.rs (under update-check): add --train <release|latest> defaulting to the baked train; print baked train and SHA under version --verbose; the latest branch GETs the per-arch manifest, compares its sha to FJ_GIT_SHA, and prints up-to-date or a new latest_behind message with the Generic Packages download URL. The release branch keeps FJ-14 behavior.
  • New Fluent key msg-version-update_check-latest_behind added to every locale (translated for the compiled en-US / de-DE / zh-Hans bundles, English placeholder for the dormant it/pl/ru/tok files).

Testing

  • cargo fmt --check, cargo clippy --all-targets -- -D warnings (default and --features update-check), cargo test, and feature builds all pass; build.rs validates all seven locale files.
  • fj version --verbose prints the baked train and SHA; a build with FJ_TRAIN=latest GIT_SHA=... correctly shows them, and rerun-if-env-changed rebuilds on change.
  • fj version --check --train latest hits .../forgejo-cli/latest/version-linux-x86_64.json (404 until this PR's workflow publishes the manifest); --check (release default) hits the Releases API.

Note

The commit uses a bare #FJ-15 reference (no State Done trailer). Per the repo's Forgejo VCS integration, commit commands are applied at push time, not merge time, so a State Done trailer would resolve the issue prematurely while this PR is still under review. The issue stays In Progress and AI Agent is set to Code Review.

## What Builds on FJ-14 to make `fj version --check` train-aware. The binary now bakes which publish train it came from (`release` vs the rolling `latest`) plus its git SHA, and the check follows that train: semver against the newest fork release for `release`, git-SHA against a published manifest for `latest`. A `--train <release|latest>` flag redirects the check at the other train for one invocation. Resolves FJ-15. ## Why The `latest` train is rolling: every build under the `latest` package tag carries the same `CARGO_PKG_VERSION`, so semver cannot distinguish two `latest` builds. A per-build identity (the git SHA) is required, and the binary did not previously know its train or SHA (`BUILD_TYPE` / `GIT_SHA` were never baked). ## Changes - `crates/fj/build.rs`: bake `FJ_TRAIN` (from `FJ_TRAIN`) and `FJ_GIT_SHA` (from `GIT_SHA`) as `rustc-env`, skipping empty values so a plain `cargo build` reads `None`; add `rerun-if-env-changed` for `FJ_TRAIN` and `GIT_SHA`. - `oci-build/get-tags.nu`: add `--train`, emitting `release` for an exact `v*` tag and `latest` otherwise. - `oci-build/Dockerfile` and `Dockerfile.windows`: add `ARG FJ_TRAIN` and expose `FJ_TRAIN` + `GIT_SHA` as `ENV` to the real-source `cargo build` (dummy-prime builds untouched). - `.forgejo/workflows/build-binary.yml` and `build-binary-windows.yml`: pass `--build-arg FJ_TRAIN=<train>` and, after uploading the binary to the `latest` package version, publish a per-arch manifest (`version-linux-x86_64.json` / `version-windows-x86_64.json`, separate filenames so the two workflows do not race) with `train`, `tag`, `sha`, `built_at`. - `crates/fj/src/version.rs` (under `update-check`): add `--train <release|latest>` defaulting to the baked train; print baked train and SHA under `version --verbose`; the `latest` branch GETs the per-arch manifest, compares its `sha` to `FJ_GIT_SHA`, and prints up-to-date or a new `latest_behind` message with the Generic Packages download URL. The `release` branch keeps FJ-14 behavior. - New Fluent key `msg-version-update_check-latest_behind` added to every locale (translated for the compiled en-US / de-DE / zh-Hans bundles, English placeholder for the dormant it/pl/ru/tok files). ## Testing - `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings` (default and `--features update-check`), `cargo test`, and feature builds all pass; `build.rs` validates all seven locale files. - `fj version --verbose` prints the baked train and SHA; a build with `FJ_TRAIN=latest GIT_SHA=...` correctly shows them, and `rerun-if-env-changed` rebuilds on change. - `fj version --check --train latest` hits `.../forgejo-cli/latest/version-linux-x86_64.json` (404 until this PR's workflow publishes the manifest); `--check` (release default) hits the Releases API. ## Note The commit uses a bare `#FJ-15` reference (no `State Done` trailer). Per the repo's Forgejo VCS integration, commit commands are applied at push time, not merge time, so a `State Done` trailer would resolve the issue prematurely while this PR is still under review. The issue stays `In Progress` and AI Agent is set to `Code Review`.
feat(version): train-aware update check baked into the binary (FJ-15)
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 37s
Create release / Create release from merged PR (pull_request) Has been skipped
d92a2bdb52
Building on FJ-14, the binary now knows which publish train it came from and which exact build it is, so `fj version --check` can follow its own train. The `release` train keeps FJ-14's Releases-API + semver comparison; the rolling `latest` train carries the same CARGO_PKG_VERSION on every build, so semver cannot tell two builds apart and a per-build identity (the git SHA) is required.

Bake the train and SHA at build time: crates/fj/build.rs reads FJ_TRAIN and GIT_SHA from the environment and emits them as FJ_TRAIN / FJ_GIT_SHA rustc-env (empty values skipped so source builds read None), with rerun-if-env-changed for both. oci-build/Dockerfile and Dockerfile.windows add `ARG FJ_TRAIN` and expose FJ_TRAIN and GIT_SHA as ENV for the real-source cargo build so build.rs sees them; the dummy-prime builds are untouched.

Classify and publish the train: oci-build/get-tags.nu gains `--train`, emitting `release` for an exact `v*` tag and `latest` otherwise. Both build-binary*.yml workflows pass `--build-arg FJ_TRAIN=<train>` alongside GIT_SHA, and after uploading the binary to the `latest` package version they publish a per-arch manifest (version-linux-x86_64.json / version-windows-x86_64.json, separate filenames so the two workflows do not race) containing train, tag, sha, and built_at.

Train-aware check in crates/fj/src/version.rs (under update-check): add a `--train <release|latest>` override defaulting to the baked FJ_TRAIN, surface the baked train and SHA under `version --verbose`, and add the `latest` branch that GETs the per-arch manifest, compares its sha to the baked FJ_GIT_SHA, and prints either "up to date" or a new msg-version-update_check-latest_behind message with the Generic Packages download URL. The new Fluent key is added to every locale (translated for the compiled en-US / de-DE / zh-Hans bundles, English placeholder for the dormant ones) and build.rs validation passes.

#FJ-15

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
David merged commit fbc1a9dacd into main 2026-05-25 16:56:12 +02:00
David deleted branch feat/version-train-aware-check-fj-15 2026-05-25 16:56:12 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pandoras-box/forgejo-cli!13
No description provided.