Skip to content

Commit 5bc14e0

Browse files
committed
refactor: Update release workflow for OIDC trusted publishing and GitHub release management
- Revised the release workflow to prioritize OIDC trusted publishing for npm, enhancing security and streamlining the publishing process. - Removed fallback to NPM_TOKEN for subsequent releases, simplifying the workflow and reducing complexity. - Added logic to update existing GitHub releases with the latest changelog, improving release management and ensuring accurate documentation. - Enhanced error handling and messaging for npm publishing failures, providing clearer guidance for configuration issues. These changes improve the overall efficiency and reliability of the release process, ensuring better version management and user experience.
1 parent 8610a7e commit 5bc14e0

File tree

3 files changed

+152
-121
lines changed

3 files changed

+152
-121
lines changed

.github/workflows/release.yml

Lines changed: 94 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Release workflow automates the following:
2-
# - Manual releases (via workflow_dispatch)
3-
# - Automatic releases on tag pushes (v*.*.* tags)
4-
# - Actions on PR merges to main branch affecting release-monitored packages or workflow files
2+
# - Manual releases (via workflow_dispatch) - Full release: version bump → changelog generation → build → publish
3+
# - Automatic releases on tag pushes (v*.*.* tags) - Publish phase only
4+
# - Automatic changelog updates on PR merges to main - Updates unreleased changelogs only (no version bump)
55
#
66
# **Phases (may be run independently):**
77
# - full-release: Complete release sequence (version bump → changelog update/generation → build → publish)
@@ -17,19 +17,16 @@
1717
# - publish-only: Only publish to npm (requires tag)
1818
#
1919
# **Triggers:**
20-
# 1. Manual workflow_dispatch - Full control via inputs
21-
# 2. Tag push v*.*.* - Automatic publish phase
22-
# 3. PR merge to main - Auto version-bump and changelog-update (if packages changed)
20+
# 1. Manual workflow_dispatch - Full release: version bump (auto from git-cliff) → changelog generation → build → publish
21+
# 2. Tag push v*.*.* - Automatic publish phase only (for existing tags)
22+
# 3. PR merge to main - Automatic changelog-update only (updates unreleased sections, no version bump)
2323
#
24-
# **First Release (NPM_TOKEN):**
25-
# - Requires NPM_TOKEN secret in GitHub repository
26-
# - Create token: npmjs.com → Account Settings → Access Tokens → Generate New Token (Automation)
27-
# - Add secret: GitHub repo → Settings → Secrets and variables → Actions → New repository secret
28-
# - Name: NPM_TOKEN
29-
#
30-
# **Subsequent Releases (OIDC - Recommended):**
31-
# - After first release, set up OIDC trusted publishing on npm
32-
# - Once OIDC is configured, NPM_TOKEN is no longer needed
24+
# **OIDC Trusted Publishing (Required):**
25+
# - Set up OIDC trusted publishing on npm for both packages
26+
# - Go to: https://www.npmjs.com/settings/JSONbored/automation
27+
# - Add trusted publisher for @jsonbored/opennextjs-cli
28+
# - Add trusted publisher for @jsonbored/opennextjs-mcp
29+
# - Both use: Repository JSONbored/opennextjs-cli, Workflow release.yml
3330
# - More secure than token-based authentication
3431
# - Automatic token rotation
3532
name: Release
@@ -82,10 +79,10 @@ jobs:
8279
BUMP_TYPE="auto"
8380
echo "🚀 Tag push trigger - Phase: $PHASE"
8481
elif [ "${{ github.event_name }}" == "pull_request" ] && [ "${{ github.event.pull_request.merged }}" == "true" ]; then
85-
PHASE="version-bump"
82+
PHASE="changelog-update"
8683
VERSION=""
8784
BUMP_TYPE="auto"
88-
echo "🚀 PR merge trigger - Phase: $PHASE (with changelog-update)"
85+
echo "🚀 PR merge trigger - Phase: $PHASE (updates unreleased changelogs only, no version bump)"
8986
else
9087
echo "❌ Unsupported trigger: ${{ github.event_name }}" >&2
9188
exit 1
@@ -98,16 +95,13 @@ jobs:
9895
RUN_CHANGELOG_GENERATE="true"
9996
RUN_BUILD="true"
10097
RUN_PUBLISH="true"
101-
elif [ "$PHASE" == "version-bump" ]; then
102-
RUN_VERSION_BUMP="true"
103-
RUN_CHANGELOG_UPDATE="false"
98+
elif [ "$PHASE" == "changelog-update" ]; then
99+
RUN_VERSION_BUMP="false"
100+
RUN_CHANGELOG_UPDATE="true"
104101
RUN_CHANGELOG_GENERATE="false"
105102
RUN_BUILD="false"
106103
RUN_PUBLISH="false"
107-
# PR merge also runs changelog-update
108-
if [ "${{ github.event_name }}" == "pull_request" ]; then
109-
RUN_CHANGELOG_UPDATE="true"
110-
fi
104+
# PR merge only updates unreleased changelogs, no version bump
111105
elif [ "$PHASE" == "changelog-update" ]; then
112106
RUN_VERSION_BUMP="false"
113107
RUN_CHANGELOG_UPDATE="true"
@@ -981,126 +975,58 @@ jobs:
981975
echo " Preview:"
982976
head -20 /tmp/changelog-section.md
983977
984-
- name: 📋 Step - Publish CLI to npm (try OIDC first)
985-
id: publish-cli-oidc
978+
- name: 📋 Step - Publish CLI to npm (OIDC)
979+
id: publish-cli
986980
working-directory: packages/opennextjs-cli
987981
run: |
988982
set -e
989983
990-
echo "⏳ Publishing @jsonbored/opennextjs-cli to npm (trying OIDC first)..."
984+
echo "⏳ Publishing @jsonbored/opennextjs-cli to npm (using OIDC trusted publishing)..."
991985
992986
# Check if version already exists first (idempotent)
993987
if npm view "@jsonbored/opennextjs-cli@${{ steps.version.outputs.VERSION }}" version >/dev/null 2>&1; then
994-
echo "⚠️ Version ${{ steps.version.outputs.VERSION }} already exists on npm, skipping OIDC publish"
995-
echo "SUCCESS=true" >> "$GITHUB_OUTPUT"
996-
# Try publishing with OIDC (if configured)
997-
elif npm publish --access public 2>&1; then
998-
echo "✅ Published @jsonbored/opennextjs-cli@${{ steps.version.outputs.VERSION }} to npm (via OIDC)"
999-
echo "SUCCESS=true" >> "$GITHUB_OUTPUT"
1000-
else
1001-
echo "⚠️ OIDC publish failed, will try NPM_TOKEN fallback"
1002-
echo "SUCCESS=false" >> "$GITHUB_OUTPUT"
1003-
exit 1
1004-
fi
1005-
continue-on-error: true
1006-
1007-
- name: 📋 Step - Publish CLI to npm (fallback to NPM_TOKEN)
1008-
if: steps.publish-cli-oidc.outputs.SUCCESS != 'true'
1009-
working-directory: packages/opennextjs-cli
1010-
env:
1011-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
1012-
run: |
1013-
set -e
1014-
1015-
echo "⏳ Publishing @jsonbored/opennextjs-cli to npm (using NPM_TOKEN)..."
1016-
1017-
if [ -z "$NODE_AUTH_TOKEN" ]; then
1018-
echo "❌ NPM_TOKEN secret not found. For first release, you need to:" >&2
1019-
echo " 1. Create npm automation token: https://www.npmjs.com/settings/JSONbored/tokens" >&2
1020-
echo " 2. Add NPM_TOKEN secret to GitHub: Settings → Secrets and variables → Actions" >&2
1021-
echo " 3. Name the secret: NPM_TOKEN" >&2
1022-
exit 1
1023-
fi
1024-
1025-
# Configure npm to use token
1026-
echo "//registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN" > ~/.npmrc
1027-
# npm publish will fail if version already exists (idempotent behavior)
1028-
if npm publish --access public 2>&1; then
1029-
echo "✅ Published @jsonbored/opennextjs-cli@${{ steps.version.outputs.VERSION }} to npm (via NPM_TOKEN)"
988+
echo "⚠️ Version ${{ steps.version.outputs.VERSION }} already exists on npm, skipping publish"
1030989
else
1031-
PUBLISH_ERROR=$?
1032-
if npm view "@jsonbored/opennextjs-cli@${{ steps.version.outputs.VERSION }}" version >/dev/null 2>&1; then
1033-
echo "⚠️ Version ${{ steps.version.outputs.VERSION }} already exists on npm, skipping publish"
990+
# Publish using OIDC (trusted publishing must be configured on npm)
991+
if npm publish --access public; then
992+
echo "✅ Published @jsonbored/opennextjs-cli@${{ steps.version.outputs.VERSION }} to npm (via OIDC)"
1034993
else
1035-
echo "❌ npm publish failed with exit code $PUBLISH_ERROR" >&2
1036-
exit $PUBLISH_ERROR
994+
echo "❌ npm publish failed" >&2
995+
echo " Make sure OIDC trusted publishing is configured:" >&2
996+
echo " 1. Go to: https://www.npmjs.com/settings/JSONbored/automation" >&2
997+
echo " 2. Add trusted publisher for @jsonbored/opennextjs-cli" >&2
998+
echo " 3. Repository: JSONbored/opennextjs-cli" >&2
999+
echo " 4. Workflow: release.yml" >&2
1000+
exit 1
10371001
fi
10381002
fi
10391003
1040-
- name: 📋 Step - Publish MCP to npm (try OIDC first)
1041-
id: publish-mcp-oidc
1004+
- name: 📋 Step - Publish MCP to npm (OIDC)
1005+
id: publish-mcp
10421006
working-directory: packages/opennextjs-mcp
10431007
run: |
10441008
set -e
10451009
1046-
echo "⏳ Publishing @jsonbored/opennextjs-mcp to npm (trying OIDC first)..."
1010+
echo "⏳ Publishing @jsonbored/opennextjs-mcp to npm (using OIDC trusted publishing)..."
10471011
10481012
# Check if version already exists first (idempotent)
10491013
if npm view "@jsonbored/opennextjs-mcp@${{ steps.version.outputs.VERSION }}" version >/dev/null 2>&1; then
1050-
echo "⚠️ Version ${{ steps.version.outputs.VERSION }} already exists on npm, skipping OIDC publish"
1051-
echo "SUCCESS=true" >> "$GITHUB_OUTPUT"
1052-
# Try publishing with OIDC (if configured)
1053-
elif npm publish --access public 2>&1; then
1054-
echo "✅ Published @jsonbored/opennextjs-mcp@${{ steps.version.outputs.VERSION }} to npm (via OIDC)"
1055-
echo "SUCCESS=true" >> "$GITHUB_OUTPUT"
1056-
else
1057-
echo "⚠️ OIDC publish failed, will try NPM_TOKEN fallback"
1058-
echo "SUCCESS=false" >> "$GITHUB_OUTPUT"
1059-
exit 1
1060-
fi
1061-
continue-on-error: true
1062-
1063-
- name: 📋 Step - Publish MCP to npm (fallback to NPM_TOKEN)
1064-
if: steps.publish-mcp-oidc.outputs.SUCCESS != 'true'
1065-
working-directory: packages/opennextjs-mcp
1066-
env:
1067-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
1068-
run: |
1069-
set -e
1070-
1071-
echo "⏳ Publishing @jsonbored/opennextjs-mcp to npm (using NPM_TOKEN)..."
1072-
1073-
if [ -z "$NODE_AUTH_TOKEN" ]; then
1074-
echo "❌ NPM_TOKEN secret not found" >&2
1075-
exit 1
1076-
fi
1077-
1078-
# Configure npm to use token (if not already configured)
1079-
if [ ! -f ~/.npmrc ]; then
1080-
echo "//registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN" > ~/.npmrc
1081-
fi
1082-
1083-
# npm publish will fail if version already exists (idempotent behavior)
1084-
if npm publish --access public 2>&1; then
1085-
echo "✅ Published @jsonbored/opennextjs-mcp@${{ steps.version.outputs.VERSION }} to npm (via NPM_TOKEN)"
1014+
echo "⚠️ Version ${{ steps.version.outputs.VERSION }} already exists on npm, skipping publish"
10861015
else
1087-
PUBLISH_ERROR=$?
1088-
if npm view "@jsonbored/opennextjs-mcp@${{ steps.version.outputs.VERSION }}" version >/dev/null 2>&1; then
1089-
echo "⚠️ Version ${{ steps.version.outputs.VERSION }} already exists on npm, skipping publish"
1016+
# Publish using OIDC (trusted publishing must be configured on npm)
1017+
if npm publish --access public; then
1018+
echo "✅ Published @jsonbored/opennextjs-mcp@${{ steps.version.outputs.VERSION }} to npm (via OIDC)"
10901019
else
1091-
echo "❌ npm publish failed with exit code $PUBLISH_ERROR" >&2
1092-
exit $PUBLISH_ERROR
1020+
echo "❌ npm publish failed" >&2
1021+
echo " Make sure OIDC trusted publishing is configured:" >&2
1022+
echo " 1. Go to: https://www.npmjs.com/settings/JSONbored/automation" >&2
1023+
echo " 2. Add trusted publisher for @jsonbored/opennextjs-mcp" >&2
1024+
echo " 3. Repository: JSONbored/opennextjs-cli" >&2
1025+
echo " 4. Workflow: release.yml" >&2
1026+
exit 1
10931027
fi
10941028
fi
10951029
1096-
echo "" >&2
1097-
echo "💡 After first release, set up OIDC trusted publishing for both packages:" >&2
1098-
echo " 1. Go to: https://www.npmjs.com/settings/JSONbored/automation" >&2
1099-
echo " 2. Add trusted publisher for @jsonbored/opennextjs-cli" >&2
1100-
echo " 3. Add trusted publisher for @jsonbored/opennextjs-mcp" >&2
1101-
echo " 4. Both use: repository JSONbored/opennextjs-cli, workflow .github/workflows/release.yml" >&2
1102-
echo " Then you can remove the NPM_TOKEN secret." >&2
1103-
11041030
- name: 📋 Step - Check if GitHub Release exists
11051031
id: check_release
11061032
run: |
@@ -1112,8 +1038,11 @@ jobs:
11121038
HTTP_CODE=$(echo "$RELEASE_RESPONSE" | tail -n1)
11131039
11141040
if [ "$HTTP_CODE" == "200" ]; then
1115-
echo "⚠️ Release $TAG already exists, will skip creation"
1041+
echo "⚠️ Release $TAG already exists, will update with new changelog"
11161042
echo "EXISTS=true" >> "$GITHUB_OUTPUT"
1043+
# Extract release ID for updating
1044+
RELEASE_ID=$(echo "$RELEASE_RESPONSE" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
1045+
echo "RELEASE_ID=$RELEASE_ID" >> "$GITHUB_OUTPUT"
11171046
else
11181047
echo "✅ Release $TAG does not exist, will create"
11191048
echo "EXISTS=false" >> "$GITHUB_OUTPUT"
@@ -1139,6 +1068,50 @@ jobs:
11391068
env:
11401069
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
11411070

1071+
- name: 📋 Step - Update existing GitHub Release (idempotent)
1072+
id: update_release
1073+
if: steps.check_release.outputs.EXISTS == 'true'
1074+
run: |
1075+
set -e
1076+
1077+
TAG="${{ steps.version.outputs.TAG }}"
1078+
VERSION="${{ steps.version.outputs.VERSION }}"
1079+
RELEASE_ID="${{ steps.check_release.outputs.RELEASE_ID }}"
1080+
1081+
echo "⏳ Updating existing GitHub Release $TAG with latest changelog..."
1082+
1083+
# Build release body with changelog (read from env var set by changelog_extract step)
1084+
{
1085+
echo "## Packages Released"
1086+
echo ""
1087+
echo "- \`@jsonbored/opennextjs-cli@$VERSION\`"
1088+
echo "- \`@jsonbored/opennextjs-mcp@$VERSION\`"
1089+
echo ""
1090+
echo "${{ env.CHANGELOG_SECTION }}"
1091+
} > /tmp/release-body.md
1092+
1093+
# Update release via GitHub API (idempotent - safe to run multiple times)
1094+
RELEASE_BODY_JSON=$(jq -Rs . /tmp/release-body.md)
1095+
UPDATE_RESPONSE=$(curl -s -w "\n%{http_code}" \
1096+
-X PATCH \
1097+
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
1098+
-H "Accept: application/vnd.github.v3+json" \
1099+
-H "Content-Type: application/json" \
1100+
-d "{\"body\": $RELEASE_BODY_JSON}" \
1101+
"https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID" || echo -e "\n000")
1102+
1103+
HTTP_CODE=$(echo "$UPDATE_RESPONSE" | tail -n1)
1104+
1105+
if [ "$HTTP_CODE" == "200" ]; then
1106+
echo "✅ GitHub Release $TAG updated with latest changelog"
1107+
else
1108+
echo "⚠️ Failed to update release (HTTP $HTTP_CODE), but this is non-critical"
1109+
echo " You can manually update the release on GitHub if needed"
1110+
fi
1111+
continue-on-error: true
1112+
env:
1113+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1114+
11421115
- name: ✅ Phase complete - Publish
11431116
run: |
11441117
echo "✅ Phase: Publish - Complete"

packages/opennextjs-cli/CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,37 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
All notable changes to this project will be documented in this file.
9+
10+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
11+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
12+
13+
## [0.1.0] - 2026-01-05
14+
15+
### Added
16+
17+
- Initialize OpenNext.js CLI project with essential configurations and utilities([c0b6a8a](https://github.com/JSONbored/opennextjs-cli/commit/c0b6a8abd827dd8835c7a05ba8afc40f5a55efc0)) by @JSONbored
18+
- Add GitHub Actions workflow for automated package release([e87cd84](https://github.com/JSONbored/opennextjs-cli/commit/e87cd840c518d15f7616d33c0eb15b919d8c8c29)) by @JSONbored
19+
- Enhance OpenNext.js CLI with @clack/prompts integration and improved user experience([4f96104](https://github.com/JSONbored/opennextjs-cli/commit/4f9610427698763757a945d8e685accd609a7015)) by @JSONbored
20+
- Add comprehensive CLI features, safety checks, monorepo support, and MCP server([647e1db](https://github.com/JSONbored/opennextjs-cli/commit/647e1dbe71d25bac587e452b94677871ab9e7fa4)) by @JSONbored
21+
- Enhance OpenNext.js CLI with new migration and template features([cfc5abe](https://github.com/JSONbored/opennextjs-cli/commit/cfc5abeffc2d44758d09ef2ce82dee5766e8283e)) by @JSONbored
22+
- Enhance OpenNext.js CLI with project root detection and testing improvements([f6c32b5](https://github.com/JSONbored/opennextjs-cli/commit/f6c32b5e7ce7034090d67552edce781268995e54)) by @JSONbored
23+
24+
### Changed
25+
26+
- Migrate ESLint configuration to eslint.config.js and remove .eslintrc.json([beeae8c](https://github.com/JSONbored/opennextjs-cli/commit/beeae8cd04f4422dc3461164c3277e40746c796a)) by @JSONbored
27+
28+
### Statistics
29+
30+
- 7 commits in this release
31+
- 7 conventional commits
32+
33+
- 1 linked issue/PR
34+
35+
[0.1.0]: https://github.com/JSONbored/opennextjs-cli/releases/tag/v0.1.0
36+
37+
<!-- generated by git-cliff -->
38+
839
## [Unreleased]
940

1041
_No unreleased changes yet._

packages/opennextjs-mcp/CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
All notable changes to this project will be documented in this file.
9+
10+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
11+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
12+
13+
## [0.1.0] - 2026-01-05
14+
15+
### Added
16+
17+
- Add comprehensive CLI features, safety checks, monorepo support, and MCP server([647e1db](https://github.com/JSONbored/opennextjs-cli/commit/647e1dbe71d25bac587e452b94677871ab9e7fa4)) by @JSONbored
18+
- Enhance OpenNext.js CLI with project root detection and testing improvements([f6c32b5](https://github.com/JSONbored/opennextjs-cli/commit/f6c32b5e7ce7034090d67552edce781268995e54)) by @JSONbored
19+
20+
### Changed
21+
22+
- Migrate ESLint configuration to eslint.config.js and remove .eslintrc.json([beeae8c](https://github.com/JSONbored/opennextjs-cli/commit/beeae8cd04f4422dc3461164c3277e40746c796a)) by @JSONbored
23+
24+
### Statistics
25+
26+
- 3 commits in this release
27+
- 3 conventional commits
28+
29+
- 1 linked issue/PR
30+
31+
[0.1.0]: https://github.com/JSONbored/opennextjs-cli/releases/tag/v0.1.0
32+
33+
<!-- generated by git-cliff -->
34+
835
## [Unreleased]
936

1037
_No unreleased changes yet._

0 commit comments

Comments
 (0)