Skip to content

ci: derive the release version from the changelog - #17

Merged
paustint merged 1 commit into
mainfrom
ci/changelog-derived-release
Sep 26, 2026
Merged

paustint merged 1 commit into
mainfrom
ci/changelog-derived-release

Conversation

@paustint

Copy link
Copy Markdown
Contributor

Brings the release process in line with sf-formula-parser and soql-parser-js. The shared scripts and workflows are copied verbatim; only the sync-note header differs.

How releasing works now

npm run release              # derive the version from CHANGELOG.md
npm run release -- --dry-run # show the plan, dispatch nothing
npm run release -- minor     # force a bump level (major | minor | patch)
npm run release -- 3.0.0     # force an explicit version

The bump comes from the ### headings in ## [Unreleased]:

[Unreleased] contains Bump
### Breaking Changes major
### Added or ### Deprecated minor
### Changed, ### Removed, ### Fixed, ### Security patch

npm run release checks that you're on main, have a clean tree, and match origin/main. It then dispatches the Release workflow and tails the run. The publish still happens on CI, so npm provenance is kept. From the GitHub UI, the workflow input is now free text and defaults to auto.

Changes

  • scripts/derive-increment.mjs (new): derives the bump, with a test suite in scripts/__tests__/.
  • scripts/release.mjs (new): the terminal entry point. release-it moves to release:ci, and release:increment explains the derived bump.
  • .github/workflows/release.yml:
    • Resolves auto from the changelog.
    • Authenticates with client-id (replacing the deprecated app-id).
    • Derives the bot's commit identity from the token.
    • Pins actions to SHAs and drops the unused pages: write permission.
  • .github/workflows/changelog.yml (new): a PR that touches src/ must update [Unreleased], and the section must classify to a bump. The skip-changelog label opts out.
  • .github/workflows/ci.yml: SHA pins, contents: read, a timeout, and build before test.
  • .release-it.json: release commits pass --no-verify.
  • AGENTS.md (new): documents the process.

Before merging

  • Confirm the org CLIENT_ID secret is available to this repo. The workflow no longer uses APP_ID.
  • Create a skip-changelog label if you want the opt-out available.

[Unreleased] is still empty because this PR is tooling only, so npm run release will refuse until a real change is recorded.

Brings the release process in line with sf-formula-parser and
soql-parser-js, sharing their scripts and workflows verbatim.

derive-increment.mjs derives the bump from the [Unreleased] section
headings of CHANGELOG.md: Breaking Changes is a major, Added and
Deprecated a minor, and Changed, Removed, Fixed and Security a patch. An
unrecognized heading is an error rather than a guess.

npm run release starts a release from the terminal, dispatching the
workflow and tailing the run; release-it moves behind release:ci. The
workflow's version input accepts auto and derives the same way, so the
GitHub UI path no longer needs a bump picked by hand.

The release workflow authenticates with client-id instead of the
deprecated app-id and derives the commit identity from the token, so
release commits carry the bot's avatar. Actions are pinned to commit
SHAs in both workflows, and the unused pages permission is dropped.

A Changelog workflow requires an [Unreleased] entry on pull requests that
touch src/, and checks that the section classifies to a bump. The
skip-changelog label opts out.

CI now builds before testing and runs with read-only contents
permission.

Requires the CLIENT_ID secret to be available to this repository.
Copilot AI lite review requested due to automatic review settings September 26, 2026 18:38
@paustint
paustint merged commit 9779a7d into main Sep 26, 2026
9 checks passed
@paustint
paustint deleted the ci/changelog-derived-release branch September 26, 2026 18:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Critical changelog parsing defects and moderate workflow/release validation issues remain unresolved.

Review effort: Lite
Findings: 2 High severity · 1 Medium severity

Open (3)
What changed in this PR

This PR adds changelog-driven release automation, CI hardening, changelog enforcement, and release documentation.

Changes:

  • Adds changelog parsing and release orchestration scripts with tests.
  • Updates CI and release workflows with pinned actions and automated version resolution.
  • Documents release conventions and configures release commits.
File Summary Findings
vitest.config.ts Includes script tests. None
scripts/​release.mjs Adds terminal release orchestration. 2 moderate findings
scripts/​derive-increment.mjs Derives semantic version increments. 2 critical findings; 1 nit
scripts/​__tests__/​derive-increment.test.mjs Tests changelog parsing. None
package.json Adds release commands. None
AGENTS.md Documents release conventions. None
.release-it.json Configures release commit behavior. None
.github/​workflows/​release.yml Automates version resolution and publishing. None
.github/​workflows/​ci.yml Hardens CI and adds build validation. None
.github/​workflows/​changelog.yml Enforces changelog updates. 2 moderate findings

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

throw new Error('CHANGELOG.md has no `## [Unreleased]` section.');
}
const rest = changelog.slice(start);
const end = rest.indexOf('\n## ', 1);
Comment on lines +113 to +114
const heading = line.match(/^###\s+(.*\S)\s*$/);
if (heading) {
fi

# -x so docs/CHANGELOG.md does not satisfy the root one.
if ! printf '%s\n' "$changed" | grep -qx 'CHANGELOG.md'; then
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants