Skip to content

chore(release-automation): R5 — retire bespoke version-bump tooling#153

Merged
githubrobbi merged 2 commits intomainfrom
chore/release-auto-r5
May 8, 2026
Merged

chore(release-automation): R5 — retire bespoke version-bump tooling#153
githubrobbi merged 2 commits intomainfrom
chore/release-auto-r5

Conversation

@githubrobbi
Copy link
Copy Markdown
Collaborator

Summary

Phase R5 of docs/architecture/release-automation-plan.md. Deletes the parallel auto-tag-release.yml + update_all_versions.rs + version-bump recipes track that has been driving releases since v0.4.x; release-plz (R4 active since 2026-05-08) is now the sole version-bump + tag creator. This is the point-of-no-return milestone for the release-automation initiative — the bespoke flow is no longer the fallback on the next push to main.

Net diff: 22 files changed, +393 / −1546 LOC (net −1153 LOC).

Removed (~1430 LOC)

  • .github/workflows/auto-tag-release.yml (168 LOC)
  • build/update_all_versions.rs (1073 LOC) — bespoke version-bump rust-script
  • scripts/ci/ci-pipeline.rs (53 LOC) — Phase 7 deprecation shim; REMOVE-AFTER: v0.5.73 marker satisfied at v0.5.92
  • increment_version + version_bump fns in scripts/ci-pipeline/src/version.rs
  • STEP_VERSION_INCREMENT from ALL_STEPS in scripts/ci-pipeline/src/workflow.rs
  • Version-bump step from run_enhanced_phase2 (ship.rs) and phase2_optimized (phases.rs)
  • version-bump recipe in just/build.just
  • Version-bump step from quick-deploy recipe in just/dev.just
  • !build/update_all_versions.rs carve-out in .gitignore

Added (~140 LOC, mostly comments + workflow YAML)

detect-release-bump short-circuit job in release-cache-warm.yml

Diffs [workspace.package].version between HEAD and HEAD~1 and skips the warm matrix when the push is a version bump. Saves ~165 runner-min/release because release.yml rebuilds + caches that same dep graph anyway.

Was originally scoped as a separate "tiny surgical PR" but folded into R5 since it's small and conceptually adjacent.

Bridge step in release-plz.yml's release job

gh workflow run release.yml ... after release-plz creates the workspace tag. Replaces the GITHUB_TOKEN anti-loop workaround that R4 deferred to a future GitHub App / PAT setup; uses workflow_dispatch (explicitly carved out of the anti-loop policy by GitHub) instead.

Also flips git_release_enable = false in release-plz.toml so release.yml owns the GitHub Release page (avoids the body-overwrite race that softprops/action-gh-release would otherwise hit when run against a release-plz-created Release with body_path: release-notes.md).

Doc updates

  • docs/architecture/release-automation-plan.md — flip R5 row to 🟢, append four deviation log entries:
    1. v0.5.91 immutable-release lockout (the failure that forced the v0.5.92 bootstrap)
    2. R5-before-R4-bakein pragmatic acceleration (R5 lands with 0 release-plz-driven releases observed; bake-in completes on next release)
    3. R5 cache-warm short-circuit
    4. R5 downstream-trigger bridge (resolves the prior R4 deferred row)
  • docs/architecture/dev-flow-implementation-plan.md — tick the final Phase 7 bake-in checkbox; deprecation shim retired, REMOVE-AFTER: v0.5.73 satisfied at v0.5.92.
  • CONTRIBUTING.md — rewrite the Release row in the four-layer quality-gates matrix to describe the post-R5 release-plz flow.
  • docs/publishing.md — flip R3.5 / R5 / R6 status rows to landed; R4 stays 🟡 (active, bake-in pending first release-plz-driven release).
  • docs/architecture/security/supply-chain-posture.md — replace the auto-tag-release.yml reference with the post-R5 chain.
  • Trailing comments in release-plz.toml, Cargo.toml, scripts/ci-pipeline/Cargo.toml, .gitignore, and scripts/ci-pipeline/src/{version,workflow,ship,phases}.rs rewritten to describe the post-R5 steady state and explicitly note the R5 retirement of any pre-R5 tooling they referenced.

Validation

