This document explains how to release @jsonbored/opennextjs-cli and @jsonbored/opennextjs-mcp packages to npm.
The release process is managed by a single consolidated GitHub Actions workflow (.github/workflows/release.yml) that supports multiple phases and triggers. Both packages are always released with synchronized versions.
The release workflow supports the following phases, which can run independently or together:
Complete release process:
- Version bump → Changelog generation → Build → Publish to npm → GitHub Release
Only bump versions and create tag:
- Calculate new version (auto or manual)
- Update both package.json files
- Update MCP's dependency on CLI
- Commit and create tag
Only update unreleased changelogs:
- Generate changelogs for unreleased commits
- Commit changelog updates to main branch
Generate changelogs for specific tag:
- Generate changelogs for a specific version/tag
- Used when tag exists and you want to regenerate
Only build packages:
- Run lint, type-check, and tests
- Build both CLI and MCP packages
- Validates compilation
Only publish to npm (requires tag):
- Verify package.json versions match tag
- Publish both packages to npm
- Create GitHub Release
- Go to GitHub Actions → "Release" workflow
- Click "Run workflow"
- Select:
- Phase: Choose the phase to execute (default:
full-release) - Version: Optional version (e.g.,
0.1.0). Leave empty to auto-calculate from commits - Bump type: Only used if version is empty. Options:
auto,major,minor,patch
- Phase: Choose the phase to execute (default:
- Click "Run workflow"
When you push a version tag (e.g., v1.0.0), the workflow automatically:
- Runs the
publish-onlyphase - Publishes both packages to npm
- Creates a GitHub Release
git tag v1.0.0
git push origin v1.0.0When a PR is merged to main that changes files in packages/, the workflow automatically:
- Runs
version-bumpphase (auto-calculates version from commits) - Runs
changelog-updatephase (updates unreleased changelogs)
- ✅ Both packages already at v0.1.0 in package.json
- ✅ NPM_TOKEN secret configured in GitHub
- ✅ Repository ready for release
Option 1: Full Release (Recommended)
- Go to GitHub Actions → "Release" workflow
- Click "Run workflow"
- Select:
- Phase:
full-release - Version:
0.1.0(or leave empty to use package.json version) - Bump type:
auto(not used if version is provided)
- Phase:
- Click "Run workflow"
- Workflow will execute all phases:
- ✅ Generate unreleased changelogs (using
--unreleasedsince tag doesn't exist) - ✅ Build both packages
- ✅ Create tag
v0.1.0 - ✅ Publish both packages to npm (using NPM_TOKEN)
- ✅ Create GitHub Release with changelog notes
- ✅ Generate unreleased changelogs (using
Option 2: Step-by-Step (For Testing/Debugging)
-
Update Changelogs First:
- Phase:
changelog-update - This generates unreleased changelogs and commits them
- Phase:
-
Build Packages:
- Phase:
build-only - Verify packages build successfully
- Phase:
-
Create Version Tag:
- Phase:
version-bump - Version:
0.1.0 - This creates the tag
- Phase:
-
Publish:
- Phase:
publish-only - This publishes to npm and creates GitHub Release
- Phase:
For the first release, you need to configure an npm automation token:
-
Create npm token:
- Go to: https://www.npmjs.com/settings/JSONbored/tokens
- Click "Generate New Token"
- Select "Automation" type
- Copy the token
-
Add secret to GitHub:
- Go to: GitHub repo → Settings → Secrets and variables → Actions
- Click "New repository secret"
- Name:
NPM_TOKEN - Value: Your npm automation token
- Click "Add secret"
-
Merge PR to main:
- The workflow automatically:
- Calculates new version from commits (using git-cliff)
- Updates package.json files
- Updates unreleased changelogs
- Creates and pushes tag
- The workflow automatically:
-
Tag push triggers publish:
- When the tag is pushed, the workflow automatically:
- Builds both packages
- Publishes to npm (using OIDC)
- Creates GitHub Release
- When the tag is pushed, the workflow automatically:
- Go to GitHub Actions → "Release" workflow
- Click "Run workflow"
- Select:
- Phase:
full-release - Version: Leave empty to auto-calculate, or specify version
- Bump type:
auto(ormajor/minor/patchif version is empty)
- Phase:
- Click "Run workflow"
Once both packages are published successfully, set up OIDC trusted publishing:
-
Go to npm automation settings:
-
Add trusted publisher for CLI:
- Click "Add GitHub Actions" or "Configure" next to "Trusted Publishers"
- Repository:
JSONbored/opennextjs-cli - Workflow:
.github/workflows/release.yml - Save
-
Add trusted publisher for MCP:
- Repeat the same steps for
@jsonbored/opennextjs-mcp - Use the same repository and workflow
- Repeat the same steps for
-
Remove NPM_TOKEN (optional):
- After OIDC is configured and tested, you can remove the
NPM_TOKENsecret - The workflow will automatically use OIDC for authentication
- After OIDC is configured and tested, you can remove the
- ✅ More secure than token-based authentication
- ✅ Automatic token rotation
- ✅ No need to manage npm tokens manually
- ✅ Works seamlessly with GitHub Actions
Automatic (Recommended):
- Merge PR to main → Workflow auto-bumps version → Tag push → Auto-publish
Manual:
- Run workflow with
full-releasephase → Enter version or leave empty for auto-calculate
- Run workflow with
changelog-updatephase - This updates unreleased changelogs and commits them
- Run workflow with
changelog-generatephase - Specify version or leave empty to use latest tag
- Changelogs are regenerated for the specified tag
- Run workflow with
build-onlyphase - Verifies lint, type-check, tests, and builds pass
- Create and push tag manually:
git tag v1.2.3 && git push origin v1.2.3 - Workflow automatically runs
publish-onlyphase
Cause: Trying to generate changelog for a tag that doesn't exist yet.
Solution:
- For first release, use
full-releasephase (it handles this automatically) - For subsequent releases, ensure the tag exists before running
changelog-generate
Cause: NPM_TOKEN not configured in GitHub secrets.
Solution:
- Create npm automation token
- Add
NPM_TOKENsecret to GitHub repository - See "NPM_TOKEN Setup" section above
Cause: Package.json version doesn't match the tag version.
Solution:
- Ensure version-bump phase ran successfully before publish
- Or manually update package.json files to match tag version
Cause: OIDC not configured or misconfigured.
Solution:
- Check OIDC setup in npm automation settings
- Verify repository and workflow path are correct
- Workflow will automatically fall back to NPM_TOKEN if OIDC fails
Cause: No commits found or git-cliff configuration issue.
Solution:
- Check that commits exist since last tag
- Verify
cliff.tomlconfiguration - Check git-cliff setup in workflow
The consolidated workflow uses a phase-based architecture:
- determine-phases job: Determines which phases to run based on trigger and inputs
- version-bump job: Runs if version bump is needed
- changelog-update job: Runs if unreleased changelog update is needed
- changelog-generate job: Runs if changelog generation for tag is needed
- build job: Runs if build is needed
- publish job: Runs if publish is needed
Jobs run in dependency order, with each job only running if its phase is enabled.
The workflow uses comprehensive logging with emoji indicators:
- 🚀 Starting phase: Indicates a phase is starting
- 📋 Step: Indicates a step within a phase
- ⏳ Current action: Shows progress
- ✅ Success: Indicates successful completion
- ❌ Error: Indicates failure
⚠️ Warning: Indicates warning or fallback
Both packages (@jsonbored/opennextjs-cli and @jsonbored/opennextjs-mcp) are always released with the same version number. The workflow ensures:
- Both package.json files are updated to the same version
- MCP's dependency on CLI is updated to match the new version
- Both packages are published with the same version
- GitHub Release includes both packages
For issues or questions about the release process:
- Check this documentation
- Review workflow logs in GitHub Actions
- Check workflow file:
.github/workflows/release.yml - Review git-cliff configuration:
cliff.toml