feat(dirty-content-fingerprint): xceadmin shows fingerprint in --version

Adds DIRTY_FINGERPRINT = "" to _build_info.py's committed fallback stub
and cli.py's separate ImportError fallback class. New
_compose_version_display() applies the strip-and-append rule via a
genuine anchored removesuffix("-dirty"), mirroring the C/Go
implementations (tasks 3.1/4.4/4.5).

Updates one pre-existing test whose hard-coded literal-GIT_COMMIT
assertion no longer holds once a fingerprint is present, to compute its
expected value via the production function instead -- independently
assessed by review as a legitimate strengthening, not a weakened check.
4 new dedicated unit tests independently guard the transform itself with
hard-coded literal assertions, including an anchored-suffix-not-blind-
substring regression case.

Verified independently by review (including a second, differently-
constructed mutation test) across both install paths via a full real
/xce-build xceadmin cycle: editable install shows "unknown, unknown" with
no import error; wheel built from the dirty tree shows <hash>-<fingerprint>,
never <hash>-dirty-<fingerprint>. 267 passed/3 skipped.

This completes all xceadmin work (tasks 5.1-5.2) for this spec.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-08-21 09:20:27 +00:00
parent eeb7a9b4db
commit c79ccf0fae
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
4 changed files with 142 additions and 23 deletions

View file

@ -77,7 +77,7 @@
- _Boundary: xcecli/cmd/main.go_ - _Boundary: xcecli/cmd/main.go_
- _Depends: 4.1_ - _Depends: 4.1_
- [ ] 5. Core: xceadmin fingerprint display - [x] 5. Core: xceadmin fingerprint display
- [x] 5.1 (P) meson-build.sh generates the fingerprint field in the build-info module - [x] 5.1 (P) meson-build.sh generates the fingerprint field in the build-info module
- `dirty_fingerprint` threaded through as an 8th positional arg (`$8`), correctly numbered and consistent between `meson.build` and `meson-build.sh`; `_build_info.py` gains `DIRTY_FINGERPRINT` with an independent empty-string fallback (not `"unknown"`); `GIT_COMMIT`/`BUILD_TIME`'s existing generation and fallback confirmed byte-for-byte untouched - `dirty_fingerprint` threaded through as an 8th positional arg (`$8`), correctly numbered and consistent between `meson.build` and `meson-build.sh`; `_build_info.py` gains `DIRTY_FINGERPRINT` with an independent empty-string fallback (not `"unknown"`); `GIT_COMMIT`/`BUILD_TIME`'s existing generation and fallback confirmed byte-for-byte untouched
- Observable confirmed live (independently re-verified by review, full real build+test+wheel cycles across 3 scenarios): dirty tree -> real, non-empty `DIRTY_FINGERPRINT` present identically in the mirrored tree, the build/lib copy, an installed venv, and the packaged wheel, cross-checked byte-for-byte against that same build's `compile_commands.json`; explicit-empty fingerprint -> genuinely `""` while `GIT_COMMIT`/`BUILD_TIME` pass through real values; all-empty -> `GIT_COMMIT`/`BUILD_TIME` still fall back to `"unknown"` while `DIRTY_FINGERPRINT` stays `""`; 261 passed/3 skipped in all three scenarios - Observable confirmed live (independently re-verified by review, full real build+test+wheel cycles across 3 scenarios): dirty tree -> real, non-empty `DIRTY_FINGERPRINT` present identically in the mirrored tree, the build/lib copy, an installed venv, and the packaged wheel, cross-checked byte-for-byte against that same build's `compile_commands.json`; explicit-empty fingerprint -> genuinely `""` while `GIT_COMMIT`/`BUILD_TIME` pass through real values; all-empty -> `GIT_COMMIT`/`BUILD_TIME` still fall back to `"unknown"` while `DIRTY_FINGERPRINT` stays `""`; 261 passed/3 skipped in all three scenarios
@ -85,10 +85,10 @@
- _Boundary: xceadmin/meson.build, xceadmin/meson-build.sh_ - _Boundary: xceadmin/meson.build, xceadmin/meson-build.sh_
- _Depends: 1_ - _Depends: 1_
- [ ] 5.2 (P) Committed fallback stub and CLI fingerprint wiring - [x] 5.2 (P) Committed fallback stub and CLI fingerprint wiring
- The committed fallback stub (`src/xceadmin/src/xceadmin/_build_info.py`) gains `DIRTY_FINGERPRINT = ""` alongside its existing two `"unknown"` fields - `_build_info.py`'s fallback stub gains `DIRTY_FINGERPRINT = ""`; `cli.py`'s new `_compose_version_display()` applies the strip-and-append rule via a genuine anchored `removesuffix("-dirty")` (independently confirmed via a second, differently-constructed mutation test); both fallback paths (`_build_info.py`'s module stub and `cli.py`'s separate `ImportError` fallback class) correctly carry the field
- `cli.py`'s `_compose_version()` applies the same strip-and-append rule as the other components: if `DIRTY_FINGERPRINT` is non-empty, strip a trailing `-dirty` from `GIT_COMMIT` and append `-DIRTY_FINGERPRINT`; if empty, use `GIT_COMMIT` as-is - A pre-existing test's hard-coded literal-`GIT_COMMIT` assertion was updated to compute its expected value via the production `_compose_version_display()` function instead -- independently assessed by review as a legitimate strengthening (the old assertion's premise no longer holds once a fingerprint is present), not a weakened/gutted check; the 4 new dedicated unit tests independently guard the transform itself with hard-coded literal assertions
- Observable confirmed live (both install paths): an editable install (`pip install -e .`) shows no fingerprint suffix (empty field, `GIT_COMMIT` unaffected, no import error); a wheel built from a dirty tree shows `<hash>-<fingerprint>`, not `<hash>-dirty-<fingerprint>` - Observable confirmed live (independently re-verified by review, both install paths via a full real `/xce-build xceadmin` cycle): editable install shows `0.1.0 (unknown, unknown)`, no import error; wheel built from the dirty tree shows `<hash>-<fingerprint>`, never `<hash>-dirty-<fingerprint>`; full suite 267 passed/3 skipped (261 baseline + 6 new)
- _Requirements: 1.1, 1.2, 1.3, 1.4, 2.1, 4.1_ - _Requirements: 1.1, 1.2, 1.3, 1.4, 2.1, 4.1_
- _Boundary: xceadmin/src/xceadmin_ - _Boundary: xceadmin/src/xceadmin_
- _Depends: 5.1_ - _Depends: 5.1_

View file

@ -1,14 +1,20 @@
"""Committed fallback build-info stub (build-time-versioning task 5.2). """Committed fallback build-info stub (build-time-versioning task 5.2;
extended by dirty-content-fingerprint task 5.2 with DIRTY_FINGERPRINT).
Both fields are always "unknown" here. This file ships checked into git so GIT_COMMIT/BUILD_TIME are always "unknown" here; DIRTY_FINGERPRINT is always
that a non-meson `pip install -e .` (the documented fast-iteration path, "" (empty, not "unknown" -- matching that field's convention everywhere else
`build-deployment.md`) still imports `xceadmin._build_info` cleanly without in the dirty-content-fingerprint feature: empty means "no fingerprint
ever having run the meson build -- Requirement 1.4's "record as unknown available", distinct from the other two fields' "unknown" sentinel for "not
rather than fail" applies here too. injected at all"). This file ships checked into git so that a non-meson `pip
install -e .` (the documented fast-iteration path, `build-deployment.md`)
still imports `xceadmin._build_info` cleanly without ever having run the
meson build -- Requirement 1.4's "record as unknown rather than fail"
applies here too.
When built via the meson custom_target (`src/xceadmin/meson-build.sh`, task When built via the meson custom_target (`src/xceadmin/meson-build.sh`, task
5.1), this exact filename is regenerated with real `GIT_COMMIT`/`BUILD_TIME` 5.1), this exact filename is regenerated with real `GIT_COMMIT`/`BUILD_TIME`/
values -- but only in meson's own out-of-tree MIRRORED copy of this package `DIRTY_FINGERPRINT` values -- but only in meson's own out-of-tree MIRRORED
copy of this package
(`$BUILD_DIR/repo-mirror/src/xceadmin/src/xceadmin/_build_info.py`). This (`$BUILD_DIR/repo-mirror/src/xceadmin/src/xceadmin/_build_info.py`). This
checked-in copy, under the live source tree, is never overwritten. checked-in copy, under the live source tree, is never overwritten.
""" """
@ -17,3 +23,4 @@ from __future__ import annotations
GIT_COMMIT = "unknown" GIT_COMMIT = "unknown"
BUILD_TIME = "unknown" BUILD_TIME = "unknown"
DIRTY_FINGERPRINT = ""

View file

@ -53,16 +53,38 @@ except ImportError: # pragma: no cover - defensive only: a committed
class _build_info: # type: ignore[no-redef] class _build_info: # type: ignore[no-redef]
GIT_COMMIT = "unknown" GIT_COMMIT = "unknown"
BUILD_TIME = "unknown" BUILD_TIME = "unknown"
DIRTY_FINGERPRINT = ""
def _compose_version_display(git_commit: str, dirty_fingerprint: str) -> str:
"""Applies the dirty-content-fingerprint feature's strip-and-append rule
to ``git_commit``: if ``dirty_fingerprint`` is non-empty, a trailing
``-dirty`` suffix on ``git_commit`` is stripped (an anchored suffix
check via ``str.removesuffix``, not a blind substring replace) and
``-<dirty_fingerprint>`` is appended in its place; otherwise
``git_commit`` is returned exactly as-is (already correctly showing
``-dirty`` or not, per the original build-time-versioning feature).
Mirrors ``xce_compose_version_ex()`` in ``src/lib/utils.c`` (task 3.1)
and ``composeVersionDisplay()`` in ``apiserver/cmd/main.go`` /
``xcecli/cmd/main.go`` (tasks 4.4/4.5) -- the equivalent implementations
already approved for the other version-displaying components
(Requirements 1.1, 1.2, 1.3, 1.4, 2.1, 4.1).
"""
if not dirty_fingerprint:
return git_commit
return git_commit.removesuffix("-dirty") + "-" + dirty_fingerprint
def _compose_version() -> str: def _compose_version() -> str:
"""Composes the string `xceadmin --version` prints: pyproject.toml's """Composes the string `xceadmin --version` prints: pyproject.toml's
static semantic version -- read via ``importlib.metadata`` (the standard static semantic version -- read via ``importlib.metadata`` (the standard
way to read an *installed* package's own version, rather than way to read an *installed* package's own version, rather than
hand-parsing pyproject.toml) -- plus the two build-info fields, which are hand-parsing pyproject.toml) -- plus the build-info fields, which are
either task 5.1's meson-generated real values or task 5.2's committed either task 5.1's meson-generated real values or task 5.2's committed
"unknown" fallback, whichever this install currently carries "unknown"/"" fallback, whichever this install currently carries
(Requirements 1.1, 1.2, 2.1). (Requirements 1.1, 1.2, 2.1). ``GIT_COMMIT`` has
``_compose_version_display``'s strip-and-append rule applied against
``DIRTY_FINGERPRINT`` before being embedded here.
""" """
try: try:
pkg_version = _package_version("xceadmin") pkg_version = _package_version("xceadmin")
@ -71,7 +93,8 @@ def _compose_version() -> str:
# entry point already running as `xceadmin`; fails soft to # entry point already running as `xceadmin`; fails soft to
# "unknown" rather than raising, matching Requirement 1.4. # "unknown" rather than raising, matching Requirement 1.4.
pkg_version = "unknown" pkg_version = "unknown"
return f"{pkg_version} ({_build_info.GIT_COMMIT}, {_build_info.BUILD_TIME})" commit_display = _compose_version_display(_build_info.GIT_COMMIT, _build_info.DIRTY_FINGERPRINT)
return f"{pkg_version} ({commit_display}, {_build_info.BUILD_TIME})"
_DEFAULT_OUTPUT = "cluster.bin" _DEFAULT_OUTPUT = "cluster.bin"

View file

@ -93,18 +93,31 @@ def test_cli_version_flag_exits_zero_and_shows_package_version() -> None:
def test_cli_version_flag_includes_build_info_fields() -> None: def test_cli_version_flag_includes_build_info_fields() -> None:
"""The printed --version string must include BOTH _build_info fields """The printed --version string must include BUILD_TIME verbatim, plus
(whichever variant -- "unknown" fallback or meson-generated real values the commit display -- whichever _build_info variant ("unknown"/""
-- is currently installed), not just the bare package version, so fallback, or meson-generated real values) is currently installed -- not
--version and the eventual startup log line (out of this task's scope) just the bare package version (Requirement 2.2). dirty-content-
can never disagree (Requirement 2.2).""" fingerprint task 5.2 note: when DIRTY_FINGERPRINT is empty, the commit
display is GIT_COMMIT verbatim (unchanged from the original
build-time-versioning feature's behavior, asserted directly below by
``test_compose_version_omits_suffix_when_build_info_fingerprint_empty``);
when non-empty (e.g. a wheel built from this dirty tree),
``_compose_version_display()``'s strip-and-append rule means the
composed display -- not the raw GIT_COMMIT string, which may still carry
an unstripped ``-dirty`` suffix -- is what appears in --version output.
This test therefore computes the same expected display the production
code does, rather than asserting GIT_COMMIT literally, so it holds for
both fallback and real-value installs."""
from xceadmin import _build_info from xceadmin import _build_info
runner = CliRunner() runner = CliRunner()
result = runner.invoke(cli, ["--version"]) result = runner.invoke(cli, ["--version"])
assert result.exit_code == 0, result.output assert result.exit_code == 0, result.output
assert _build_info.GIT_COMMIT in result.output expected_commit_display = cli_module._compose_version_display(
_build_info.GIT_COMMIT, _build_info.DIRTY_FINGERPRINT
)
assert expected_commit_display in result.output
assert _build_info.BUILD_TIME in result.output assert _build_info.BUILD_TIME in result.output
@ -121,6 +134,82 @@ def test_build_info_module_is_importable_with_string_fields() -> None:
assert isinstance(_build_info.BUILD_TIME, str) and _build_info.BUILD_TIME assert isinstance(_build_info.BUILD_TIME, str) and _build_info.BUILD_TIME
# ---------------------------------------------------------------------------
# dirty-content-fingerprint task 5.2: DIRTY_FINGERPRINT is a third
# _build_info field (empty-string fallback, not "unknown" -- see
# _build_info.py's docstring) and cli.py's _compose_version_display()
# applies the same strip-and-append rule already approved for the C daemons
# (xce_compose_version_ex(), src/lib/utils.c task 3.1) and the Go binaries
# (composeVersionDisplay(), apiserver/cmd/main.go and xcecli/cmd/main.go
# tasks 4.4/4.5). Tested directly as a pure function (mirroring this file's
# own _format_timestamp_ns precedent) since _compose_version() is evaluated
# once at module-import time to build click.version_option()'s default, so
# monkeypatching _build_info after import would not be observed by a
# `runner.invoke(cli, ["--version"])` call.
# ---------------------------------------------------------------------------
def test_compose_version_display_strips_dirty_suffix_and_appends_fingerprint() -> None:
"""dirty_fingerprint non-empty + git_commit ending in '-dirty' -> the
suffix is stripped and the fingerprint appended in its place
(<hash>-<fingerprint>, not <hash>-dirty-<fingerprint>) -- Requirements
1.1, 1.2, 1.3."""
assert cli_module._compose_version_display("abc1234-dirty", "f00dcafe") == "abc1234-f00dcafe"
def test_compose_version_display_empty_fingerprint_clean_commit_passthrough() -> None:
"""dirty_fingerprint empty + a clean (no -dirty suffix) git_commit ->
git_commit returned exactly as-is -- Requirement 2.1."""
assert cli_module._compose_version_display("abc1234", "") == "abc1234"
def test_compose_version_display_empty_fingerprint_dirty_commit_unchanged() -> None:
"""dirty_fingerprint empty + git_commit already ending in '-dirty'
(fingerprint computation failed, tree still dirty) -> git_commit passed
through completely unchanged, '-dirty' left in place -- this is
Requirement 5.2's fallback, satisfied by simply not touching commit_id
when dirty_fingerprint is empty."""
assert cli_module._compose_version_display("abc1234-dirty", "") == "abc1234-dirty"
def test_compose_version_display_anchored_suffix_not_blind_substring() -> None:
"""A regression case matching the pattern already established in the Go
tests (tasks 4.4/4.5): '-dirty' appearing elsewhere in the commit
string (not as the trailing suffix) must NOT be stripped -- only a
literal trailing '-dirty' is anchored-matched and removed."""
assert (
cli_module._compose_version_display("abc-dirty1234", "f00dcafe") == "abc-dirty1234-f00dcafe"
)
def test_compose_version_includes_fingerprint_when_build_info_has_one(monkeypatch) -> None:
"""_compose_version() (the function that actually feeds
click.version_option()) applies _compose_version_display() against the
live _build_info module's GIT_COMMIT/DIRTY_FINGERPRINT fields --
Requirement 4.1."""
monkeypatch.setattr(cli_module._build_info, "GIT_COMMIT", "abc1234-dirty")
monkeypatch.setattr(cli_module._build_info, "DIRTY_FINGERPRINT", "f00dcafe")
version_str = cli_module._compose_version()
assert "abc1234-f00dcafe" in version_str
assert "abc1234-dirty-f00dcafe" not in version_str
assert "-dirty" not in version_str
def test_compose_version_omits_suffix_when_build_info_fingerprint_empty(monkeypatch) -> None:
"""The committed fallback stub's DIRTY_FINGERPRINT = "" case: --version
shows GIT_COMMIT exactly as _build_info carries it, no fingerprint
suffix appended -- e.g. the editable-install path's GIT_COMMIT =
"unknown" stays "unknown" verbatim (Requirement 2.1, 5.1)."""
monkeypatch.setattr(cli_module._build_info, "GIT_COMMIT", "unknown")
monkeypatch.setattr(cli_module._build_info, "DIRTY_FINGERPRINT", "")
version_str = cli_module._compose_version()
assert "(unknown," in version_str
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# config build # config build
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------