Gate Result
cargo check --workspace --locked --all-targets ✅ green
cargo clippy -p uffs-ci-pipeline --locked --all-targets -- -D warnings ✅ green
cargo fmt --all ✅ green
actionlint on release-plz.yml + release-cache-warm.yml ✅ green
just gates-drift ✅ manifest + consumers agree (23 gates)
lint-pre-push (full Tier 1 gate, 19 jobs) ✅ green in 77s

Pre-push gate ran every CI-equivalent check locally including lint-ci-windows (cross-compiled clippy), vet, deny, nextest, rustdoc -D warnings, etc. See the push log in the commit checks for the full breakdown.

R4 bake-in

R4 stays 🟡 in the dashboard until the first release-plz-driven release lands. After R5 merges, the next feat: / fix: / perf: / security: commit to main will trigger release-plz to open a release-plz-vX.Y.Z PR; merging that PR produces v0.5.93 end-to-end through the new flow. At that point R4 flips to 🟢 in a follow-up dashboard-only commit.

Rollback

Fully reversible — git revert of this single PR restores auto-tag-release.yml + update_all_versions.rs + the version-bump recipes; the bespoke flow is back operational with one merge. No data has moved.

Refs

Phase R5 of `docs/architecture/release-automation-plan.md`.  Deletes the
parallel `auto-tag-release.yml` + `update_all_versions.rs` + `version-bump`
recipes track that has been driving releases since v0.4.x; release-plz
(R4 active since 2026-05-08) is now the sole version-bump + tag creator.
This is the point-of-no-return milestone for the release-automation
initiative; the bespoke flow can no longer be the fallback on the next
push to `main`.

Removed (~1430 LOC):

  - `.github/workflows/auto-tag-release.yml` (168 LOC).
  - `build/update_all_versions.rs` (1073 LOC).
  - `scripts/ci/ci-pipeline.rs` (53 LOC) — Phase 7 deprecation shim;
    `REMOVE-AFTER: v0.5.73` marker satisfied at v0.5.92.
  - `increment_version` + `version_bump` fns in
    `scripts/ci-pipeline/src/version.rs`.
  - `STEP_VERSION_INCREMENT` from `ALL_STEPS` in
    `scripts/ci-pipeline/src/workflow.rs`.
  - Version-bump step from `run_enhanced_phase2` (ship.rs) and
    `phase2_optimized` (phases.rs).
  - `version-bump` recipe in `just/build.just`.
  - Version-bump step from `quick-deploy` recipe in `just/dev.just`.
  - `!build/update_all_versions.rs` carve-out in `.gitignore`.

Added (~140 LOC, mostly comments + workflow YAML):

  - `detect-release-bump` short-circuit job in
    `.github/workflows/release-cache-warm.yml` — diffs
    `[workspace.package].version` between `HEAD` and `HEAD~1` and
    skips the warm matrix when the push is a version bump (saves
    ~165 runner-min/release because `release.yml` rebuilds + caches
    that same dep graph anyway).
  - Bridge step in `release-plz.yml`'s release job —
    `gh workflow run release.yml ...` after release-plz creates the
    workspace tag.  Replaces the GITHUB_TOKEN anti-loop workaround
    that R4 deferred to a future GitHub App / PAT setup; uses
    `workflow_dispatch` (explicitly carved out of the anti-loop
    policy) instead.  Flips `git_release_enable = false` in
    `release-plz.toml` so `release.yml` owns the GitHub Release page
    (avoids the body-overwrite race that softprops/action-gh-release
    would otherwise hit when run against a release-plz-created
    Release with `body_path: release-notes.md`).

Doc updates:

  - `docs/architecture/release-automation-plan.md` — flip R5 row to
    🟢, append four deviation log entries (v0.5.91 immutable-release
    lockout, R5-before-R4-bakein pragmatic acceleration, R5
    cache-warm short-circuit, R5 downstream-trigger bridge resolves
    prior R4 deferred row).
  - `docs/architecture/dev-flow-implementation-plan.md` — tick the
    final Phase 7 bake-in checkbox (deprecation shim retired,
    `REMOVE-AFTER: v0.5.73` satisfied at v0.5.92).
  - `CONTRIBUTING.md` — rewrite the Release row in the four-layer
    quality-gates matrix to describe the post-R5 release-plz flow.
  - `docs/publishing.md` — flip R3.5 / R5 / R6 status rows to landed;
    R4 stays 🟡 (active, bake-in pending first release-plz-driven
    release).
  - `docs/architecture/security/supply-chain-posture.md` — replace
    `auto-tag-release.yml` reference with the post-R5 chain.
  - Trailing comments in `release-plz.toml`, `Cargo.toml`,
    `scripts/ci-pipeline/Cargo.toml`, `.gitignore`, and
    `scripts/ci-pipeline/src/{version,workflow,ship,phases}.rs`
    rewritten to describe the post-R5 steady state and explicitly
    note the R5 retirement of any pre-R5 tooling they referenced.

