A version bump touches seven places and is graded by eight tests across five crates, with no command that does it #284
Labels
No labels
code-review
correctness
dos
performance
security
severity/high
severity/low
severity/medium
tech-debt
Kind/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
h-dv/code-index#284
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What v0.30.0 actually cost
The bump itself is one number. Finding every place that number lives took three CI cycles, and six of the seven sites were found by a gate going red rather than by looking.
Cargo.tomlinstall.ps1(×2)README.md(×6, incl. "Current release")Cargo.lockcargo checkdistribution/registry.v1.json—version+tagcli/registry_schema_gatedistribution/registry.v1.json— 8 plugin asset URLscli/registry_schema_gatecrates/guest/{ruby,example,svelte,timeline}/Cargo.lockindexer/release_gategrep 0.29.0finds sites 1–3. Everything after that is discovered by pushing and waiting.Site 7 is the one no local command can reach
The guest crates are outside the workspace — #276's subject. So
cargo check --workspace,cargo clippy --workspace,cargo test --workspaceandcargo test -p <anything>are all structurally blind to their lockfiles. The only instrument that sees them isrelease_gate::every_guest_lockfile_agrees_with_the_workspace_version, which failed on a pushed commit ~50 minutes after the push.To its credit the failure names the exact repair:
A gate that tells you the fix is a good gate. It is still a gate you meet by pushing.
Site 6 is the one that would have shipped a broken catalog
every_plugin_fact_is_derived_from_the_package_it_describesrefuses a catalog whose plugin URLs do not carry its own tag:That is not pedantry. Every release republishes all four
.cippackages under its own tag (releaseneedspackage-plugin,-timeline,-ruby,-svelte). A catalog left pointing atv0.29.0resolves to assets the new release did not publish, and everyplugin installfrom it 404s.The eight gates that grade a bump
Enumerated by
grep -rl CARGO_PKG_VERSION --include=*.rs crates/*/tests. Running all eight takes about a minute locally and would have caught sites 5, 6 and 7 before any push.What would close this
Something that turns seven-places-and-hope into one step. In rough order of appetite:
code-index release bump <version>— a subcommand that rewrites all seven sites and runscargo update --offline -p code-index-guestin each guest directory. It is the same shape ascode-index rules: the tool already owns the files it generates, and this is another set of files it owns.bounding_site_registry,disclosure_surface_registry)._prdoc/guides/, listing the seven sites and the eight-gate command line. Cheapest, and strictly better than the current state, which is that the knowledge exists only in this issue.Option 2 is the one that matches how this project handles "a set nobody is counting" everywhere else.
Related
platforms.state: unmeasuredand only the release may write checksums. That constraint is correct and this issue does not propose changing it; a bump command must editversion,tagand the asset URLs and must NOT touch the platform block.Closed by #292, shipped in v0.31.0 (
2453904).This took option 2 — the gate over the sites — as the issue recommended, plus a script for option 1. Option 3 was skipped deliberately: a checklist in
_prdoc/guides/is a document nothing checks, which is the same failure mode one level up.What the tree actually said, versus the table above
Checking each of the seven sites before building anything changed the scope:
Sites 5 and 6 are already gated.
crates/cli/tests/registry_schema_gate.rsassertscatalog.code_index.tag == format!("v{}", env!("CARGO_PKG_VERSION"))(line 355) and that every plugin asset URL carries/download/{tag}/(line 678). They fire atcargo test, not at release time. Nothing new was added for them, on purpose — two gates over one claim can disagree about which one failed.The genuinely ungated sites were 3 and 7:
README.mdand the four guest lockfiles.And there was an eighth thing the table does not list.
install.ps1's two occurrences say "a specific release, including an older one" while naming the current release. Theinstall.shlines they mirror have sat atv0.28.0untouched. So site 2 was being bumped every release purely to keep its own comment false. Freezing the two.ps1examples removes the site rather than automating it — seven sites became eight files but one fewer thing to remember.The registry
crates/indexer/tests/version_site_registry.rs, 6 tests. The site set is derived: the gate lists tracked files, finds those containing the current version, and compares that againstBUMP_SITES. A hand list checked against nothing is the drift the gate exists to prevent.Exclusions are rules, not names:
_prdoc/(records — "Release vX.Y.Z only after CI is green" is a statement about what happened) and dot-directories except.forgejo/.github/.gitlab.The claim that earns its place is
no_human_facing_file_names_a_release_that_is_not_this_one. All three per-file claims pass over a README where three of five occurrences moved; only this one fails. That mutation was run.Three things measured rather than assumed
.code-index/index.db. The gate's first run went red on the daemon's own database, which stamps the version it was written by. That is what turned the dot-directory exclusion from a guess into a rule.rusqlitewas already at the version being bumped to. Letting cargo own the lockfiles is not tidiness: a textual rewrite would have moved a third-party pin to a version that does not exist and left itschecksumdescribing the old one.Core dumps. The gate passed locally and failed on the runner, naming twelve
crates/indexer/core.<pid>files. CI's container has core dumps enabled, deliberately-killed test subprocesses leave them, and a core dump contains the version string because it snapshots a process whose binary embedsCARGO_PKG_VERSION. Not a regression — that job passed 4002 of 4003 tests with no signal in its log. But the gate was wrong: a version site is something under version control. It now scansgit ls-files, with an anti-vacuity floor so a broken listing cannot pass over nothing.The script
.forgejo/scripts/version_bump.sh <version>derives the same set, hands lockfiles to cargo, and then asserts that nothing outside the exclusion rules still states the old version. A bump that half-lands exits non-zero there rather than at CI or in a reader's install command.It refuses a leading
v, a non-version, and the version already inCargo.toml. It also refuses when any candidate site is a.rsfile — Rust reads the version throughenv!("CARGO_PKG_VERSION"), so a bump has nothing to write in source, and a match there means something upstream is already wrong.That last guard exists because the mutation found it. Widening the argument guard let
version = "v9.9.9"reachCargo.toml; the next invocation readoldback as that value and rewrotev9.9.9wherever it appeared — which in this tree isinstaller_e2e.rsandinstaller_ps1_e2e.rs, where it is the fake release tag their fixtures are built around. The bump reported success having quietly edited two test suites.The test for that guard was also wrong at first, and worth recording: it asserted only a non-zero exit, and the mutation survived it, because the script got as far as
cargo updateand cargo rejected the manifest the script had just written. A non-zero exit borrowed from a different gate — fired after the damage — is not evidence about the gate under test. Each arm now matches the refusal's own words.Also closed
code-index rulesandcode-index queryshipped in v0.30.0, a release whose stated purpose was agent adoption, and appeared nowhere inREADME.mdfor its whole life. Both are documented now, andcrates/cli/tests/readme_cli_reference.rsreads the verb list out ofcode-index --helpand fails on any subcommand the README omits.Verification
The bump to 0.31.0 was performed by the script. It touched exactly the 10 fields this issue specifies —
version,tag, and the eight plugin asset URLs. The platform block is byte-identical and stillstate: unmeasured, so the I066 constraint this issue records is honoured: only the release writes checksums. No package digest moved, since the release packs a checked-inextractor.wasmrather than rebuilding the guest.Green on one unchanged tree (hash recorded before and after): fmt, clippy
-D warnings, rustdoc-D warnings, 373 workspace suites / 4003 tests, 73 e2e suites / 840 tests on the daemon leg, guest gates under--locked,corpus_ratchet6/6 withtests/corpus/baseline.jsonunmoved, andprecision_gate7/7 with every POPULATION line printed. Then 13/13 CI jobs on the PR head and 13/13 again on the merge commit.