ci: replace release-plz with in-house xtask release tool - #981
Draft
mcrakhman wants to merge 12 commits into
Draft
ci: replace release-plz with in-house xtask release tool#981mcrakhman wants to merge 12 commits into
mcrakhman wants to merge 12 commits into
Conversation
Add the `cargo xtask` release tool (ported from toy-kv) that replaces
release-plz with a small, testable, in-house binary. Two subcommands:
- `cargo xtask prepare-release --version X` builds a single-commit release
PR (version bump + per-crate changelogs + npm mirror) and opens/updates it.
- `cargo xtask release --sha <merge>` publishes crates in topological order,
cuts per-crate `{name}-v{version}` tags + GitHub releases, and publishes the
lumina-node npm packages. Both flows are idempotent and resumable.
Wiring for lumina:
- add `xtask` to the workspace members and a `cargo xtask` alias
- add `release.toml` configuring the branch prefix (`release-`) and the
lumina-node-wasm / node-wasm/js npm component
- derive the wasm-pack build dir from the npm component's package_dir parent
(node-wasm) instead of toy-kv's hardcoded `wasm`
- pin xtask's own serde (workspace serde lacks `derive`) and set package
metadata directly (lumina's [workspace.package] only defines version+edition)
- retarget the workspace/commit fixture tests off toy-kv onto lumina
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Swap the two release-plz workflows for thin `workflow_dispatch` wrappers
around `cargo xtask`:
- `prepare-release.yml` — manual, takes a `version` input, runs
`cargo xtask prepare-release --push` to open/refresh the release PR
(uses the RELEASE_PLZ_TOKEN PAT so the pushed commit re-triggers PR CI).
- `release.yml` — manual, run after merging the release PR; runs
`cargo xtask release --sha ${{ github.sha }}` to publish crates + npm and
cut tags/releases. Idempotent, so it safely resumes a partial release.
Remove release-plz.toml and the release-plz-*.yml workflows.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The design spec is toy-kv-specific reference material and not needed to run the tool. The remaining `release-spec/...` mentions are inert doc-comment links. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Break the ~250-line `cmd_prepare::run` into named phase helpers (guard_release_branch, discover_current_version, validate_requested_version, bump_workspace_version, preflight_publishable, build_package_reports, update_npm_wrappers, create_release_commit). `run` now reads as a linear sequence of named steps, so the `// --- Step N ---` divider comments are redundant and gone. Also remove the numbered/scaffolding comments elsewhere where the code is self-explanatory (npmops `// 1.`..`// 5.`, cmd_release `// Step 0/3`, prbody `// Step 1/2/3`, lib.rs "Wave"/"M#" module grouping), keeping only the substantive explanations. Behavior preserved exactly, including the ordering constraint that `git_default_branch` (which can run `git remote set-head` and reads the current branch) is evaluated only *after* the branch-exists guard and *before* the branch switch. All 254 tests pass; the four non-orchestration files change comments only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sweep every module's comments to read like an engineer wrote them rather than generated from a spec: - drop the full-width banner/divider comments (`// ====`, `// ----`, and the `// --- label ---` section rules in test modules) - remove the dead design-spec scaffolding that referenced now-deleted docs: module IDs (M1..M14), spec filenames and `§section` citations, "Flow N step", "Spec question", "the contract", "Wave N", "(orchestrator-fixed)" - rewrite the module-level docs as short plain descriptions - tighten comments that merely restated the code, keeping the load-bearing "why" notes (idempotency, PAT/CI attribution, git_default_branch ordering, the release-plz first-render trim, fail-open on missing cargo-semver-checks, in-workspace local-source hazard, tokens-by-env-name) Comments only — every non-comment line is byte-for-byte unchanged (verified); 254 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two correctness fixes for the release flow's tag creation: - Pass `target_commitish: opts.sha` when creating the GitHub release. The local tag is never pushed, so GitHub creates the tag itself — and with no target_commitish it defaulted to the repo's default-branch HEAD rather than the commit we published from. Pinning it to the release SHA lands the tag on the right commit; GitHub ignores the field when the tag already exists, so re-runs stay idempotent. - Add `ensure_sha_is_head`: refuse to release unless `opts.sha` resolves to the checked-out HEAD. The version is read from the working tree while tags target `opts.sha`, so a mismatch would tag a commit that doesn't carry the published version. Both are resolved via `rev-parse`, so a short SHA / ref name still matches a full HEAD. Adds a real-repo test for the guard and extends the create_release_body test to assert target_commitish. 255 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Untrack the .idea/ JetBrains files that were committed by mistake and add .idea/ to .gitignore. Also scrub the dangling references to the removed release-spec/orchestrator.md in release.toml and the release workflows, repointing them at xtask/README.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The docs job runs `cargo clippy --workspace -- -D missing-docs` plus a rustdoc `-D warnings` pass, and xtask tripped both: - Add `#![allow(missing_docs)]` to the xtask crate root — it is `publish = false` internal tooling, not a documented public API. - Fix a broken intra-doc link (`[`git-cliff-core`]`) in changelog.rs that failed the rustdoc `-D warnings` step. - Exclude xtask from the wasm32 missing-docs step; it is native-only (ureq/git-cliff-core have no wasm support) and can't target wasm. - Point xtask's anyhow/serde/serde_json/base64 at the workspace versions so the internal tool never diverges from the rest of the tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Neither file changed in this branch; a newer clippy promoted these to errors
under the CI's `-D warnings`:
- types: collapse an `if let Some(_) = _ else { return None }` into `?`
(clippy::question_mark) in round_up_to_power_of_2.
- grpc test helper: drop a redundant `&` in a format arg
(clippy::useless_borrows_in_formatting).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
xtask's release-tooling deps (git-cliff-core, tera, ureq, …) are heavier and float independently of the library crates. As a workspace member they dragged the whole tree's dependency resolution — in particular the `-Z direct-minimal-versions` CI check — upward: git-cliff-core alone forces newer serde/dyn-clone/tera than the published crates pin. Split xtask into its own workspace so those deps stay out of the main tree: - Root Cargo.toml: drop xtask from members, add it to `exclude`. This also shrinks the main Cargo.lock back down (~950 fewer lines). - xtask/Cargo.toml: add `[workspace]`, give it a concrete version/edition and concrete deps (it can no longer inherit `version.workspace` etc.). It gets its own Cargo.lock. - .cargo/config.toml: run the alias via `--manifest-path xtask/Cargo.toml`. - ci.yml: xtask is no longer in the clippy/test matrices (it never was), so add a dedicated job that runs its clippy (-D warnings) and tests; revert the now-invalid `--workspace --exclude xtask` in the docs job. - Fix the discover() integration test (xtask is no longer a member) and clear clippy lints the new -D warnings job surfaces. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The minimal-versions CI check had drifted red on main: newer transitive requirements outran two declared floors. Neither is caused by this branch, but fix them here so the check passes end-to-end: - bytes 1.6 -> 1.7.1 (workspace): hyper-util 0.1.19 requires bytes >=1.7.1. - quote 1.0.35 -> 1.0.37 (grpc-macros): rstest_macros 0.26 requires quote >=1.0.37. Verified with `cargo minimal-versions check --direct --all-features` for both native and wasm32 targets. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why replace release-plz
release-plzis a solid general-purpose tool, and much of what it does well we simply keep (Verified commits via GitHub'screateCommitOnBranchAPI, cargo-semver-checks, env-var secrets, CI-native/non-interactive operation). We're replacing it not because those are weak, but because of a few structural mismatches with how we actually release: we want to choose the version ourselves, we want npm in the same pipeline as crates, and we want the release logic to be our own code we can tailor rather than configuration wrapped around a black box.The real differences
Explicit, human-chosen version — vs. release-plz inferring (and auto-bumping) it. release-plz derives the next version from conventional-commit history and will auto-bump the major when cargo-semver-checks detects a breaking API change. We deliberately don't want the tool deciding that. xtask makes the version a required
--versionflag, validated against a strict legal-successor model (version.rs): from a stableX.Y.Zyou may go to one reset bump ((X+1).0.0/X.(Y+1).0/X.Y.(Z+1)), optionally-rc.1; from-rc.Nonly to-rc.(N+1)or the promotion. A human picks the number; the tool only rejects illegal jumps.As a corollary, xtask still runs breaking-change detection (
breaking.rs, API signal from cargo-semver-checks + intent from!/BREAKING CHANGE:), but it is diagnostic only — surfaced in the PR body, never changing the version. Same signal release-plz uses; opposite policy on who acts on it.npm in the same pipeline — vs. a separate bolted-on workflow. This is the biggest concrete win. Under release-plz, npm was entirely outside the tool:
release-plz.tomland its commands only touched crates, and two extra jobs reproduced the version bump,wasm-packbuild, dist-tag derivation, and publish in ~100 lines of hand-rolled bash keyed off release-plz's job outputs. xtask makes npm a first-class step of the same flows:prepare-releasemirrors the version + refreshes the lockfile for each[[npm]]component, andreleasebuilds viawasm-packand publishes both the wasm crate and the JS wrapper at the same version under the derived dist-tag (npmops.rs,release.toml). One tool, one source of truth for the version.Our own code we can tailor — vs. configuring around a black box. release-plz is configured only through what
release-plz.tomlexposes (ours was a singlerelease_always = false); anything beyond that meant working around it in bash (the npm jobs above being the prime example). xtask puts the bespoke logic — the successor model, the npm mirror, our tag/PR conventions, the diagnostic breaking-change report — directly in the pipeline.What's in this PR
xtaskcrate — the release tool, run ascargo xtask prepare-release/cargo xtask release. Layered pure-core / thin-I/O-shell design with unit tests.workflow_dispatchworkflows:prepare-release.yml(opens/refreshes the release PR) andrelease.yml(publishes crates + npm, cuts tags + GitHub releases; idempotent/resumable).release.tomlconfig and acargo xtaskalias in.cargo/config.toml.release-plz.tomland the tworelease-plz-*.ymlworkflows..idea/files (now gitignored) and fixed stale doc references.🤖 Generated with Claude Code