fix: only treat call-signature and type changes as breaking in release metadata#32
Merged
Merged
Conversation
Two improvements to the changelog produced by sdk-release-metadata.mjs, both aimed at the local "--spec-commit --sdk-repo --format changelog" flow: 1. Auto-derive the SDK compat report from the checkout when --compat-report is omitted. It snapshots the current tree (candidate) and the tree at the base ref (baseline, via a throwaway git worktree) and diffs them — no SDK regeneration. This is what surfaces SDK-surface changes like method renames, which the spec diff alone cannot see. Fails open (spec-diff-only changelog) and is skipped when --compat-report is passed, so CI is unaffected. Language is inferred from the repo basename (workos-python → python) or set via --lang. 2. Name the types in operation response/request-body changes: instead of "Changed response for `X.list`", emit "Changed response of `X.list` from `UserOrganizationMembership` to `UserOrganizationMembershipList`", read from the old/new IR (the diff report only carries a boolean). Falls back to the generic wording when a type name isn't resolvable. Verified end-to-end against workos-python PR #670 (rename + enriched response lines) and across all per-language compat reports under --strict-scopes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e metadata sdk-release-metadata.mjs marked field, enum-value, and response/request-shape changes as breaking — it inherited the spec differ's classification and trusted every breaking-severity compat symbol, including the model properties the compat snapshot tracks. That emitted feat! (major-bump) commits for what are really backend API changes. Cap them so only a changed call signature (parameters, constructor) or a removed/renamed type (model/enum/service) or removed method stays breaking. Field renames/removals, removed response data, dropped enum values, and response/request body type renames now land under Fixes. The compat path tells a model property (field — not breaking) apart from a service method using the IR's service/type names, so SDK-surface method removals/renames stay breaking. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 'Compose PR metadata' step was re-reading the unfiltered COMPAT_BREAKING array and forcing ROLLUP_TYPE=feat / ROLLUP_BANG=! whenever any raw severity=="breaking" compat row existed. This bypassed the compatChangeIsBreaking filter applied by the metadata script, causing backend-only compat changes (field_type_changed, return_type_changed, model-property symbol_removed on non-service types) to produce unwarranted major-bump PRs. The metadata script already emits feat! entries for genuine compat breaks via factsFromCompat, and lines 297-306 promote the rollup based on those filtered entries. The raw override was redundant and harmful — remove it so the filtered result is the single source of truth for the rollup decision. Co-Authored-By: bot_apk <apk@cognition.ai>
- field-added: add to BACKEND_ONLY_DIFF_KINDS so a breaking-classified required field addition is capped to `fix` instead of riding through as `feat!`, matching the stated policy that field shape changes are never breaking. - mixed requiredness: only collapse a field-required-changed group to a single "required"/"optional" line when every fact moves the same way; mixed directions now fall through to the generic summary / per-fact details rather than misreporting one direction. - historical compat: prepareSpecInputs now exposes the --spec-commit spec snapshot as _specPath, and prepareCompatInputs prefers it, so a historical changelog repair extracts compat against that commit's spec instead of the current checkout. CI (which passes --compat-report) is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The fallback at the end of the classify step only runs when the metadata script produced zero entries and there are no behavior changes. If oagen diff still reports breaking changes in that state, it means factsFromDiff doesn't recognize the diff kind. Keep the conservative feat! default (over-bumping is safer than shipping an unclassified break as a patch), but emit a CI warning so the unhandled kind is investigated instead of silently producing a vague major-bump PR. 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.
Summary
scripts/sdk-release-metadata.mjsover-classified changes as breaking, producingfeat!(major-bump) commits for what are really backend API changes. It inherited the spec differ'sclassificationfor field / enum-value / response / request changes, and trusted every breaking-severity compat symbol — including the model properties the compat snapshot tracks (~2000 of them).This tightens the rule so a change is breaking (
feat!) only when:parameter_removed,parameter_renamed,parameter_requiredness_increased,parameter_type_narrowed,signature, operation param changes), orEverything else becomes a non-breaking backend API change (
fix):How
capSeverityhelper downgrades would-be-breakingfield-*,value-*,response-changed, andrequest-body-changedfacts tofix. The made-required/optional changelog wording, which previously rode onseverity === 'breaking', now carries an explicitmadeRequiredflag on the fact.compatChangeIsBreakingskips backend-only categories (field_type_changed,enum_member_value_changed,return_type_changed,default_value_changed) and, forsymbol_removed/symbol_renamed, distinguishes a model property (field → not breaking) from a service/client method or whole type (→ breaking) by checking the symbol's owner against the IR's service/type names (now exposed frombuildIndexes).By this same rule the tooling change itself is not breaking →
fix:, no!.Test plan
Verified with synthetic and real fixtures (no automated test exists for this script):
model-removed+operation-removedrender underfield-removed, made-required,value-removed,response-changedrender under Fixes.feat!; rollup isfix..oagen/ruby/compat-report.json→encryptorparameter removal andSSO/UserManagementmethod removals stay breaking.ActionAuthenticationDenied.context(property) and afield_type_changedare dropped;SSO.get_authorization_url(method) stays breaking.--format jsonoutput keeps correct prefixes;madeRequireddoes not leak into the emittedchanges[].🤖 Generated with Claude Code