Validation:

  - `cargo check --workspace --locked --all-targets` green.
  - `cargo clippy -p uffs-ci-pipeline --locked --all-targets
    -- -D warnings` green.
  - `cargo fmt --all` green.
  - `actionlint` on the two modified workflow YAML files green.
  - `just gates-drift` — manifest + consumers agree (23 gates).

R4 bake-in completes naturally on the next `feat:` / `fix:` / `perf:` /
`security:` commit to `main`, which release-plz will turn into the
first end-to-end release-plz-driven release (v0.5.93).  At that point
the R4 row in the dashboard flips to 🟢 in a follow-up commit.

Refs: #148 (R4 active-mode flip), #145 (R3.5 internal-dep version
requirements + R6 metadata), #151 (`release_always = false` gate),
#152 (v0.5.92 manual bootstrap after v0.5.91 immutable-release
lockout).
@githubrobbi githubrobbi enabled auto-merge (squash) May 8, 2026 13:30
Comment-only follow-up to R5 retirement (auto-tag-release.yml was deleted in the prior commit on this branch).  No behaviour change.
@githubrobbi githubrobbi merged commit 779c14f into main May 8, 2026
27 checks passed
@githubrobbi githubrobbi deleted the chore/release-auto-r5 branch May 8, 2026 13:55
githubrobbi added a commit that referenced this pull request May 8, 2026
…ty:` (#154)

Brings forward the Phase R1b "decide whether to keep top-level
`security:` or migrate to `chore(security):`" sub-question and resolves
it: top-level `security:` is no longer an accepted Conventional Commits
type anywhere in the toolchain.  Security work uses `fix(security):`
(patch + Security changelog row) or `chore(security):` (no bump +
Security changelog row).

Background — four regexes had drifted into two camps:

  Strict (11 standard CC types):
    - scripts/ci/check_commit_subjects.sh  (commit-msg + pre-push hook)
    - .github/workflows/commitlint.yml     (PR-title advisory check)

  Permissive (11 + top-level `security:`):
    - cliff.toml::commit_parsers
    - release-plz.toml::release_commits

The permissive carve-out tolerated PRs #31, #33, #34 — three early-
project commits that used `security:` as a top-level type before the
commit-msg hook was installed.  Since the hook landed, no future commit
can use that prefix on `main`, so the cliff.toml + release-plz.toml
allowances are dead code preemptively allowing what no longer reaches
the codebase.  The dedicated `^fix\(security\)` and `^chore\(security\)`
parsers in `cliff.toml` already route security work to the dedicated
**### Security** changelog section without the top-level type.

Changes:

  - `release-plz.toml::release_commits`:
        ^(feat|fix|perf|security)(\\(.+\\))?:
      → ^(feat|fix|perf)(\\(.+\\))?:
    Plus a comment block explaining the security-encoding convention
    and pointing to CONTRIBUTING.md.

  - `cliff.toml::commit_parsers`:
    Drop the `^security(\\([a-z0-9-]+\\))?:` line and its carve-out
    comment.  The two scope-based parsers
    (`^fix\\(security\\)` + `^chore\\(security\\)`) remain, so the
    Security changelog section is unaffected.

  - `CONTRIBUTING.md` § "Commit message conventions":
    Add a "Security commits" paragraph explicitly codifying
    `fix(security):` + `chore(security):` as the canonical encodings
    and stating that top-level `security:` is NOT an allowed type.
    Cross-reference the commit-msg hook + commitlint workflow + the
    release-plz `release_commits` filter.

  - `docs/architecture/release-automation-plan.md`:
    Append a deviation log entry "R1b CC-type convergence (early)"
    documenting the decision, the dead-code rationale, and that
    historical PRs #31/#33/#34 remain in the changelog.

No code changes.  Pure regex + comment + docs convergence.

Validation:

  - `git grep -nE "release_commits|\\^security|security:"` in
    `cliff.toml` + `release-plz.toml` shows the four regexes now
    agree (11 standard CC types only).
  - No CHANGELOG churn — the historical PR #31/#33/#34 entries are
    not regenerated by `git-cliff` because they predate the most
    recent tag.
  - `taplo fmt --check` on the two TOML files green.

Refs: #153 (R5 retirement, where the drift was first surfaced).

Plan impact: brings R1b's enforcement decision forward by ~1 phase.
Does NOT change the R1a → R1b advisory→required scheduling for the
commitlint workflow itself; only resolves the orthogonal type-list
sub-question.
githubrobbi added a commit that referenced this pull request May 8, 2026
…R6 deviation row 5 — Path A) (#155)

* fix(release-automation): converge CC regexes — drop top-level `security:`

Brings forward the Phase R1b "decide whether to keep top-level
`security:` or migrate to `chore(security):`" sub-question and resolves
it: top-level `security:` is no longer an accepted Conventional Commits
type anywhere in the toolchain.  Security work uses `fix(security):`
(patch + Security changelog row) or `chore(security):` (no bump +
Security changelog row).

Background — four regexes had drifted into two camps:

  Strict (11 standard CC types):
    - scripts/ci/check_commit_subjects.sh  (commit-msg + pre-push hook)
    - .github/workflows/commitlint.yml     (PR-title advisory check)

  Permissive (11 + top-level `security:`):
    - cliff.toml::commit_parsers
    - release-plz.toml::release_commits

The permissive carve-out tolerated PRs #31, #33, #34 — three early-
project commits that used `security:` as a top-level type before the
commit-msg hook was installed.  Since the hook landed, no future commit
can use that prefix on `main`, so the cliff.toml + release-plz.toml
allowances are dead code preemptively allowing what no longer reaches
the codebase.  The dedicated `^fix\(security\)` and `^chore\(security\)`
parsers in `cliff.toml` already route security work to the dedicated
**### Security** changelog section without the top-level type.

Changes:

  - `release-plz.toml::release_commits`:
        ^(feat|fix|perf|security)(\\(.+\\))?:
      → ^(feat|fix|perf)(\\(.+\\))?:
    Plus a comment block explaining the security-encoding convention
    and pointing to CONTRIBUTING.md.

  - `cliff.toml::commit_parsers`:
    Drop the `^security(\\([a-z0-9-]+\\))?:` line and its carve-out
    comment.  The two scope-based parsers
    (`^fix\\(security\\)` + `^chore\\(security\\)`) remain, so the
    Security changelog section is unaffected.

  - `CONTRIBUTING.md` § "Commit message conventions":
    Add a "Security commits" paragraph explicitly codifying
    `fix(security):` + `chore(security):` as the canonical encodings
    and stating that top-level `security:` is NOT an allowed type.
    Cross-reference the commit-msg hook + commitlint workflow + the
    release-plz `release_commits` filter.

  - `docs/architecture/release-automation-plan.md`:
    Append a deviation log entry "R1b CC-type convergence (early)"
    documenting the decision, the dead-code rationale, and that
    historical PRs #31/#33/#34 remain in the changelog.

No code changes.  Pure regex + comment + docs convergence.

Validation:

  - `git grep -nE "release_commits|\\^security|security:"` in
    `cliff.toml` + `release-plz.toml` shows the four regexes now
    agree (11 standard CC types only).
  - No CHANGELOG churn — the historical PR #31/#33/#34 entries are
    not regenerated by `git-cliff` because they predate the most
    recent tag.
  - `taplo fmt --check` on the two TOML files green.

Refs: #153 (R5 retirement, where the drift was first surfaced).

Plan impact: brings R1b's enforcement decision forward by ~1 phase.
Does NOT change the R1a → R1b advisory→required scheduling for the
commitlint workflow itself; only resolves the orthogonal type-list
sub-question.

* fix(release-automation): scope publishability to polars-free crates (R6→R8 deviation row 5 — Path A)

Resolves the `release-plz-pr` job hard-failing on every push to `main`
with `failed to select a version for chrono` from the polars subtree's
`cargo package` step.  See `docs/architecture/release-automation-plan.md`
deviation log row "R6 → R8 publishability resolution (Path A)" for the
full diagnostic trail.

  TL;DR root cause:
    polars git/rev pin → polars-arrow declares chrono ^0.4.42
    crates.io polars 0.53.0 → polars-arrow declares chrono <=0.4.41
    These are mutually exclusive — no chrono version satisfies both.
    `cargo package` strips the git rev (publishing simulation) and
    falls back to crates.io polars 0.53.0; the conflict surfaces on
    every release-plz invocation.

  Why not "drop the git rev" (Path B-i)?
    Probed on 2026-05-08.  Crates.io polars 0.53.0 has accumulated
    multiple nightly-rust-API regressions that the in-workspace git rev
    actively patches:
      - polars-arrow-0.53.0/src/bitmap/bitmask.rs:2 →
        `std::simd::{LaneCount, SupportedLaneCount}` shapes don't exist
        in current nightly (`nightly-2026-05-08`).
      - polars-ops-0.53.0/src/chunked_array/strings/case.rs:79 →
        `core::unicode::{Case_Ignorable, Cased}` (Cased missing,
        Case_Ignorable private).
    Dropping the git rev breaks `cargo build --workspace`.  The git rev
    is load-bearing, not opportunistic.  Path B-i abandoned.

  What this PR does (Path A):

  1. Adds `publish = false` to the 8 polars-tainted crates' Cargo.toml:
       - uffs-polars   (direct polars dep — root of the subtree)
       - uffs-mft      (direct uffs-polars dep, ~28 import sites)
       - uffs-format   (transitive via uffs-mft)
       - uffs-core     (direct + transitive, ~54 import sites)
       - uffs-daemon   (transitive via uffs-mft + uffs-core)
       - uffs-client   (transitive via uffs-format → uffs-mft)
       - uffs-mcp      (transitive via uffs-client → …)
       - uffs-cli      (transitive via uffs-client + uffs-format → …)
     Each crate's comment block explains its specific role in the
     subtree and points at the deviation log row.

  2. Updates `release-plz.toml`: replaces the 8 corresponding
     `[[package]] changelog_path = "CHANGELOG.md"` blocks with
     `release = false` so release-plz skips them entirely (no version
     bump computation, no `cargo package` step at all).  The 4 polars-
     free crates (`uffs-time`, `uffs-text`, `uffs-security`,
     `uffs-broker`) keep their `changelog_path` entries and remain
     release-eligible.

  3. Updates `crates-io-dry-run.yml` doc-comments: the workflow's jq
     filter (`select(.publish != [])`) already skips publish=false
     crates automatically, so no logic change needed; the header
     comments are refreshed to mark the polars/chrono known-expected
     failure as RESOLVED.

  4. Appends a new deviation log row to release-automation-plan.md
     §8 documenting the probe-and-pivot trail and the re-enable
     procedure (5 steps, all reversible) for when polars upstream
     publishes a release containing the nightly-API patches.

  Verification:
    - `cargo build --workspace` ✓ (1m 40s, post-changes)
    - `cargo package -p uffs-time --no-verify --allow-dirty` ✓
      (representative polars-free crate)
    - `cargo metadata` jq partition matches expectation:
        publishable (4): uffs-broker, uffs-security, uffs-text, uffs-time
        non-publishable (12): 8 newly-tagged + 4 pre-existing internal
                              tools (uffs-ci-pipeline, uffs-diag,
                              uffs-gen-hooks, uffs-gen-workflow)

  Plan impact:
    - R6 PARTIALLY RESOLVED — publishability invariant scoped to 4 of
      12 originally-publishable crates.
    - R7 (OIDC scaffolding) unaffected — the dormancy gate doesn't care
      which crates are publishable.
    - R8 dress rehearsal still feasible on its originally-chosen leaf
      target `uffs-time` (polars-free).
    - R9 (full publish) DEFERRED until polars upstream ships a
      compatible release; track via `crates-io-dry-run.yml` weekly.

  End-user impact:
    - `cargo install uffs-cli` is now blocked.  `just use` (GitHub
      Releases tarball install — the recommended path) is unaffected.
    - Daily development workflows (`cargo build`, `cargo test`,
      `just ship`, `just use`) all work unchanged.

Refs: deviation log row "R6 → R8 publishability resolution (Path A)"
      in docs/architecture/release-automation-plan.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant