Skip to content

Commit 91b7d6f

Browse files
committed
feat: Update changelogs for OpenNext.js CLI and MCP packages
- Refactored CHANGELOG.md to clarify that this monorepo contains multiple packages, each with its own changelog. - Added links to individual package changelogs for better navigation. - Removed the obsolete FEATURE_ROADMAP.md file and RELEASE.md documentation. - Updated package.json scripts for changelog generation to support individual packages. - Introduced a new GitHub Actions workflow for automated changelog updates upon PR merges. These changes enhance documentation clarity and streamline the changelog management process for the OpenNext.js project.
1 parent f6c32b5 commit 91b7d6f

File tree

14 files changed

+855
-824
lines changed

14 files changed

+855
-824
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Automated Changelog Update Workflow
2+
#
3+
# Automatically updates package-specific CHANGELOG.md files when PRs are merged to main.
4+
# This ensures the changelogs stay up-to-date with unreleased changes.
5+
#
6+
# **What it does:**
7+
# 1. Generates changelog for unreleased commits for each package
8+
# 2. Updates packages/opennextjs-cli/CHANGELOG.md and packages/opennextjs-mcp/CHANGELOG.md
9+
# 3. Commits and pushes changes back to main
10+
#
11+
# **Triggers:**
12+
# - PR merge to main (automatic)
13+
#
14+
# **Note:** This is separate from version-bump workflow to allow
15+
# changelog updates even when version doesn't need bumping.
16+
name: Update Changelog
17+
18+
on:
19+
pull_request:
20+
types: [closed]
21+
branches: [main]
22+
paths:
23+
- 'packages/**'
24+
- '.github/workflows/changelog-update.yml'
25+
26+
# Only run when PR is merged (not just closed)
27+
jobs:
28+
update-changelog:
29+
runs-on: ubuntu-latest
30+
timeout-minutes: 10
31+
32+
if: github.event.pull_request.merged == true
33+
34+
permissions:
35+
contents: write # Required to commit and push
36+
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@v6
40+
with:
41+
fetch-depth: 0 # Full history for git-cliff
42+
token: ${{ secrets.GITHUB_TOKEN }}
43+
44+
- name: Setup pnpm
45+
uses: pnpm/action-setup@v4
46+
47+
- name: Setup Node.js
48+
uses: actions/setup-node@v4
49+
with:
50+
node-version: '22'
51+
cache: 'pnpm'
52+
53+
- name: Install dependencies
54+
run: pnpm install --frozen-lockfile
55+
56+
- name: Setup git-cliff
57+
uses: kenji-miyake/setup-git-cliff@v1
58+
with:
59+
version: latest
60+
61+
- name: Generate unreleased changelog
62+
id: changelog
63+
env:
64+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65+
run: |
66+
set -e
67+
68+
# Check if there are any unreleased commits
69+
LAST_TAG=$(git describe --tags --match 'v*.*.*' --abbrev=0 2>/dev/null || echo "")
70+
71+
if [ -z "$LAST_TAG" ]; then
72+
echo "No previous tag found, skipping changelog update"
73+
echo "HAS_CHANGES=false" >> $GITHUB_OUTPUT
74+
exit 0
75+
fi
76+
77+
# Check if there are commits since last tag
78+
COMMIT_COUNT=$(git rev-list --count "$LAST_TAG"..HEAD 2>/dev/null || echo "0")
79+
80+
if [ "$COMMIT_COUNT" -eq 0 ]; then
81+
echo "No new commits since last tag, skipping changelog update"
82+
echo "HAS_CHANGES=false" >> $GITHUB_OUTPUT
83+
exit 0
84+
fi
85+
86+
echo "Found $COMMIT_COUNT commits since $LAST_TAG"
87+
echo "HAS_CHANGES=true" >> $GITHUB_OUTPUT
88+
89+
# Generate CLI changelog (writes directly to packages/opennextjs-cli/CHANGELOG.md)
90+
echo "📝 Generating CLI changelog..."
91+
pnpm changelog:package opennextjs-cli --unreleased || \
92+
echo "⚠️ CLI changelog generation failed" >&2
93+
94+
# Generate MCP changelog (writes directly to packages/opennextjs-mcp/CHANGELOG.md)
95+
echo "📝 Generating MCP changelog..."
96+
pnpm changelog:package opennextjs-mcp --unreleased || \
97+
echo "⚠️ MCP changelog generation failed" >&2
98+
99+
echo "✅ Package changelogs updated with unreleased changes"
100+
101+
- name: Configure git
102+
if: steps.changelog.outputs.HAS_CHANGES == 'true'
103+
run: |
104+
git config user.name "github-actions[bot]"
105+
git config user.email "github-actions[bot]@users.noreply.github.com"
106+
107+
- name: Commit and push changelogs
108+
if: steps.changelog.outputs.HAS_CHANGES == 'true'
109+
run: |
110+
git add packages/opennextjs-cli/CHANGELOG.md packages/opennextjs-mcp/CHANGELOG.md
111+
if git diff --staged --quiet; then
112+
echo "No changes to commit"
113+
exit 0
114+
fi
115+
git commit -m "docs: update package changelogs with unreleased changes [skip ci]"
116+
git push origin main
117+
echo "✅ Package changelogs committed and pushed"

