Repository navigation
stability support - #153
Merged
Merged
Conversation
Sebastian Thiel (Byron)
force-pushed
the
stability-support
branch
4 times, most recently
from
October 30, 2026 04:05
6eb50fa to
6e14a0d
Compare
<!-- agent --> A minor release of a stable dependency must not force major versions of its workspace dependants. Use Cargo's first nonzero version component as the compatibility boundary, including incompatible `0.0.x` patch releases. Validation: reproduced the `1.2.3` to `1.3.0` failure before the fix, then passed `cargo test --all --locked` (57 unit and integration tests). Assisted-by: GPT 6.1 Sol Co-authored-by: GPT 6.1 Sol <codex@openai.com>
Sebastian Thiel (Byron)
force-pushed
the
stability-support
branch
3 times, most recently
from
November 1, 2026 15:20
ef616a3 to
b6077ea
Compare
Sebastian Thiel (Byron)
marked this pull request as ready for review
November 1, 2026 15:26
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical defects can let incompatible APIs pass CI, hide published compatibility breaks, and produce release plans that omit required bumps or downgrade explicitly requested versions.
9 open issues
Isolate rustdoc output to prevent concurrent checks from racing · New Resolve published baselines for packages without version adjustments · New Experimental incompatibilities do not trigger the release-plan failure status · New Preserve explicitly requested release bumps after API rejection · New Promote all experimentally incompatible packages, including added siblings · New Do not build removed baseline profiles against the current manifest · New Treat removed baseline dependencies as identity changes, not resolution errors · New Canonicalize generic parameter names before comparing signatures · New Preserve type identity when adding a shorter public re-export alias · New
What changed in this PR
Adds API stability checks to release planning, with a reusable core library and a new cargo api-check command. Checked API boundaries can limit dependency-driven version bumps while preserving separate stable and experimental compatibility rules.
Changes:
- Adds local API audits, baseline comparisons, and release-plan preflight checks.
- Integrates compatibility results into version planning, dependency requirements, and stable breaking-change reports.
- Supports detached-HEAD previews and adds regression tests and documentation.
| File | Description |
|---|---|
| tests/smart_release/release.rs | Tests breaking-change reports and detached-HEAD behavior. |
| tests/smart_release/main.rs | Registers Unix release API tests. |
| tests/smart_release/api.rs | Tests checker integration and release planning. |
| tests/api_check.rs | Tests API commands, compatibility, and lockfile preservation. |
| tests/api_check_local.rs | Tests local checks and baseline selection. |
| src/version.rs | Adds experimental minor floors and Cargo compatibility rules. |
| src/traverse.rs | Integrates API checks into dependency bump propagation. |
| src/lib.rs | Registers the release checker module. |
| src/git/history.rs | Collects history from detached HEAD. |
| src/context.rs | Supports supplied metadata and detached-HEAD history. |
| src/command/release/mod.rs | Runs checks and reports stable breaking releases. |
| src/command/release/manifest.rs | Constrains experimental dependency requirements. |
| src/command/release/git.rs | Handles detached-HEAD push previews. |
| src/command/mod.rs | Exposes the API preflight command. |
| src/command/changelog.rs | Enables changelog generation from detached HEAD. |
| src/command/api_check.rs | Implements release-plan preflight checks. |
| src/cli/options.rs | Registers the API-check subcommand. |
| src/cli/main.rs | Dispatches API-check requests. |
| src/cli/main-api-check.rs | Adds the API-check binary entry point. |
| src/cli/api_check.rs | Defines API-check options and exit handling. |
| src/api.rs | Executes configured checkers and tracks compatibility. |
| README.md | Documents stability policies, commands, and protocols. |
| Cargo.toml | Registers the binary and core workspace dependency. |
| Cargo.lock | Records core dependencies and the index upgrade. |
| cargo-smart-release-core/src/lib.rs | Exposes the reusable API-check module. |
| cargo-smart-release-core/src/api_check/types.rs | Defines requests and compatibility reports. |
| cargo-smart-release-core/src/api_check/mod.rs | Implements metadata handling and baseline selection. |
| cargo-smart-release-core/src/api_check/check.rs | Implements rustdoc audits and API comparisons. |
| cargo-smart-release-core/README.md | Introduces the core library and requirements. |
| cargo-smart-release-core/CHANGELOG.md | Initializes the core crate changelog. |
| cargo-smart-release-core/Cargo.toml | Defines the reusable core crate. |
Review effort: Balanced
Sebastian Thiel (Byron)
force-pushed
the
stability-support
branch
from
November 1, 2026 16:21
9787866 to
74b13ea
Compare
…leases Review of tests was very quick, and also through the production code. I can only assume that this is fine or better than it was before, let's see. <!-- agent --> Opt-in `package.metadata.smart-release.api-check` commands can establish a stable API boundary while private plumbing dependencies keep evolving. Pass candidate workspace versions, the published baseline, and excluded unstable features over JSON stdin; require an explicit compatible/incompatible result and abort on tool failures before release mutations. Recompute the release plan when a boundary is incompatible so downstream checkers see its actual proposed version. Preserve direct breaking changes, conservative handling of unchecked crates, and consumers that enable unstable features through defaults, aliases, or forwarding. Compatible boundaries still receive dependency updates and patch releases. Document the checker contract, including the need to audit external type identity alongside API syntax. No new runtime dependencies are required. Assisted-by: GPT 6.1 Sol Co-authored-by: GPT 6.1 Sol <codex@openai.com>
<!-- Byron --> Rubber-stamp, but tested it locally. <!-- agent --> Collect history from detached HEAD so automatic version bumps and changelog previews use the checked-out commit, including during Tix travel. Skip the push preview with an explanatory warning when detached. Reject actual releases requiring a push before changing files or publishing, while allowing releases that disable pushing or tags. Add a regression covering a detached commit behind the branch tip, release and changelog dry runs, mutation-free rejection, and execution without tags. Validation: all 69 Rust tests passed with all features; the extended detached HEAD regression, Clippy with warnings denied, and formatting checks passed. Shell journey tests and live publishing/pushing were not run.
<!-- Byron --> Rubber stamp, but tested it locally. <!-- agent --> Show a separate warning report before dry runs and execution, including version transitions, publishing status, and the causes of stable breaking releases. Compare against known published versions to include pre-bumped manifests. Validated with 70 workspace tests, rustfmt, and Clippy with warnings denied.
<!-- Byron --> Refactored quite a bit, added licenses, to make the core library a bit more like a library, and less like something that is cut out from a CLI application. <!-- agent --> Gitoxide needs the same API compatibility checks in its local tooling, CI, and release planning. Put the manifest-driven checker in `cargo-smart-release-core` so `it check-api` can reuse it without building the release tool or maintaining a second implementation. Expose boundary audits, rustdoc dependency audits, and JSON release requests through `cargo_smart_release_core::api_check`. Keep its dependencies independent of `gix`, the release planner, and the CLI. Library callers use `cargo-smart-release-core` directly. Add `cargo api-check CRATE` to audit supported feature profiles and compare the working tree against a supported release tag or an explicit revision. Expose the plumbing through the `release`, `boundary`, and `audit` subcommands. Use the existing release planner for `--release-plan`, including proposed dependency identities, repeated compatibility checks, and index-refresh retries. Report candidate versions and compatibility verdicts without entering the release mutation phase. Protect existing lockfiles and fail when a baseline or API check cannot be evaluated. Fix the Docs CI failure from ambiguous links to `api_check::check` when `--document-private-items` also exposes the private module of the same name. Add function parentheses to both link targets so rustdoc resolves them unambiguously. Validated with RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps --document-private-items and cargo fmt --all -- --check. Address PR review feedback on API comparison and checker completion. > Concurrent checks share the same `<target_directory>/<host>/doc/<library>.json`, but Cargo's build lock is released before this copy. Another invocation can delete or overwrite that file between the completed build and the copy, causing a spurious failure or comparison of the wrong feature profile. Use an invocation-specific rustdoc output directory, or hold a separate lock across removal, generation, and copying. > Appending a removed baseline profile makes the next loop build it against the current manifest. If its feature was also removed, `feature_args` returns an unknown-feature error, turning the recorded incompatibility into exit 2 and aborting release planning. Keep the removal reason, but only build profiles still declared by the current manifest. > Because `exposed` includes baseline-only dependencies, removing a public function and its now-unused dependency returns a tool error (exit 2) rather than a completed incompatibility (exit 10). This aborts release planning instead of allowing a breaking release. Treat a known baseline identity disappearing as an identity change, and reserve the resolution error for dependencies unidentified in both versions. > Signature equality still depends on generic parameter names: `normalized_type` preserves both parameter declarations and `generic` references. Renaming `T` to `U` in `pub fn identity<T>(value: T) -> T` therefore produces `SignatureChanged` and forces a breaking release, although callers remain source-compatible. Canonicalize bound parameter names and their references before comparing signatures, with a regression case for harmless generic renames. > Adding a shorter public re-export such as `pub use LongName as S` replaces the stored name even though `LongName` remains available. Signature comparison then uses `S` and incorrectly reports the original export or functions returning it as removed or changed, rejecting an additive release. Track export aliases separately from type identity rather than selecting a new shortest name. Keep a process lock over shared rustdoc generation and copying; retain removed-profile and removed-dependency incompatibility reports; compare generic bindings and public aliases without treating harmless renames or additions as API breaks. Validation: cargo test -p cargo-smart-release-core -- --include-ignored (22 tests and documentation test); cargo test --test api_check -- --include-ignored (12 tests); core Clippy with warnings denied; formatter and diff checks. Feature-profile and identity regressions failed before their fixes. Five concurrent shared-target checker pairs returned the expected 0/10 statuses, and a real public dependency removal completed with exit 10. Assisted-by: GPT 6.1 Sol Co-authored-by: GPT 6.1 Sol <codex@openai.com>
…eleases This rule is needed to give users of experimental APIs the chance to receive patch updates without possibly introducing breakage. With the rule, minor versions are used for features *and* breaking changes of the `unstable` gated APIs, so explicitly upgrading their `~X.Y.Z` dependencies could break, but doesn't have to. Most code was rubber-stamped, but looked at the `core` crate a bit more carefully. <!-- agent --> Consumers of experimental APIs should be able to accept patch updates without unexpected breakage. As `gix` approaches 1.0, exact pins would otherwise prevent them from receiving compatible fixes, while broad dependency requirements could silently introduce incompatible plumbing updates. Check stable and experimental APIs separately during release planning. Stable incompatibility retains the existing breaking-release requirement; experimental incompatibility requires at least a minor release. Compatible full APIs still permit patch releases, and explicit breaking release intent remains intact. Preserve `~` dependency requirements and constrain experimental opt-ins, including aliases, feature forwarding, and workspace inheritance, to a minor series. Retain matching exact pins and handle unchanged dependencies too. BREAKING CHANGE: checker requests gain `experimental` and `experimental_breaking` flags. Update configured checkers together with the planner; older built-in checkers reject the new requests before mutations. The corresponding public request structs in `cargo-smart-release-core` also gain fields. Validation: workspace tests, rustdoc/semver fixtures, doc tests, strict Clippy, formatting, and whitespace checks passed. The existing local HTTP-listener test was excluded after the sandbox prevented it from binding a socket. Assisted-by: GPT 6.1 Sol Co-authored-by: GPT 6.1 Sol <codex@openai.com>
Validated that it works by hand. <!-- agent --> Older published crates can fail to build rustdoc when required Cargo features were not forwarded by downstream consumers. A release fixing that problem needs a way to proceed without pretending the API comparison succeeded. Add --no-api-check to cargo smart-release for a single invocation. All configured checkers still run, and completed compatibility and incompatibility verdicts remain effective. Only comparisons that cannot complete fall back; metadata errors remain fatal. Track incomplete stable and experimental comparisons separately. A failed stable comparison loses its API boundary and uses conservative version and dependency rules. An incomplete experimental comparison requires at least a minor release, retaining any completed stable verdict. Skip incomplete comparisons for the remainder of that planning pass while continuing to recheck completed comparisons when candidate versions change. Subsequent invocations attempt all checks again. Preserve the override if the crates index is refreshed. Execution errors identify the package and baseline and suggest the override when the upcoming release fixes the old build problem. Explain that manual compatibility review is required and advise inspecting the dry-run plan. Update CLI help and README to describe the conditional fallback. Validation: all 44 smart_release integration tests, strict workspace/all-feature/ all-target Clippy, formatting, and whitespace checks passed. Regression coverage includes completed compatible and incompatible checkers alongside failures, independent stable and experimental outcomes, rechecking completed comparisons after candidate changes, retrying on the next invocation, and metadata validation. Assisted-by: GPT 6.1 Sol Co-authored-by: GPT 6.1 Sol <codex@openai.com>
Sebastian Thiel (Byron)
force-pushed
the
stability-support
branch
from
November 1, 2026 16:38
74b13ea to
d4a44af
Compare
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.


Tasks