1- # Package Release Workflow
2- #
31# Automatically releases both @jsonbored/opennextjs-cli and @jsonbored/opennextjs-mcp
42# packages to npm when a version tag is pushed. Supports both NPM_TOKEN (for first release)
53# and OIDC (for subsequent releases). Both packages are released with synchronized versions.
@@ -49,38 +47,46 @@ name: Release
4947on :
5048 push :
5149 tags :
52- - ' v*.*.*' # Matches v1.2.3
50+ - v*.*.* # Matches v1.2.3
5351 workflow_dispatch :
5452 inputs :
5553 version :
56- description : ' Version to release (e.g., 0.1.0). Leave empty to use package.json version.'
54+ description : Version to release (e.g., 0.1.0). Leave empty to use package.json version.
5755 required : false
58- type : string
5956
6057jobs :
6158 release :
6259 runs-on : ubuntu-latest
6360 timeout-minutes : 20
6461
6562 permissions :
66- contents : write # Required to create GitHub releases
63+ actions : read
64+ checks : read
65+ contents : write # Required to create GitHub releases and push tags/commits
66+ deployments : none
6767 id-token : write # Required for npm publish (OIDC)
68+ issues : none
69+ packages : none
70+ pull-requests : none
71+ repository-projects : none
72+ security-events : none
73+ statuses : read
6874
6975 steps :
7076 - name : Checkout repository
71- uses : actions/checkout@v6
77+ uses : actions/checkout@b4ffde65d8f02787b2c0e554639e0e5e24e7c8c1 # v6
7278 with :
7379 fetch-depth : 0 # Full history for changelog generation
7480
7581 - name : Setup pnpm
76- uses : pnpm/action-setup@v4
82+ uses : pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4
7783
7884 - name : Setup Node.js
79- uses : actions/setup-node@v4
85+ uses : actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
8086 with :
8187 node-version : ' 22'
82- registry-url : ' https://registry.npmjs.org'
83- cache : ' pnpm'
88+ registry-url : https://registry.npmjs.org
89+ cache : pnpm
8490
8591 - name : Install dependencies
8692 run : pnpm install --frozen-lockfile
@@ -116,17 +122,17 @@ jobs:
116122 # Remove 'v' prefix if present
117123 VERSION="${VERSION#v}"
118124 TAG="v$VERSION"
119- echo "TAG=$TAG" >> $GITHUB_OUTPUT
120- echo "IS_MANUAL=true" >> $GITHUB_OUTPUT
125+ echo "TAG=$TAG" >> " $GITHUB_OUTPUT"
126+ echo "IS_MANUAL=true" >> " $GITHUB_OUTPUT"
121127 else
122128 # Extract version from tag (e.g., v1.0.0 → 1.0.0)
123129 TAG_NAME="${{ github.ref_name }}"
124130 VERSION="${TAG_NAME#v}"
125131 TAG="$TAG_NAME"
126- echo "IS_MANUAL=false" >> $GITHUB_OUTPUT
132+ echo "IS_MANUAL=false" >> " $GITHUB_OUTPUT"
127133 fi
128-
129- echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
134+
135+ echo "VERSION=$VERSION" >> " $GITHUB_OUTPUT"
130136 echo "Version: $VERSION"
131137 echo "Tag: $TAG"
132138
@@ -153,7 +159,7 @@ jobs:
153159 echo "✅ MCP version match: $PACKAGE_VERSION"
154160
155161 - name : Setup git-cliff
156- uses : kenji-miyake/setup-git-cliff@v1
162+ uses : kenji-miyake/setup-git-cliff@e4913b34dd9c321f11f2ef3c3866f800714a1d2e # v1
157163 with :
158164 version : latest
159165
@@ -163,10 +169,10 @@ jobs:
163169 run : |
164170 TAG="${{ steps.version.outputs.TAG }}"
165171 if git rev-parse "$TAG" >/dev/null 2>&1; then
166- echo "EXISTS=true" >> $GITHUB_OUTPUT
172+ echo "EXISTS=true" >> " $GITHUB_OUTPUT"
167173 echo "⚠️ Tag $TAG already exists - will use existing tag"
168174 else
169- echo "EXISTS=false" >> $GITHUB_OUTPUT
175+ echo "EXISTS=false" >> " $GITHUB_OUTPUT"
170176 echo "✅ Tag $TAG does not exist - will create it and generate changelogs first"
171177 fi
172178
@@ -176,37 +182,37 @@ jobs:
176182 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
177183 run : |
178184 set -e
179-
185+
180186 TAG="${{ steps.version.outputs.TAG }}"
181-
187+
182188 echo "📝 Generating CLI changelog..."
183189 pnpm changelog:package opennextjs-cli --tag "$TAG" || {
184190 echo "⚠️ CLI changelog generation failed" >&2
185191 exit 1
186192 }
187-
193+
188194 echo "📝 Generating MCP changelog..."
189195 pnpm changelog:package opennextjs-mcp --tag "$TAG" || {
190196 echo "⚠️ MCP changelog generation failed" >&2
191197 exit 1
192198 }
193-
199+
194200 echo "✅ Changelogs generated successfully"
195-
201+
196202 # Commit changelogs
197203 git config user.name "github-actions[bot]"
198204 git config user.email "github-actions[bot]@users.noreply.github.com"
199-
205+
200206 git add packages/opennextjs-cli/CHANGELOG.md packages/opennextjs-mcp/CHANGELOG.md
201-
207+
202208 if git diff --staged --quiet; then
203209 echo "No changelog changes to commit"
204210 else
205211 git commit -m "chore: update changelogs for $TAG release"
206212 git push origin main
207213 echo "✅ Changelogs committed and pushed"
208214 fi
209-
215+
210216 # Create and push tag (this will trigger this workflow again with tag push event)
211217 git tag -a "$TAG" -m "Release $TAG"
212218 git push origin "$TAG"
@@ -221,29 +227,29 @@ jobs:
221227 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
222228 run : |
223229 set -e
224-
230+
225231 TAG="${{ steps.version.outputs.TAG }}"
226-
232+
227233 # Generate CLI changelog (writes directly to packages/opennextjs-cli/CHANGELOG.md)
228234 echo "📝 Generating CLI changelog..."
229235 pnpm changelog:package opennextjs-cli --tag "$TAG" || \
230236 echo "⚠️ CLI changelog generation failed" >&2
231-
237+
232238 # Generate MCP changelog (writes directly to packages/opennextjs-mcp/CHANGELOG.md)
233239 echo "📝 Generating MCP changelog..."
234240 pnpm changelog:package opennextjs-mcp --tag "$TAG" || \
235241 echo "⚠️ MCP changelog generation failed" >&2
236-
242+
237243 # Extract changelog sections for GitHub Release notes
238244 # Read from package-specific CHANGELOG.md files
239245 echo "📝 Extracting changelog sections for release notes..."
240-
246+
241247 VERSION="${{ steps.version.outputs.VERSION }}"
242-
248+
243249 # Start with version header
244250 echo "## [$VERSION] - $(date +%Y-%m-%d)" > /tmp/changelog-section.md
245251 echo "" >> /tmp/changelog-section.md
246-
252+
247253 # Extract CLI section from packages/opennextjs-cli/CHANGELOG.md
248254 if [ -f "packages/opennextjs-cli/CHANGELOG.md" ]; then
249255 # Find the version section in CLI changelog
@@ -256,7 +262,7 @@ jobs:
256262 echo "" >> /tmp/changelog-section.md
257263 fi
258264 fi
259-
265+
260266 # Extract MCP section from packages/opennextjs-mcp/CHANGELOG.md
261267 if [ -f "packages/opennextjs-mcp/CHANGELOG.md" ]; then
262268 # Find the version section in MCP changelog
@@ -269,18 +275,18 @@ jobs:
269275 echo "" >> /tmp/changelog-section.md
270276 fi
271277 fi
272-
278+
273279 # If no package-specific sections, create a generic one
274280 if [ ! -s /tmp/changelog-section.md ] || [ "$(wc -l < /tmp/changelog-section.md)" -lt 5 ]; then
275281 echo "Initial release of OpenNext.js CLI and MCP server packages." >> /tmp/changelog-section.md
276282 echo "" >> /tmp/changelog-section.md
277283 fi
278-
284+
279285 # Set changelog section for GitHub release
280- echo "CHANGELOG_SECTION<<EOF" >> $GITHUB_ENV
281- cat /tmp/changelog-section.md >> $GITHUB_ENV
282- echo "EOF" >> $GITHUB_ENV
283-
286+ echo "CHANGELOG_SECTION<<EOF" >> " $GITHUB_ENV" # Trunk: Add missing newline for echo
287+ cat /tmp/changelog-section.md >> " $GITHUB_ENV"
288+ echo "EOF" >> " $GITHUB_ENV" # Trunk: Add missing newline
289+
284290 echo "✅ Changelogs generated successfully"
285291 echo " - packages/opennextjs-cli/CHANGELOG.md"
286292 echo " - packages/opennextjs-mcp/CHANGELOG.md"
@@ -348,16 +354,16 @@ jobs:
348354 echo " Then you can remove the NPM_TOKEN secret." >&2
349355
350356 - name : Create GitHub Release
351- uses : softprops/action-gh-release@v2
357+ uses : softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2
352358 with :
353359 tag_name : ${{ steps.version.outputs.TAG }}
354360 name : Release ${{ steps.version.outputs.VERSION }}
355361 body : |
356362 ## Packages Released
357-
363+
358364 - `@jsonbored/opennextjs-cli@${{ steps.version.outputs.VERSION }}`
359365 - `@jsonbored/opennextjs-mcp@${{ steps.version.outputs.VERSION }}`
360-
366+
361367 ${{ env.CHANGELOG_SECTION }}
362368 draft : false
363369 prerelease : false
0 commit comments