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
20 changes: 17 additions & 3 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ jobs:
- run: npm ci
- run: npm test

# All publish jobs depend directly on [build, test] (not on each other) so
# they all enter "waiting for approval" together and can be approved in a
# single "Review deployments" click.

publish:
runs-on: ubuntu-latest
if: github.event_name == 'release'
Expand Down Expand Up @@ -88,7 +92,7 @@ jobs:
runs-on: ubuntu-latest
if: github.event_name == 'release'
environment: Release
needs: [publish]
needs: [build, test]

permissions:
contents: read
Expand Down Expand Up @@ -134,16 +138,26 @@ jobs:
- name: Build example
run: npm run build --workspace examples/${{ matrix.example }}

- name: Determine npm tag
id: npm-tag
run: |
VERSION=$(node -p "require('./package.json').version")
if [[ "$VERSION" == *"-"* ]]; then
echo "tag=--tag beta" >> $GITHUB_OUTPUT
else
echo "tag=" >> $GITHUB_OUTPUT
fi

- name: Publish example
run: npm publish --workspace examples/${{ matrix.example }} --provenance --access public
run: npm publish --workspace examples/${{ matrix.example }} --provenance --access public ${{ steps.npm-tag.outputs.tag }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_SECRET }}

publish-mcpb:
runs-on: ubuntu-latest
if: github.event_name == 'release'
environment: Release
needs: [publish-examples]
needs: [build, test]

permissions:
contents: write
Expand Down
33 changes: 5 additions & 28 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -539,40 +539,17 @@ Before publishing releases, ensure the following are configured:

### Publishing a Release

Releases are published automatically via GitHub Actions when a GitHub Release is created.

#### Steps to publish:

1. **Update the version** in `package.json`:
1. **Bump the version** across the root and all workspace packages:

```bash
# For a regular release
npm version patch # or minor, or major

# For a beta release
npm version prerelease --preid=beta
npm run bump -- minor # or: patch | major | prerelease --preid=beta | 1.7.0
```

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

```bash
git add package.json
git commit -m "Bump version to X.Y.Z"
git push origin main
```
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.

3. **Create a GitHub Release**:
- Go to [Releases](https://github.com/modelcontextprotocol/ext-apps/releases)
- Click "Draft a new release"
- Create a new tag matching the version (e.g., `v0.1.0`)
- Set the target branch (usually `main`)
- Write release notes describing the changes
- Click "Publish release"

4. **Monitor the workflow**:
- The [npm-publish workflow](https://github.com/modelcontextprotocol/ext-apps/actions/workflows/npm-publish.yml) will trigger automatically
- It runs build and test jobs before publishing
- On success, the package is published to npm with provenance
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.

#### npm Tags

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"prettier": "prettier -u \"**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --check",
"prettier:fix": "prettier -u \"**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --write",
"check:versions": "node scripts/check-versions.mjs",
"bump": "node scripts/bump-version.mjs",
"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/"
},
"author": "Olivier Chafik",
Expand Down
47 changes: 47 additions & 0 deletions scripts/bump-version.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env node
/**
* Bump the version in the root package.json and sync all workspace packages
* to the same version.
*
* Usage:
* node scripts/bump-version.mjs patch
* node scripts/bump-version.mjs minor
* node scripts/bump-version.mjs major
* node scripts/bump-version.mjs 1.4.0
* node scripts/bump-version.mjs prerelease --preid=beta
*
* Writes the new version to stdout (logs go to stderr).
*/

import { execSync } from "node:child_process";
import { readFileSync } from "node:fs";

const args = process.argv.slice(2);
if (!args[0]) {
console.error(
"Usage: node scripts/bump-version.mjs <patch|minor|major|prerelease|X.Y.Z> [--preid=<id>]",
);
process.exit(1);
}

const exec = (cmd) =>
execSync(cmd, { stdio: ["inherit", "pipe", "inherit"] })
.toString()
.trim();

const pkgName = JSON.parse(readFileSync("package.json", "utf-8")).name;

const newVersion = exec(
`npm version ${args.join(" ")} --no-git-tag-version`,
).replace(/^v/, "");
exec(`npm pkg set version=${newVersion} --workspaces`);

// Keep workspace dependency ranges compatible (needed on major bumps)
const [major, minor] = newVersion.split(".");
exec(`npm pkg set "dependencies.${pkgName}=^${major}.${minor}.0" --workspaces`);

// Sync package-lock.json so `npm ci` doesn't reject the release PR
exec("npm install --package-lock-only --ignore-scripts");

console.error(`Bumped root + workspaces to ${newVersion}`);
console.log(newVersion);
Loading