Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ on:
# Running this from a branch other than main is harmless — .releaserc.yaml
# releases from main only, so semantic-release finds nothing to do.
workflow_dispatch:
inputs:
minor:
description: >-
Release a minor version. Leave unticked for a patch, which is
what everything releasable defaults to.
type: boolean
default: false

defaults:
run:
Expand Down Expand Up @@ -97,10 +104,25 @@ jobs:

- run: pnpm install --frozen-lockfile

# The checks pr.yml already ran, run again against main.
#
# This is not belt and braces. The main ruleset does not require a pull
# request to be up to date with main before it merges, so two branches
# that were each green on their own can still break main together, and
# a release is the first thing after that which anyone would notice.
#
# Spelled out rather than calling `pnpm check`, because that starts with
# `pnpm fmt`, which rewrites files instead of reporting on them. Keep
# this list and the jobs in pr.yml in step with each other.
- run: pnpm lint
- run: pnpm fta
- run: pnpm build:check
- run: pnpm examples:check
- run: pnpm test:coverage

# The same check pr.yml runs as Pack: builds the tarball, installs it
# into a throwaway project and imports every export subpath. The pull
# request already ran it, but main is what gets published, so this is
# the last gate before a broken dist/ reaches the registry.
# into a throwaway project and imports every export subpath. The last
# gate before a broken dist/ reaches the registry.
- run: pnpm verify:pack

# Decides the version, publishes to npm, tags and writes the GitHub
Expand All @@ -109,3 +131,6 @@ jobs:
- run: pnpm exec semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Read by analyzeCommitsCmd in .releaserc.yaml, which raises the
# release to a minor when this is "true".
RELEASE_MINOR: ${{ inputs.minor }}
84 changes: 59 additions & 25 deletions .releaserc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,71 @@ branches:
- main

plugins:
# Reads the conventional-commit subjects on main and works out the bump.
# The stock rules already match what this repository writes: feat gives a
# minor, fix and perf give a patch, and chore, test, docs, refactor, style,
# build and ci release nothing.
# Reads the commit subjects on main and works out the bump.
#
# Two of the stock rules are worth knowing about, since neither is angular.
# A commit the parser recognises as a revert gives a patch, which is wanted:
# undoing something already published is a change consumers need. The rest —
# Atom emoji, Ember and ESLint tags, Express components, JSHint's uppercase
# types — read commit fields the angular parser never fills in, so they can
# match nothing here.
# Anything that ships is a patch. A minor is not something a commit subject
# can ask for: it is the checkbox on the workflow, below. The reasoning is
# that "is this significant enough to be a minor" is a judgement about the
# release as a whole, made once, by a person looking at the whole batch —
# not a judgement each commit subject should be trusted to make. Reserving
# it that way is also what keeps the minor number meaning something.
#
# No custom releaseRules deliberately. A rule set here would be a second
# place defining the commit convention, and the catch-all needed to make it
# exhaustive can swallow feat and fix outright if it is ordered wrong.
- "@semantic-release/commit-analyzer"
# So the ladder is: patch automatically, minor by checkbox, major by hand
# and never from this workflow at all.
#
# The breaking rule has to come first and has to be here. Without it the
# feat rule below matches "feat!: …" too, and a breaking change would go out
# as a patch — worse than any of this, because it would be silent. With it,
# both "feat!: …" and a BREAKING CHANGE: footer reach the guard further
# down and fail the run.
#
# docs, test, chore, ci and style are absent on purpose: they change nothing
# a consumer installs, so they release nothing.
- - "@semantic-release/commit-analyzer"
- preset: conventionalcommits
releaseRules:
- breaking: true
release: major
- type: feat
release: patch
- type: fix
release: patch
- type: perf
release: patch
- type: refactor
release: patch
- type: build
release: patch

# Turns those same commits into the GitHub Release notes.
- "@semantic-release/release-notes-generator"
# Turns those same commits into the GitHub Release notes. Same preset as the
# analyzer, so the notes group commits the way the analyzer read them.
- - "@semantic-release/release-notes-generator"
- preset: conventionalcommits

# Majors are published by hand, deliberately: a breaking change to a
# simulator is a decision about what consumers have to rewrite, not
# something a commit footer should be able to trigger on its own.
# The two ends of the ladder the analyzer above deliberately cannot reach.
#
# analyzeCommitsCmd raises the release to a minor when the workflow was
# started with its checkbox ticked. semantic-release takes the highest
# result across every analyzer, so this can only ever raise a patch to a
# minor — it cannot lower anything, and it leaves a major alone. Printing
# nothing, which is what happens when the box is unticked, is read as "no
# opinion" rather than "no release".
#
# Ticking the box with nothing releasable on main would publish a minor
# with empty notes. That is a deliberate act with an obvious result, so it
# is left possible rather than guarded against.
#
# This runs after the version is worked out and before anything is
# published, so a stray "BREAKING CHANGE:" footer fails the run rather than
# silently shipping 2.0.0. The alternative — mapping breaking changes down
# to a minor — was rejected because it would put a false version number
# against a genuinely breaking change.
# verifyReleaseCmd refuses majors. A breaking change to a simulator is a
# decision about what consumers have to rewrite, so it is made by a person
# publishing by hand, not by a marker in a subject line. This runs after
# the version is worked out and before anything is published, so "feat!: …"
# or a BREAKING CHANGE: footer fails the run rather than shipping 2.0.0.
# Mapping breaking changes down to a minor was rejected: it would put a
# false version number against a genuinely breaking change.
- - "@semantic-release/exec"
- verifyReleaseCmd: >-
- analyzeCommitsCmd: >-
if [ "$RELEASE_MINOR" = "true" ]; then echo minor; fi
verifyReleaseCmd: >-
if [ "${nextRelease.type}" = "major" ]; then
echo "Refusing to publish ${nextRelease.version} automatically:
major releases are published by hand." >&2;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
"aws-jwt-verify": "^5.2.1",
"aws-sdk-client-mock": "^4.1.0",
"constructs": "^10.8.0",
"conventional-changelog-conventionalcommits": "10.2.1",
"eslint": "^10.8.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jsdoc": "^63.3.2",
Expand Down
17 changes: 17 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.