chore: use changesets to support an automatic release process - #3445
chore: use changesets to support an automatic release process#3445zbynekstara wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a Changesets-based deferred versioning workflow to support an automated two-phase release process (prepare + publish) for the JointJS monorepo, including custom root changelog/release-notes rendering and CI enforcement that releasable PRs include a changeset.
Changes:
- Add Changesets CLI integration + CI enforcement (
changeset status) for releasable PRs. - Add custom scripts to derive release metadata and to render the root
CHANGELOG/RELEASE_NOTES.mdfrom pending changesets. - Add GitHub Actions workflows to prepare a release PR and to publish/tag/create a GitHub Release + refresh
prod.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Adds Changesets and related dependency graph tooling to the lockfile. |
| scripts/release-info.mjs | Computes release metadata (versions/title) from pending changesets for workflow use. |
| scripts/changelog-from-changesets.mjs | Generates JointJS-formatted root CHANGELOG and RELEASE_NOTES.md from pending changesets. |
| package.json | Adds Changesets CLI + release helper scripts (status/changelog/version/publish). |
| CONTRIBUTING.md | Documents changeset requirement and the new maintainer release workflow. |
| .github/workflows/test-pr.yml | Enforces “releasable change ⇒ changeset exists” in PR CI. |
| .github/workflows/release.yml | Adds “Release (prepare)” workflow to render changelog, version, and open a release PR. |
| .github/workflows/publish.yml | Adds “Release (publish)” workflow to publish packages, tag/release, and force-update prod. |
| .github/pull_request_template.md | Updates contributor checklist to reference yarn test + changesets. |
| .changeset/README.md | Adds repo-specific Changesets conventions (body format, ordering, documented packages). |
| .changeset/config.json | Adds Changesets configuration, including changedFilePatterns for bump enforcement. |
Suppressed comments (1)
.github/workflows/release.yml:143
- The dry-run summary prints
inputs.dist_tag, butdist_tagis not actually used by the workflow/pipeline. If you want to show the channel, derive it from the computed core version (prerelease suffix) to matchpublish.yml.
echo "## Dry run — release NOT pushed" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
echo "channel: ${{ inputs.dist_tag }}" >> "$GITHUB_STEP_SUMMARY"
echo "${{ steps.info.outputs.release_title }}" >> "$GITHUB_STEP_SUMMARY"
echo "released: ${{ steps.info.outputs.released }}" >> "$GITHUB_STEP_SUMMARY"
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 18 changed files in this pull request and generated 4 comments.
Suppressed comments (6)
package.json:32
release:publishrunsnpm publishbut passes Yarn-specific flags (e.g.--tolerate-republish) and the workflow expects Yarn to handleworkspace:ranges. This will fail with the npm CLI and may publish incorrect dependency ranges. Useyarn npm publishinsideworkspaces foreachinstead (so--tagpassed by publish.yml is forwarded to the right command).
"release:publish": "yarn workspaces foreach --all --no-private -t npm publish --access public --tolerate-republish"
packages/joint-shapes-general/package.json:5
- Marking this workspace as
privateprevents it from being versioned/published by Changesets (and it will be skipped by--no-privatepublishing). That contradicts.changeset/README.mdwhich explicitly calls@joint/shapes-generala publishable package that is still versioned and published. Either keep it non-private, or update the release docs/pipeline to match the new intent.
"name": "@joint/shapes-general",
"private": true,
"title": "JointJS General Shapes",
"version": "4.3.1",
packages/joint-shapes-general-tools/package.json:5
- Marking this workspace as
privateprevents it from being versioned/published by Changesets (and it will be skipped by--no-privatepublishing). That contradicts.changeset/README.mdwhich explicitly calls@joint/shapes-general-toolsa publishable package that is still versioned and published. Either keep it non-private, or update the release docs/pipeline to match the new intent.
"name": "@joint/shapes-general-tools",
"private": true,
"title": "JointJS General Shapes Tools",
"version": "4.3.1",
scripts/changelog-from-changesets.mjs:367
- Prerelease sorting is currently lexicographic (
pa.pre < pb.pre), which misorders numeric identifiers (e.g.beta.10will sort beforebeta.2). This can produce incorrectly ordered CHANGELOG blocks when usingchangeset pre(as described in CONTRIBUTING). Implement semver-consistent prerelease comparison (numeric identifiers compared numerically, and shorter prerelease sets sort lower).
// A version WITH a prerelease tag is lower than one without.
if (pa.pre && !pb.pre) return 1;
if (!pa.pre && pb.pre) return -1;
if (pa.pre && pb.pre) return pa.pre < pb.pre ? 1 : pa.pre > pb.pre ? -1 : 0;
return 0;
scripts/release-info.mjs:39
- If
@joint/coreis missing from the workspace list for any reason, this will throw a crypticCannot read properties of undefinedwhen accessing.packageJson. Since this script is intended for CI automation, it should fail with a clear error message.
const core = versionByPkg.get('@joint/core');
const coreVersion = core ?? packages.packages.find((p) => p.packageJson.name === '@joint/core').packageJson.version;
const coreChanged = versionByPkg.has('@joint/core');
.github/workflows/release.yml:122
- The PR description references a
release/nextPR/branch, but the workflow hard-codesrelease/pending. Please align the branch naming between the workflow and the documented release process to avoid operational confusion.
BRANCH="release/pending"
Description
Alternative to #3436.
Use changesets for deferred versioning and changelog creation.
Motivation and Context
This will allow us to streamline our release process by asking PR contributors to make versioning and changelog decisions at PR time (when they have the most context about their changes) instead of at release time.
A changeset is a file inside
.changesets/folder (one per PR), which records two things:Setup TODO
Before the Changesets release pipeline can run, these steps need to be completed:
NPM_TOKEN(org 2FA must permit automation tokens; there's no interactive OTP in CI).
contents: write+pull-requests: write,installed on
clientIO/joint. Add its credentials as repo secretsRELEASE_APP_IDandRELEASE_APP_PRIVATE_KEY. (Used instead ofGITHUB_TOKENso the release PR triggers CI, and topush tags + force-update
prod.)release/nextPRself-merges on green.
master, (b) pushvX.Y.Ztags, and (c) force-updateprod(git push --force origin master:prod). Add abypass/allowance for the App on any rules that would block these, and make sure a
prodbranchexists (or can be created by the first push).
releasePR label — the workflow adds areleaselabel to the PR.**/*.test.{js,ts,mjs}→**/*.test.{js,jsx,ts,tsx,mjs}, so it stays the exact inverse of.changeset/config.json'schangedFilePatterns.git commitcurrently hangs (GPG passphrase prompt innon-interactive shells). Resolve (agent/pinentry, or
commit.gpgsign=false) before committingthis branch.
changesetsbranch once the above are ready.First release should be a dry run: dispatch Release (prepare) with
dry_run: trueand review therendered
CHANGELOG/RELEASE_NOTES.mdin the job summary before doing a real run (optionally anext/betachannel end-to-end first).