feat(build-time-versioning): add build_time meson option and C-wide define
Add a build_time meson option (string, default '') sibling to the existing commit_id option, threaded project-wide via the same add_project_arguments() call that already defines VERSION_COMMIT_ID -- one call, one mechanism, no new plumbing. No consumer wired yet (later tasks); a plain meson setup with neither option set still configures cleanly with both defines resolving to empty string. Task 1/13 of build-time-versioning (spec: .kiro/specs/build-time-versioning/). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
12408a384b
commit
4b7cc7867f
3 changed files with 127 additions and 1 deletions
124
.kiro/specs/build-time-versioning/tasks.md
Normal file
124
.kiro/specs/build-time-versioning/tasks.md
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
# Implementation Plan
|
||||
|
||||
- [x] 1. Foundation: meson build-time option and C project-wide define
|
||||
- Add a `build_time` meson option (string, default `''`) alongside the existing `commit_id` option in `src/meson.options`
|
||||
- Extend `src/meson.build`'s existing `add_project_arguments()` call to also define `VERSION_BUILD_TIME` for every C component, mirroring how `VERSION_COMMIT_ID` is already threaded through
|
||||
- Observable: a plain `meson setup` with neither option set still configures successfully (both defines resolve to empty string, no build failure)
|
||||
- _Requirements: 1.1, 1.2, 1.4, 4.3_
|
||||
|
||||
- [ ] 2. Foundation: compute real values at both build entry points
|
||||
- [ ] 2.1 (P) xce-build.sh computes and passes commit id and build time
|
||||
- Compute `commit_id` via `git rev-parse --short HEAD`, appended with `-dirty` when the tree has uncommitted changes (`git status --porcelain` or `git diff --quiet HEAD --`)
|
||||
- Compute `build_time` via `date -u +%Y-%m-%dT%H:%M:%SZ`
|
||||
- Fall back to the literal string `unknown` for `commit_id` when `git` itself fails (e.g. no `.git` present)
|
||||
- Append `-Dcommit_id="$commit_id" -Dbuild_time="$build_time"` to `MESON_OPTS` for every build profile, before the existing `meson setup`/`meson setup --reconfigure` calls
|
||||
- After computing both values, verify each is non-empty (`build_time` always is; `commit_id` falls back to `unknown` only on a genuine `git` failure) and print a loud warning to stderr if either resolves empty anyway -- the build tooling must not silently proceed with a value it cannot confirm
|
||||
- Observable: running `/xce-build scheduler debug` followed by the resulting binary's `--version` shows a commit id matching the current `git rev-parse --short HEAD` at build time, not empty; deliberately breaking the computation (e.g. temporarily renaming `.git`) prints the warning instead of silently succeeding
|
||||
- _Requirements: 1.1, 1.2, 1.3, 1.4, 4.1, 4.2, 5.1, 5.2_
|
||||
- _Boundary: xce-build.sh_
|
||||
|
||||
- [ ] 2.2 (P) Nix packages compute and pass build time
|
||||
- Add a `builtins.currentTime`-derived build-time value in `src/flake.nix`, passed via a new `-Dbuild_time=` entry alongside the existing `-Dcommit_id=` wiring in `xce.nix`/`xcecli.nix`
|
||||
- Since `builtins.currentTime` cannot itself be empty, the confirmation this requirement asks for is structural here: assert (in the derivation or a post-build check) that the meson option actually reached the binary, rather than a runtime empty-value check
|
||||
- Observable: `nix build .#xcecore_debug` produces a binary whose `--version` shows a non-empty build time, without any `git` invocation inside the sandboxed derivation
|
||||
- _Requirements: 1.1, 1.2, 1.4, 4.1, 4.2, 5.1, 5.2_
|
||||
- _Boundary: Nix packaging_
|
||||
|
||||
- [ ] 3. Core: C daemon version display
|
||||
- [ ] 3.1 Extend the shared version macro with build time and unknown fallback
|
||||
- Extend `MK_VERSION`/`STR` in `src/include/utils.h` so the composed string carries both commit id and build time
|
||||
- Both fields render as `unknown` when their underlying define is empty, never a blank/garbled string
|
||||
- Observable: a build with both meson options unset produces a `--version` string containing `unknown` for both fields, not empty gaps
|
||||
- _Requirements: 1.4, 2.2_
|
||||
- _Boundary: utils.h_
|
||||
|
||||
- [ ] 3.2 (P) Controller and scheduler: version in --version and startup log
|
||||
- Update each daemon's `argp_program_version` construction to use the extended macro from 3.1
|
||||
- Add the version string to each daemon's existing first startup INFO log line (controller's `"My name is %s"` line, scheduler's `"HA cluster config..."` line) rather than a second, independently-formatted line
|
||||
- Observable: `xce_controller --version` and `xce_scheduler --version` each print commit id + build time and exit without starting the daemon; each daemon's startup log's first lines include the identical two values
|
||||
- _Requirements: 1.1, 1.2, 2.1, 2.2, 3.1, 3.2, 4.3_
|
||||
- _Boundary: controller/main.c, scheduler/main.c_
|
||||
- _Depends: 3.1_
|
||||
|
||||
- [ ] 3.3 (P) Worker: add --version and startup log line
|
||||
- Add a long-only `--version` option to worker's `getopt_long()` option table and a handling case that prints the same macro output and exits before any other startup work
|
||||
- Add the version string to worker's existing first startup INFO log line (its own `"HA cluster config..."` line)
|
||||
- Observable: `xcecd --version` prints commit id + build time and exits without starting the daemon; the startup log's first lines include the identical two values
|
||||
- _Requirements: 1.1, 1.2, 2.1, 2.2, 3.1, 3.2, 4.3_
|
||||
- _Boundary: worker/main.c_
|
||||
- _Depends: 3.1_
|
||||
|
||||
- [ ] 4. Core: Go binary version display
|
||||
- [ ] 4.1 go_build script injects ldflags from environment
|
||||
- `src/tools/go_build` reads `XCE_GIT_COMMIT`/`XCE_BUILD_TIME` from its environment (both optional, empty-safe) and appends `-ldflags "-X main.GitCommit=... -X main.BuildTime=..."` to its `go build` invocation, falling back to `unknown` for any unset value
|
||||
- Observable: invoking `go_build` with neither env var set still produces a working binary whose injected vars read `unknown`
|
||||
- _Requirements: 1.1, 1.2, 1.4, 4.1, 4.2_
|
||||
- _Boundary: go_build script_
|
||||
|
||||
- [ ] 4.2 apiserver and xcecli meson builds pass resolved values through
|
||||
- `src/frontend/apiserver/meson.build` and `src/frontend/xcecli/meson.build` read the project's `commit_id`/`build_time` meson options and pass them as `XCE_GIT_COMMIT`/`XCE_BUILD_TIME` env vars into their existing `custom_target()` calls
|
||||
- Observable: a meson-driven `/xce-build apiserver` (with 2.1's values set) produces an `xce_apiserver` binary whose linked-in vars are non-`unknown`
|
||||
- _Requirements: 1.1, 1.2, 4.1, 4.2_
|
||||
- _Boundary: apiserver/meson.build, xcecli/meson.build_
|
||||
- _Depends: 4.1_
|
||||
|
||||
- [ ] 4.3 (P) Makefile dev-loop path computes and passes the same values
|
||||
- `src/frontend/Makefile`'s `build-server`/`build-cli` targets compute commit id (git, dirty-suffixed) and build time (date) directly and pass the identical `-ldflags` shape 4.1 establishes, independent of meson
|
||||
- Fall back to `unknown` for commit id when `git` itself fails (e.g. no `.git` present), matching 2.1's/4.1's fallback discipline
|
||||
- Observable: `make build-server` and `make build-cli` each produce a binary whose `--version`/`-version` output matches the same commit id `git rev-parse --short HEAD` reports at build time
|
||||
- _Requirements: 1.1, 1.2, 1.3, 1.4, 4.1, 4.2, 5.1, 5.2_
|
||||
- _Boundary: Makefile_
|
||||
- _Depends: 4.1_
|
||||
|
||||
- [ ] 4.4 (P) apiserver: version flag, vars, and startup log
|
||||
- Declare `GitCommit`/`BuildTime` package vars (default `unknown`) in `src/frontend/apiserver/cmd/main.go`
|
||||
- Add a `-version` flag, checked before `utils.InitLogger()`, that prints both values and exits with no logging side effects
|
||||
- Extend the existing `logger.Info("********** Initialize Logger done!")` call site to also log both values
|
||||
- Observable: `xce_apiserver -version` prints both values and exits without starting the server; the startup log's first lines include the identical two values
|
||||
- _Requirements: 1.1, 1.2, 2.1, 2.2, 3.1, 3.2_
|
||||
- _Boundary: apiserver/cmd/main.go_
|
||||
- _Depends: 4.1_
|
||||
|
||||
- [ ] 4.5 (P) xcecli: version field and vars
|
||||
- Declare the same two package vars in `src/frontend/xcecli/cmd/main.go`; set Cobra's built-in `rootCmd.Version` field from them once at init
|
||||
- Observable: `xcecli --version` (Cobra's native handling) prints both values and exits
|
||||
- _Requirements: 1.1, 1.2, 2.1_
|
||||
- _Boundary: xcecli/cmd/main.go_
|
||||
- _Depends: 4.1_
|
||||
|
||||
- [ ] 5. Core: xceadmin version display
|
||||
- [ ] 5.1 (P) meson-build.sh generates a build-info module before packaging
|
||||
- `src/xceadmin/meson.build`'s `custom_target()` passes the resolved commit id/build time to `meson-build.sh` (new positional args or env vars)
|
||||
- `meson-build.sh` writes a small `_build_info.py` (containing `GIT_COMMIT`/`BUILD_TIME` string constants, `unknown` fallback) into the mirrored source tree's xceadmin package directory, before the existing `pip install` step, matching the schema-sync step's own before-install ordering
|
||||
- After writing the module, verify it actually landed in the mirrored tree before proceeding to `pip install` (e.g. a file-exists check) and fail the build loudly if it did not, rather than silently packaging the fallback-shaped-but-wrong wheel
|
||||
- Observable: a meson-driven `/xce-build xceadmin` produces a wheel whose installed `_build_info.py` contains non-`unknown` values when 2.1's values are set
|
||||
- _Requirements: 1.1, 1.2, 1.4, 4.1, 4.2_
|
||||
- _Boundary: xceadmin/meson.build, xceadmin/meson-build.sh_
|
||||
- _Depends: 1_
|
||||
|
||||
- [ ] 5.2 (P) Committed fallback stub and CLI version wiring
|
||||
- Commit a fallback `src/xceadmin/src/xceadmin/_build_info.py` with both fields set to `unknown` (used whenever 5.1's generated version isn't present, e.g. `pip install -e .`)
|
||||
- Wire `click.version_option()` on `cli.py`'s top-level group, importing `_build_info` defensively and composing its version string from `pyproject.toml`'s static version plus the two build-info fields
|
||||
- Observable: both `pip install -e .` (no meson) and the meson-built wheel produce a working `xceadmin --version` that prints and exits; the editable-install case shows `unknown` for both build fields, never an import error
|
||||
- _Requirements: 1.1, 1.2, 2.1_
|
||||
- _Boundary: xceadmin/src/xceadmin_
|
||||
|
||||
- [ ] 6. Integration: cross-toolchain consistency and regression verification
|
||||
- [ ] 6.1 Motivating-incident regression test
|
||||
- Build a C daemon via `/xce-build` (any profile) and confirm its `--version` commit id is non-`unknown` and matches `git rev-parse --short HEAD` at build time -- the exact scenario that was previously silent/empty
|
||||
- Repeat against at least the `asan` and `debug` profiles specifically (the motivating incident was a `debug`-profile binary), confirming both carry accurate, matching values
|
||||
- Observable: an automated check fails loudly if `xce-build.sh`'s computed commit id ever regresses to empty/missing, in either profile
|
||||
- _Requirements: 4.1, 4.2, 4.3, 5.1, 5.2_
|
||||
- _Depends: 2.1, 3.2, 3.3_
|
||||
|
||||
- [ ] 6.2 Version/startup-log consistency test
|
||||
- For one C daemon (controller or scheduler) and one Go binary (apiserver), capture the startup log's version line and separately run `--version`/`-version`, asserting the two report byte-identical commit id and build time
|
||||
- Observable: a passing test proves `--version` and the startup log can never disagree for the same artifact
|
||||
- _Requirements: 2.2_
|
||||
- _Depends: 3.2, 4.4_
|
||||
|
||||
- [ ] 6.3 xceadmin end-to-end build/install/version cycle
|
||||
- Run xceadmin's full meson-driven build (schema sync, venv install, pytest, wheel build), install the resulting wheel, and confirm `xceadmin --version` reports the generated (non-`unknown`) build-info fields
|
||||
- Observable: the installed wheel's `--version` output differs from an editable (`pip install -e .`) install's `unknown`-only output, proving the generated module actually replaces the fallback
|
||||
- _Requirements: 1.1, 1.2, 2.1, 4.1, 4.2_
|
||||
- _Depends: 5.1, 5.2_
|
||||
Loading…
Add table
Add a link
Reference in a new issue