ci: add cargo-public-api check for breaking API changes (#924)
* chore: bump Rust toolchain to 1.96 * ci: add cargo-public-api breaking-change check Adds a release-type-aware `cargo-public-api` diff job that fails on changed/removed public items unless the PR's commits mark a breaking (major) release. This catches source-breaking API changes that cargo-semver-checks cannot yet detect (e.g. function return-type or field-type changes).
This commit is contained in:
parent
b79e0d9df3
commit
42a1069833
2 changed files with 72 additions and 1 deletions
71
.github/workflows/ci.yml
vendored
71
.github/workflows/ci.yml
vendored
|
|
@ -112,6 +112,77 @@ jobs:
|
|||
--only-explicit-features \
|
||||
--features "$FEATURES"
|
||||
|
||||
public-api:
|
||||
name: Public API Check
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# cargo-public-api builds rustdoc JSON, which requires a nightly toolchain
|
||||
# to be installed (it does not need to be the default; the tool invokes it
|
||||
# via `cargo +nightly`).
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@nightly
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Install cargo-public-api
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: cargo-public-api
|
||||
|
||||
# Mirror the SemVer Check job's release-type detection: a breaking-change
|
||||
# commit marker (`!:` or `BREAKING CHANGE:`) means a major release (any API
|
||||
# change is allowed); otherwise a minor release (additions allowed, but
|
||||
# changed/removed public items are denied). This catches breaking changes
|
||||
# that cargo-semver-checks cannot yet detect, such as a change to a
|
||||
# function's return type or a field's type.
|
||||
# See https://github.com/obi1kenobi/cargo-semver-checks/issues/5
|
||||
- name: Determine release type and deny flags
|
||||
run: |
|
||||
if git log --format=%B \
|
||||
${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} \
|
||||
| grep -Eq '(^[A-Za-z0-9_-]+(\([^)]*\))?!:|^BREAKING[ -]CHANGE:)'; then
|
||||
SEMVER_RELEASE_TYPE=major
|
||||
else
|
||||
SEMVER_RELEASE_TYPE=minor
|
||||
fi
|
||||
case "$SEMVER_RELEASE_TYPE" in
|
||||
major) DENY="" ;;
|
||||
patch) DENY="--deny added --deny changed --deny removed" ;;
|
||||
*) DENY="--deny changed --deny removed" ;;
|
||||
esac
|
||||
echo "SEMVER_RELEASE_TYPE=$SEMVER_RELEASE_TYPE" >> "$GITHUB_ENV"
|
||||
echo "DENY=$DENY" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Check rmcp (default features)
|
||||
run: |
|
||||
cargo public-api \
|
||||
--package rmcp \
|
||||
-ss \
|
||||
diff \
|
||||
$DENY \
|
||||
--force \
|
||||
${{ github.event.pull_request.base.sha }}..${{ github.sha }}
|
||||
|
||||
- name: Check rmcp (all features except local)
|
||||
run: |
|
||||
FEATURES=$(cargo metadata --no-deps --format-version 1 \
|
||||
| jq -r '[.packages[] | select(.name == "rmcp") | .features | keys[]
|
||||
| select(startswith("__") | not)
|
||||
| select(. != "local")] | join(",")')
|
||||
cargo public-api \
|
||||
--package rmcp \
|
||||
--features "$FEATURES" \
|
||||
-ss \
|
||||
diff \
|
||||
$DENY \
|
||||
--force \
|
||||
${{ github.event.pull_request.base.sha }}..${{ github.sha }}
|
||||
|
||||
spelling:
|
||||
name: spell check with typos
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "1.92"
|
||||
channel = "1.96"
|
||||
components = ["rustc", "rust-std", "cargo", "clippy", "rustfmt", "rust-docs"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue