Skip to content

Changeset Format

Changesets are Markdown files stored in .contractual/changesets/. Each changeset declares which contracts are changing and at what semver level, and provides human-readable context about the change.


A changeset file has two parts: a YAML frontmatter block and a Markdown body.

.contractual/changesets/fuzzy-lion-dances.md

--- “orders-api”: major “order-schema”: minor ---

## orders-api

Removed the GET /orders/{id}/details endpoint. Consumers using this endpoint must migrate to GET /orders/{id}?include=details before upgrading.

## order-schema

Added optional shipping_address field to the Order object. Consumers do not need to make any changes. The field is not required and existing responses remain valid.


The frontmatter is a YAML block delimited by ---. Each line declares one contract and its bump level.

---
"contract-name": major | minor | patch
---
  • The key is the contract name as defined in contractual.yaml, enclosed in double quotes.
  • The value is one of major, minor, or patch.
  • Multiple contracts can appear in the same changeset.
  • Order does not matter.

Single contract, single bump:

single-bump.md

--- “orders-api”: major ---

Multiple contracts with different bump levels:

multiple-bumps.md

--- “orders-api”: major “order-schema”: minor “payment-schema”: patch ---


The body is free-form Markdown. It is appended directly to CHANGELOG.md under the version heading when contractual version runs.

Recommended structure: One ## heading per contract, followed by a description of what changed and any migration steps.

changeset-body.md
## orders-api

Removed the legacy_id field from the Order response object. This field was deprecated in v2.1.0. Consumers relying on order.legacy_id should use order.id instead.

## order-schema

Added billing_address as an optional field. No migration required.

The body can be empty if there is nothing to add beyond the structural diff output. Contractual will still generate a minimal changelog entry from the detected changes.


Changeset files use an adjective-noun-verb.md naming pattern. This produces human-readable names that are easy to distinguish in pull request file trees.

Examples:

  • gentle-tigers-fly.md
  • angry-lions-jump.md
  • lucky-foxes-swim.md

Contractual generates names using a dictionary of common adjectives, animals, and verbs. The combination is random and has no semantic meaning. The content of the file is what matters.


When the GitHub Action runs in pr-check mode and detects spec changes, it generates a changeset automatically:

  1. Contractual runs contractual breaking to produce the structural diff.
  2. Each detected change is classified according to the Classifications rules.
  3. The highest classification across all changes for each contract becomes the frontmatter bump level.
  4. A changeset body is generated describing each detected change.
  5. The file is committed to the PR branch with an auto-generated name.

The auto-generated file is a starting point. Review and edit the classification or body before the PR merges if the auto-detection is wrong.


If auto-detection classifies a change incorrectly, edit the frontmatter directly:

Before (auto-generated):

brave-wolf-leaps.md

--- “orders-api”: major ---

Removed field internal_trace_id from Order response.

After (corrected):

brave-wolf-leaps.md

--- “orders-api”: patch # was: major; field removed but unused ---

Removed the internal internal_trace_id field from the Order response. This field was never documented, never included in the published schema, and no external consumers reference it. No migration required.

Contractual uses the value in the file at contractual version time. It does not re-run detection or override edits.


Use the contractual changeset command to create a changeset interactively:

Terminal window
contractual changeset

Or skip the prompt and specify everything inline:

Terminal window
contractual changeset --contract orders-api --bump major --no-interactive

To create one by hand, create a .md file in .contractual/changesets/ with the correct frontmatter:

Terminal window
touch .contractual/changesets/my-change.md

Then open it in an editor and write the frontmatter and body.


.contractual/
changesets/
gentle-tigers-fly.md # created on PR #42
lucky-foxes-swim.md # created on PR #43
snapshots/
orders-api/
1.2.0.yaml
1.3.0.yaml
versions.json

All files in .contractual/changesets/ are consumed and deleted when contractual version runs. The directory is empty between releases.


  • Usage: CLI commands for creating and consuming changesets
  • Overview: The changeset model explained