Skip to content

Commit 3e99500

Browse files
ochafikclaudegithub-actions[bot]
authored
build: add npm run bump; parallel npm-publish approval (#568)
* ci: automate release process with workflow-driven version bumps and PR flow Adds a Release workflow that bumps all package versions, generates release notes, and opens a PR. Merging the PR auto-tags and creates the GitHub Release, which triggers npm-publish. Also adds `npm run bump` for local use and a release.yml config for categorized auto-generated notes. * ci: simplify release workflow and flatten npm-publish approval chain - Drop auto-generated RELEASES.md prepending (notes are written manually in PR) - Flatten npm-publish job dependencies so all publish jobs wait for approval together instead of sequentially, reducing 3 approval clicks to 1 - Remove Release environment from publish-mcpb (only needs GH_TOKEN) - Use --generate-notes for GitHub Release creation * fix: address review findings in release automation - release.yml: use RELEASE_TOKEN PAT for gh release create so the release:published event triggers npm-publish (GITHUB_TOKEN events don't cascade to other workflows) - release.yml: checkout merge_commit_sha in tag job instead of ref:main to avoid tagging later commits - release.yml: checkout ref:main in prepare job so dispatching from a feature branch doesn't pollute the release PR - release.yml: constrain preid to type:choice[beta] to match npm-publish.yml's tag detection - release.yml: drop -f on push so re-runs fail loudly instead of clobbering manual RELEASES.md edits; drop pr-edit fallback - release.yml: ensure release label exists before gh pr create - release.yml: make tag push idempotent for re-runs after partial failure - bump-version.mjs: update workspace dependency ranges so major bumps don't leave examples pointing at the old major - bump-version.mjs: run npm install --package-lock-only so npm ci on the release PR doesn't fail on lockfile mismatch - npm-publish.yml: add npm-tag detection to publish-examples so beta example releases don't overwrite latest - .github/release.yml: use [bot] suffix in author excludes so dependabot PRs are actually filtered from release notes - CONTRIBUTING.md: document RELEASE_TOKEN setup; fix npm run -- syntax * style: auto-fix prettier formatting * build: add npm run bump; parallel npm-publish approval - scripts/bump-version.mjs (+ npm run bump): bumps root and all workspace package versions, updates examples' ^X.Y.0 dependency range on the root package (matters on major bumps), and refreshes package-lock so npm ci accepts the release PR. - npm-publish.yml: all publish jobs now depend directly on [build, test] instead of chaining, so they enter "waiting for approval" together and a single Review-deployments click approves the lot. Prerelease versions (any X.Y.Z-…) publish under --tag beta so they don't take latest. - CONTRIBUTING.md: release steps now use npm run bump. Dropped from the original change: the workflow_dispatch release.yml (required a long-lived PAT to cascade events), label-based .github/release.yml auto-notes (PRs aren't labeled today), and the release-X.Y npm-tag for non-main branches (no backport branches yet). --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent cc02e17 commit 3e99500

4 files changed

Lines changed: 70 additions & 31 deletions

File tree

.github/workflows/npm-publish.yml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ jobs:
4242
- run: npm ci
4343
- run: npm test
4444

45+
# All publish jobs depend directly on [build, test] (not on each other) so
46+
# they all enter "waiting for approval" together and can be approved in a
47+
# single "Review deployments" click.
48+
4549
publish:
4650
runs-on: ubuntu-latest
4751
if: github.event_name == 'release'
@@ -88,7 +92,7 @@ jobs:
8892
runs-on: ubuntu-latest
8993
if: github.event_name == 'release'
9094
environment: Release
91-
needs: [publish]
95+
needs: [build, test]
9296

9397
permissions:
9498
contents: read
@@ -134,16 +138,26 @@ jobs:
134138
- name: Build example
135139
run: npm run build --workspace examples/${{ matrix.example }}
136140

141+
- name: Determine npm tag
142+
id: npm-tag
143+
run: |
144+
VERSION=$(node -p "require('./package.json').version")
145+
if [[ "$VERSION" == *"-"* ]]; then
146+
echo "tag=--tag beta" >> $GITHUB_OUTPUT
147+
else
148+
echo "tag=" >> $GITHUB_OUTPUT
149+
fi
150+
137151
- name: Publish example
138-
run: npm publish --workspace examples/${{ matrix.example }} --provenance --access public
152+
run: npm publish --workspace examples/${{ matrix.example }} --provenance --access public ${{ steps.npm-tag.outputs.tag }}
139153
env:
140154
NODE_AUTH_TOKEN: ${{ secrets.NPM_SECRET }}
141155

142156
publish-mcpb:
143157
runs-on: ubuntu-latest
144158
if: github.event_name == 'release'
145159
environment: Release
146-
needs: [publish-examples]
160+
needs: [build, test]
147161

148162
permissions:
149163
contents: write

CONTRIBUTING.md

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -539,40 +539,17 @@ Before publishing releases, ensure the following are configured:
539539

540540
### Publishing a Release
541541

542-
Releases are published automatically via GitHub Actions when a GitHub Release is created.
543-
544-
#### Steps to publish:
545-
546-
1. **Update the version** in `package.json`:
542+
1. **Bump the version** across the root and all workspace packages:
547543

548544
```bash
549-
# For a regular release
550-
npm version patch # or minor, or major
551-
552-
# For a beta release
553-
npm version prerelease --preid=beta
545+
npm run bump -- minor # or: patch | major | prerelease --preid=beta | 1.7.0
554546
```
555547

556-
2. **Commit the version bump** (if not done by `npm version`):
548+
Commit and open a PR with a grouped changelog in the body (see prior `chore: bump …` PRs for the format).
557549

558-
```bash
559-
git add package.json
560-
git commit -m "Bump version to X.Y.Z"
561-
git push origin main
562-
```
550+
2. **Merge the PR**, then [draft a GitHub Release](https://github.com/modelcontextprotocol/ext-apps/releases/new) — create a `vX.Y.Z` tag on `main`, paste the changelog, publish.
563551

564-
3. **Create a GitHub Release**:
565-
- Go to [Releases](https://github.com/modelcontextprotocol/ext-apps/releases)
566-
- Click "Draft a new release"
567-
- Create a new tag matching the version (e.g., `v0.1.0`)
568-
- Set the target branch (usually `main`)
569-
- Write release notes describing the changes
570-
- Click "Publish release"
571-
572-
4. **Monitor the workflow**:
573-
- The [npm-publish workflow](https://github.com/modelcontextprotocol/ext-apps/actions/workflows/npm-publish.yml) will trigger automatically
574-
- It runs build and test jobs before publishing
575-
- On success, the package is published to npm with provenance
552+
3. **Approve the deployment** — publishing the Release triggers the [npm-publish workflow](https://github.com/modelcontextprotocol/ext-apps/actions/workflows/npm-publish.yml); all publish jobs wait together for a single "Review deployments" approval.
576553

577554
#### npm Tags
578555

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"prettier": "prettier -u \"**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --check",
7272
"prettier:fix": "prettier -u \"**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --write",
7373
"check:versions": "node scripts/check-versions.mjs",
74+
"bump": "node scripts/bump-version.mjs",
7475
"update-lock:docker": "rm -rf node_modules package-lock.json examples/*/node_modules && docker run --rm --platform linux/amd64 -v $(pwd):/work -w /work -e HOME=/tmp node:latest npm i --registry=https://registry.npmjs.org/ --ignore-scripts && rm -rf node_modules examples/*/node_modules && npm i --registry=https://registry.npmjs.org/"
7576
},
7677
"author": "Olivier Chafik",

scripts/bump-version.mjs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Bump the version in the root package.json and sync all workspace packages
4+
* to the same version.
5+
*
6+
* Usage:
7+
* node scripts/bump-version.mjs patch
8+
* node scripts/bump-version.mjs minor
9+
* node scripts/bump-version.mjs major
10+
* node scripts/bump-version.mjs 1.4.0
11+
* node scripts/bump-version.mjs prerelease --preid=beta
12+
*
13+
* Writes the new version to stdout (logs go to stderr).
14+
*/
15+
16+
import { execSync } from "node:child_process";
17+
import { readFileSync } from "node:fs";
18+
19+
const args = process.argv.slice(2);
20+
if (!args[0]) {
21+
console.error(
22+
"Usage: node scripts/bump-version.mjs <patch|minor|major|prerelease|X.Y.Z> [--preid=<id>]",
23+
);
24+
process.exit(1);
25+
}
26+
27+
const exec = (cmd) =>
28+
execSync(cmd, { stdio: ["inherit", "pipe", "inherit"] })
29+
.toString()
30+
.trim();
31+
32+
const pkgName = JSON.parse(readFileSync("package.json", "utf-8")).name;
33+
34+
const newVersion = exec(
35+
`npm version ${args.join(" ")} --no-git-tag-version`,
36+
).replace(/^v/, "");
37+
exec(`npm pkg set version=${newVersion} --workspaces`);
38+
39+
// Keep workspace dependency ranges compatible (needed on major bumps)
40+
const [major, minor] = newVersion.split(".");
41+
exec(`npm pkg set "dependencies.${pkgName}=^${major}.${minor}.0" --workspaces`);
42+
43+
// Sync package-lock.json so `npm ci` doesn't reject the release PR
44+
exec("npm install --package-lock-only --ignore-scripts");
45+
46+
console.error(`Bumped root + workspaces to ${newVersion}`);
47+
console.log(newVersion);

0 commit comments

Comments
 (0)