.github/workflows/release.yml

Lines changed: 130 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,17 @@
1212
# 5. Publishes both packages to npm (tries OIDC first, falls back to NPM_TOKEN)
1313
# 6. Creates GitHub Release with changelog notes
1414
#
15-
# **Trigger:**
16-
# Push a version tag:
17-
# ```bash
18-
# git tag v1.0.0
19-
# git push origin main --tags
20-
# ```
15+
# **Triggers:**
16+
# 1. Push a version tag (automatic):
17+
# ```bash
18+
# git tag v1.0.0
19+
# git push origin v1.0.0
20+
# ```
21+
# 2. Manual workflow_dispatch (button in GitHub Actions dashboard):
22+
# - Go to Actions → Release → Run workflow
23+
# - Enter version (e.g., "0.1.0") or leave empty to use package.json version
24+
# - Click "Run workflow"
25+
# - Workflow will: create tag → generate changelogs → commit → push tag → publish to npm
2126
#
2227
# **Prerequisites:**
2328
# - package.json version must match tag version (e.g., 1.0.0)
@@ -52,6 +57,22 @@ on:
5257
required: false
5358
type: string
5459

60+
# YAML anchors for reusable configurations
61+
x-common-setup: &common-setup
62+
- name: Checkout repository
63+
uses: actions/checkout@v6
64+
with:
65+
fetch-depth: 0 # Full history for changelog generation
66+
- name: Setup pnpm
67+
uses: pnpm/action-setup@v4
68+
- name: Setup Node.js
69+
uses: actions/setup-node@v4
70+
with:
71+
node-version: '22'
72+
cache: 'pnpm'
73+
- name: Install dependencies
74+
run: pnpm install --frozen-lockfile
75+
5576
jobs:
5677
release:
5778
runs-on: ubuntu-latest
@@ -99,14 +120,22 @@ jobs:
99120
# Read from CLI package.json
100121
VERSION=$(node -p "require('./packages/opennextjs-cli/package.json').version")
101122
fi
123+
# Remove 'v' prefix if present
124+
VERSION="${VERSION#v}"
125+
TAG="v$VERSION"
126+
echo "TAG=$TAG" >> $GITHUB_OUTPUT
127+
echo "IS_MANUAL=true" >> $GITHUB_OUTPUT
102128
else
103129
# Extract version from tag (e.g., v1.0.0 → 1.0.0)
104130
TAG_NAME="${{ github.ref_name }}"
105131
VERSION="${TAG_NAME#v}"
132+
TAG="$TAG_NAME"
133+
echo "IS_MANUAL=false" >> $GITHUB_OUTPUT
106134
fi
107135
108136
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
109137
echo "Version: $VERSION"
138+
echo "Tag: $TAG"
110139
111140
- name: Verify CLI package.json version matches tag
112141
working-directory: packages/opennextjs-cli
@@ -130,111 +159,136 @@ jobs:
130159
fi
131160
echo "✅ MCP version match: $PACKAGE_VERSION"
132161
133-
- name: Check if git-cliff is installed
134-
id: git-cliff-check
162+
- name: Setup git-cliff
163+
uses: kenji-miyake/setup-git-cliff@v1
164+
with:
165+
version: latest
166+
167+
- name: Check if tag exists (for manual trigger)
168+
if: steps.version.outputs.IS_MANUAL == 'true'
169+
id: tag_check
135170
run: |
136-
if command -v git-cliff &> /dev/null; then
137-
echo "installed=true" >> $GITHUB_OUTPUT
171+
TAG="${{ steps.version.outputs.TAG }}"
172+
if git rev-parse "$TAG" >/dev/null 2>&1; then
173+
echo "EXISTS=true" >> $GITHUB_OUTPUT
174+
echo "⚠️ Tag $TAG already exists - will use existing tag"
138175
else
139-
echo "installed=false" >> $GITHUB_OUTPUT
176+
echo "EXISTS=false" >> $GITHUB_OUTPUT
177+
echo "✅ Tag $TAG does not exist - will create it and generate changelogs first"
140178
fi
141179
142-
- name: Install git-cliff (if needed)
143-
if: steps.git-cliff-check.outputs.installed == 'false'
180+
- name: Generate changelogs and create tag (manual trigger, tag doesn't exist)
181+
if: steps.version.outputs.IS_MANUAL == 'true' && steps.tag_check.outputs.EXISTS == 'false'
182+
env:
183+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
144184
run: |
145-
# Install git-cliff on Ubuntu
146-
sudo apt-get update && sudo apt-get install -y git-cliff || \
147-
echo "⚠️ git-cliff installation failed, will skip changelog generation" >&2
185+
set -e
186+
187+
TAG="${{ steps.version.outputs.TAG }}"
188+
189+
echo "📝 Generating CLI changelog..."
190+
pnpm changelog:package opennextjs-cli --tag "$TAG" || {
191+
echo "⚠️ CLI changelog generation failed" >&2
192+
exit 1
193+
}
194+
195+
echo "📝 Generating MCP changelog..."
196+
pnpm changelog:package opennextjs-mcp --tag "$TAG" || {
197+
echo "⚠️ MCP changelog generation failed" >&2
198+
exit 1
199+
}
200+
201+
echo "✅ Changelogs generated successfully"
202+
203+
# Commit changelogs
204+
git config user.name "github-actions[bot]"
205+
git config user.email "github-actions[bot]@users.noreply.github.com"
206+
207+
git add packages/opennextjs-cli/CHANGELOG.md packages/opennextjs-mcp/CHANGELOG.md
208+
209+
if git diff --staged --quiet; then
210+
echo "No changelog changes to commit"
211+
else
212+
git commit -m "chore: update changelogs for $TAG release"
213+
git push origin main
214+
echo "✅ Changelogs committed and pushed"
215+
fi
216+
217+
# Create and push tag (this will trigger this workflow again with tag push event)
218+
git tag -a "$TAG" -m "Release $TAG"
219+
git push origin "$TAG"
220+
echo "✅ Tag $TAG created and pushed"
221+
echo "ℹ️ This workflow will run again automatically when the tag is pushed"
148222
149-
- name: Generate package-specific changelog sections
223+
- name: Generate package-specific changelogs (when tag already exists)
224+
if: |
225+
(steps.version.outputs.IS_MANUAL == 'true' && steps.tag_check.outputs.EXISTS == 'true') ||
226+
steps.version.outputs.IS_MANUAL == 'false'
150227
env:
151228
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
152229
run: |
153230
set -e
154231
155-
TAG_VERSION="${{ steps.version.outputs.VERSION }}"
156-
TAG="v$TAG_VERSION"
232+
TAG="${{ steps.version.outputs.TAG }}"
157233
158-
# Generate CLI changelog section (only commits affecting packages/opennextjs-cli/**)
159-
echo "📝 Generating CLI changelog section..."
160-
git-cliff \
161-
--config cliff.toml \
162-
--include-path "packages/opennextjs-cli/**" \
163-
--tag "$TAG" \
164-
--latest \
165-
--unreleased \
166-
--output /tmp/cli-changelog.md \
167-
--verbose || \
234+
# Generate CLI changelog (writes directly to packages/opennextjs-cli/CHANGELOG.md)
235+
echo "📝 Generating CLI changelog..."
236+
pnpm changelog:package opennextjs-cli --tag "$TAG" || \
168237
echo "⚠️ CLI changelog generation failed" >&2
169238
170-
# Generate MCP changelog section (only commits affecting packages/opennextjs-mcp/**)
171-
echo "📝 Generating MCP changelog section..."
172-
git-cliff \
173-
--config cliff.toml \
174-
--include-path "packages/opennextjs-mcp/**" \
175-
--tag "$TAG" \
176-
--latest \
177-
--unreleased \
178-
--output /tmp/mcp-changelog.md \
179-
--verbose || \
239+
# Generate MCP changelog (writes directly to packages/opennextjs-mcp/CHANGELOG.md)
240+
echo "📝 Generating MCP changelog..."
241+
pnpm changelog:package opennextjs-mcp --tag "$TAG" || \
180242
echo "⚠️ MCP changelog generation failed" >&2
181243
182-
# Combine changelog sections
183-
echo "📝 Combining changelog sections..."
244+
# Extract changelog sections for GitHub Release notes
245+
# Read from package-specific CHANGELOG.md files
246+
echo "📝 Extracting changelog sections for release notes..."
184247
185248
# Start with version header
186249
echo "## [$TAG_VERSION] - $(date +%Y-%m-%d)" > /tmp/changelog-section.md
187250
echo "" >> /tmp/changelog-section.md
188251
189-
# Extract CLI section (skip header, get body)
190-
if [ -f /tmp/cli-changelog.md ] && [ -s /tmp/cli-changelog.md ]; then
191-
echo "### @jsonbored/opennextjs-cli" >> /tmp/changelog-section.md
192-
echo "" >> /tmp/changelog-section.md
193-
# Skip the header and version line, get the body
194-
tail -n +2 /tmp/cli-changelog.md | sed '/^## \[/,$d' >> /tmp/changelog-section.md || true
195-
echo "" >> /tmp/changelog-section.md
252+
# Extract CLI section from packages/opennextjs-cli/CHANGELOG.md
253+
if [ -f "packages/opennextjs-cli/CHANGELOG.md" ]; then
254+
# Find the version section in CLI changelog
255+
CLI_SECTION=$(awk "/^## \[$TAG_VERSION\]/,/^## \[|^<!-- generated/" "packages/opennextjs-cli/CHANGELOG.md" | head -n -1 || true)
256+
if [ -n "$CLI_SECTION" ]; then
257+
echo "### @jsonbored/opennextjs-cli" >> /tmp/changelog-section.md
258+
echo "" >> /tmp/changelog-section.md
259+
# Remove the version header line, keep the rest
260+
echo "$CLI_SECTION" | sed '/^## \[/d' >> /tmp/changelog-section.md || true
261+
echo "" >> /tmp/changelog-section.md
262+
fi
196263
fi
197264
198-
# Extract MCP section (skip header, get body)
199-
if [ -f /tmp/mcp-changelog.md ] && [ -s /tmp/mcp-changelog.md ]; then
200-
echo "### @jsonbored/opennextjs-mcp" >> /tmp/changelog-section.md
201-
echo "" >> /tmp/changelog-section.md
202-
# Skip the header and version line, get the body
203-
tail -n +2 /tmp/mcp-changelog.md | sed '/^## \[/,$d' >> /tmp/changelog-section.md || true
204-
echo "" >> /tmp/changelog-section.md
265+
# Extract MCP section from packages/opennextjs-mcp/CHANGELOG.md
266+
if [ -f "packages/opennextjs-mcp/CHANGELOG.md" ]; then
267+
# Find the version section in MCP changelog
268+
MCP_SECTION=$(awk "/^## \[$TAG_VERSION\]/,/^## \[|^<!-- generated/" "packages/opennextjs-mcp/CHANGELOG.md" | head -n -1 || true)
269+
if [ -n "$MCP_SECTION" ]; then
270+
echo "### @jsonbored/opennextjs-mcp" >> /tmp/changelog-section.md
271+
echo "" >> /tmp/changelog-section.md
272+
# Remove the version header line, keep the rest
273+
echo "$MCP_SECTION" | sed '/^## \[/d' >> /tmp/changelog-section.md || true
274+
echo "" >> /tmp/changelog-section.md
275+
fi
205276
fi
206277
207278
# If no package-specific sections, create a generic one
208-
if [ ! -s /tmp/cli-changelog.md ] && [ ! -s /tmp/mcp-changelog.md ]; then
279+
if [ ! -s /tmp/changelog-section.md ] || [ "$(wc -l < /tmp/changelog-section.md)" -lt 5 ]; then
209280
echo "Initial release of OpenNext.js CLI and MCP server packages." >> /tmp/changelog-section.md
210281
echo "" >> /tmp/changelog-section.md
211282
fi
212283
213-
# Update main CHANGELOG.md (prepend new section)
214-
if [ -f CHANGELOG.md ]; then
215-
# Prepend new section to existing changelog
216-
cat /tmp/changelog-section.md CHANGELOG.md > /tmp/combined-changelog.md
217-
mv /tmp/combined-changelog.md CHANGELOG.md
218-
else
219-
# Create new changelog with header
220-
cat > CHANGELOG.md << 'EOF'
221-
# Changelog
222-
223-
All notable changes to this project will be documented in this file.
224-
225-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
226-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
227-
228-
EOF
229-
cat /tmp/changelog-section.md >> CHANGELOG.md
230-
fi
231-
232284
# Set changelog section for GitHub release
233285
echo "CHANGELOG_SECTION<<EOF" >> $GITHUB_ENV
234286
cat /tmp/changelog-section.md >> $GITHUB_ENV
235287
echo "EOF" >> $GITHUB_ENV
236288
237-
echo "✅ Changelog generated successfully"
289+
echo "✅ Changelogs generated successfully"
290+
echo " - packages/opennextjs-cli/CHANGELOG.md"
291+
echo " - packages/opennextjs-mcp/CHANGELOG.md"
238292
239293
- name: Publish CLI to npm (try OIDC first)
240294
id: publish-cli-oidc

0 commit comments

Comments
 (0)