Skip to content

Semver CI should compare against last released API, not main #22192

@kosiew

Description

@kosiew

Summary

The current breaking-change detector compares pull requests against the base branch (typically main), not against the latest released API surface. This creates semver failures for changes that only modify unreleased APIs and do not break any public, shipped contract.

This issue proposes changing the blocking semver baseline to released versions, with an optional non-blocking advisory comparison to main.

Current behavior

The semver check is wired to compare against the PR base branch:

  1. Workflow runs on pull requests targeting main:
  2. Changed crates are computed against apache/${BASE_REF}:
  3. Semver check is invoked with apache/${BASE_REF}:
  4. Script passes that value directly to cargo semver-checks via --baseline-rev:

The comment workflow also states the comparison is against base branch:

Problem

Comparing against main can flag API breaks that are only breaks relative to unreleased commits on main, not breaks relative to the latest release users depend on.

This lowers signal quality for a blocking check and can delay valid PRs that simply refine unreleased APIs.

Concrete example

In #22106, semver flagged removed members on HigherOrderSignature.

Those members were introduced after release 53.1.0 and later changed before release. So the PR is incompatible with current main state, but not incompatible with the last public release API.

Why this matters

  1. Blocking semver should model user-facing released compatibility, not in-progress branch churn.
  2. False-positive blocking results increase maintainer and reviewer overhead.
  3. Contributors get conflicting signals: bot says break while release contract is still intact.
  4. Trust in semver automation drops when failures are not release-relevant.

Proposed behavior

Use released baselines for blocking semver checks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions