Skip to content

refactor: rewrite zc in Rust - #15

Merged
upbqdn merged 1 commit into
mainfrom
rust-rewrite
Aug 4, 2026
Merged

refactor: rewrite zc in Rust#15
upbqdn merged 1 commit into
mainfrom
rust-rewrite

Conversation

@upbqdn

@upbqdn upbqdn commented Aug 4, 2026

Copy link
Copy Markdown
Member

Rewrites zc in Rust. Behaviour, output text, exit codes and cache file names are unchanged.

Why

The tool had outgrown shell: 3129 lines of bash, 24 jq filters and two large awk
programs doing semver classification, API-path grouping, changelog rendering, and a nested
--json schema that only a header comment enforced.

What changed

Git, Cargo, rustdoc and cargo-public-api stay subprocesses, so ref resolution, feature
resolution and worktree semantics are untouched. Rust replaces the layer above them:

  • The --json document is serde-derived from the same values the human report uses, so the
    two cannot drift.
  • Cargo metadata and rustdoc JSON are parsed with serde_json, keeping the previous
    contract that an unstable-format change yields zero rows rather than an error. The
    nightly/format compatibility strategy is unchanged: ZC_TOOLCHAIN plus the rustdoc-JSON
    cache fingerprint.
  • The grouping and changelog awk programs are now pure functions, unit-tested in
    isolation for the first time.
  • jq and bash 4+ are no longer runtime requirements; cargo-public-api and a nightly
    toolchain still are. The composite action builds the binary with cargo install --path.

tests/run.sh is kept as the behavioural contract and now runs against the built binary
(ZC still overrides). Its 17 sourced classify_bump cases moved into
src/version_req/tests.rs, along with the wildcard and operator-swap cases.

Verification

Ran locally before pushing, on the committed tree:

  • Output diffed against the previous shell implementation: byte-identical stdout and
    stderr, same exit codes, in all seven modes (default, --with-values, --with-lock,
    --by-type, --flat, --json, --changelog) on a fixture covering added/removed
    items, a new enum variant, trait impls, a new module, a pub const value change, a
    doc-comment change, an MSRV bump and a major runtime dependency bump. Also identical on a
    real crate's build-failure path.
  • tests/run.sh with a freshly built release binary: 118 passed, 0 failed.
  • cargo fmt --all -- --check; cargo clippy --all-targets --all-features -- -D warnings;
    cargo check --locked --all-features --all-targets; cargo test --locked --all-features
    (30 tests); cargo doc --no-deps --all-features --document-private-items;
    cargo +1.82 check --locked --all-features --all-targets (declared MSRV);
    cargo hack check --workspace --feature-powerset; cargo udeps clean.
  • cargo deny check was not run to completion: the installed version rejects the advisory
    database's CVSS 4.0 entries, which is unrelated to this change.

The tool had outgrown shell: 3129 lines of bash, 24 jq filters and two large
awk programs doing semver classification, API-path grouping, changelog
rendering and a nested JSON schema that nothing enforced.

Git, Cargo, rustdoc and cargo-public-api stay subprocesses, so ref, feature
and worktree semantics are unchanged. Rust replaces the parsing,
classification and rendering layer above them:

- The --json document is now serde-derived, so it cannot drift from the
  human report.
- Cargo metadata and rustdoc JSON are parsed with serde_json, keeping the
  previous contract that an unstable-format change yields zero rows rather
  than an error.
- The grouping and changelog awk programs became pure functions, unit-tested
  in isolation for the first time.

Behaviour, output text, exit codes and cache file names are unchanged.
Output was diffed against the previous implementation across every mode.
@upbqdn
upbqdn merged commit 1f31ba5 into main Aug 4, 2026
3 checks passed
@upbqdn
upbqdn deleted the rust-rewrite branch August 4, 2026 21:13
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