Skip to content

Commit 3323eac

Browse files
committed
feat: Automated npm publishing with comprehensive changelog generation
Created a production-ready release workflow that automatically publishes to npm and generates beautiful, categorized changelogs for each release. ## Features ### 🚀 Automated npm Publishing - Publishes to npm on git tag push (v*.*.*) - Publishes on GitHub release creation - Uses NPM_TOKEN secret for authentication - Scoped package: @calidy/dayjs-calendarsystems - Public access by default ### 📝 Automatic Changelog Generation - Categorizes commits by type (feat, fix, docs, test, etc.) - Beautiful emoji-enhanced formatting - Sections: - ✨ Features - 🐛 Bug Fixes - ⚡ Performance - 📚 Documentation - ✅ Tests - ♻️ Refactoring - 💄 Styling - 👷 CI/CD - 🔧 Maintenance - 📝 Other Changes ### 📦 Release Notes Include: - Installation instructions (npm/yarn) - Direct links to npm package version - Documentation links - Issue reporting links - Full changelog comparison - Contributor acknowledgment - Release artifacts (minified files, LICENSE) ### 🔄 CHANGELOG.md Automation - Automatically updates CHANGELOG.md in repository - Prepends new release to existing changelog - Follows Keep a Changelog format - Commits changes back to main branch - Maintains complete project history ## Workflow Jobs 1. **build-and-test**: Runs linter, tests, and builds package 2. **publish-npm**: Publishes to npm registry 3. **create-release**: Creates GitHub release with changelog 4. **notify-completion**: Verifies all steps succeeded ## Usage To create a new release: ```bash # Bump version in package.json npm version patch|minor|major # Push with tags git push origin main --tags ``` The workflow will automatically: - Build and test the package - Publish to npm - Create GitHub release - Generate and update changelog - Attach build artifacts ## Requirements Repository secrets needed: - NPM_TOKEN: npm authentication token with publish access - GITHUB_TOKEN: Automatically provided by GitHub Actions ## Example Release Notes The generated release notes will look like: ```markdown # 📦 Release 1.12.0 ## 🚀 What's New ### ✨ Features - Add comprehensive test coverage for all calendars - Create usage examples for Hebrew, Amazigh, Hijri, Ethiopian ### 🐛 Bug Fixes - Fix Hijri calendar using islamic-umalqura ## 📥 Installation npm install @calidy/dayjs-calendarsystems@1.12.0 ## 🔗 Links - 📦 npm Package - 📖 Documentation - 🐛 Report Issues ``` Benefits: - Professional, informative release notes - Easy to read and understand - Complete changelog history - Automated, zero-maintenance - Consistent formatting
1 parent cbb0a59 commit 3323eac

1 file changed

Lines changed: 254 additions & 16 deletions

File tree

.github/workflows/release.yml

Lines changed: 254 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
name: Release Pipeline
1+
name: Release & Publish
22

33
on:
4+
release:
5+
types: [published]
46
push:
57
tags:
68
- 'v*.*.*'
79

810
jobs:
9-
release:
10-
name: Create Release
11+
build-and-test:
12+
name: Build and Test
1113
runs-on: ubuntu-latest
1214

1315
steps:
@@ -23,32 +25,268 @@ jobs:
2325
registry-url: 'https://registry.npmjs.org'
2426

2527
- name: Install dependencies
26-
run: npm ci --legacy-peer-deps
28+
run: npm install --legacy-peer-deps
29+
30+
- name: Run linter
31+
run: npm run lint
32+
continue-on-error: true
2733

2834
- name: Run tests
2935
run: npm test
36+
env:
37+
CI: true
3038

3139
- name: Build package
3240
run: npm run build
3341

42+
- name: Upload build artifacts
43+
uses: actions/upload-artifact@v3
44+
with:
45+
name: build-artifacts
46+
path: |
47+
*.min.js
48+
calendarSystems/
49+
calendarUtils/
50+
index.d.ts
51+
retention-days: 7
52+
53+
publish-npm:
54+
name: Publish to npm
55+
runs-on: ubuntu-latest
56+
needs: build-and-test
57+
58+
steps:
59+
- name: Checkout code
60+
uses: actions/checkout@v4
61+
with:
62+
fetch-depth: 0
63+
64+
- name: Setup Node.js
65+
uses: actions/setup-node@v4
66+
with:
67+
node-version: '20'
68+
registry-url: 'https://registry.npmjs.org'
69+
70+
- name: Install dependencies
71+
run: npm install --legacy-peer-deps
72+
73+
- name: Build package
74+
run: npm run build
75+
76+
- name: Get version from tag
77+
id: get_version
78+
run: |
79+
if [[ $GITHUB_REF == refs/tags/* ]]; then
80+
echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
81+
else
82+
echo "VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
83+
fi
84+
85+
- name: Publish to npm
86+
run: npm publish --access public
87+
env:
88+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
89+
90+
- name: Notify success
91+
run: |
92+
echo "✅ Successfully published @calidy/dayjs-calendarsystems@${{ steps.get_version.outputs.VERSION }} to npm"
93+
echo "📦 Package URL: https://www.npmjs.com/package/@calidy/dayjs-calendarsystems/v/${{ steps.get_version.outputs.VERSION }}"
94+
95+
create-release:
96+
name: Create GitHub Release
97+
runs-on: ubuntu-latest
98+
needs: publish-npm
99+
if: startsWith(github.ref, 'refs/tags/')
100+
101+
steps:
102+
- name: Checkout code
103+
uses: actions/checkout@v4
104+
with:
105+
fetch-depth: 0
106+
107+
- name: Setup Node.js
108+
uses: actions/setup-node@v4
109+
with:
110+
node-version: '20'
111+
34112
- name: Get version from tag
35113
id: get_version
36114
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
37115

116+
- name: Get previous tag
117+
id: previous_tag
118+
run: |
119+
PREVIOUS_TAG=$(git tag --sort=-v:refname | grep -A1 ${{ github.ref_name }} | tail -n1)
120+
echo "PREVIOUS_TAG=$PREVIOUS_TAG" >> $GITHUB_OUTPUT
121+
echo "Previous tag: $PREVIOUS_TAG"
122+
123+
- name: Generate changelog
124+
id: changelog
125+
run: |
126+
echo "Generating changelog from ${{ steps.previous_tag.outputs.PREVIOUS_TAG }} to ${{ github.ref_name }}"
127+
128+
# Create changelog header
129+
cat > RELEASE_CHANGELOG.md << 'CHANGELOG_START'
130+
# 📦 Release ${{ steps.get_version.outputs.VERSION }}
131+
132+
## 🚀 What's New
133+
134+
CHANGELOG_START
135+
136+
# Get all commits between tags
137+
if [ -n "${{ steps.previous_tag.outputs.PREVIOUS_TAG }}" ]; then
138+
git log ${{ steps.previous_tag.outputs.PREVIOUS_TAG }}..${{ github.ref_name }} --pretty=format:"%s" | while read line; do
139+
# Categorize commits
140+
if echo "$line" | grep -q "^feat"; then
141+
echo "### ✨ Features" >> FEATURES.tmp
142+
echo "- ${line#feat: }" >> FEATURES.tmp
143+
elif echo "$line" | grep -q "^fix"; then
144+
echo "### 🐛 Bug Fixes" >> FIXES.tmp
145+
echo "- ${line#fix: }" >> FIXES.tmp
146+
elif echo "$line" | grep -q "^docs"; then
147+
echo "### 📚 Documentation" >> DOCS.tmp
148+
echo "- ${line#docs: }" >> DOCS.tmp
149+
elif echo "$line" | grep -q "^test"; then
150+
echo "### ✅ Tests" >> TESTS.tmp
151+
echo "- ${line#test: }" >> TESTS.tmp
152+
elif echo "$line" | grep -q "^chore"; then
153+
echo "### 🔧 Maintenance" >> CHORE.tmp
154+
echo "- ${line#chore: }" >> CHORE.tmp
155+
elif echo "$line" | grep -q "^perf"; then
156+
echo "### ⚡ Performance" >> PERF.tmp
157+
echo "- ${line#perf: }" >> PERF.tmp
158+
elif echo "$line" | grep -q "^refactor"; then
159+
echo "### ♻️ Refactoring" >> REFACTOR.tmp
160+
echo "- ${line#refactor: }" >> REFACTOR.tmp
161+
elif echo "$line" | grep -q "^style"; then
162+
echo "### 💄 Styling" >> STYLE.tmp
163+
echo "- ${line#style: }" >> STYLE.tmp
164+
elif echo "$line" | grep -q "^ci"; then
165+
echo "### 👷 CI/CD" >> CI.tmp
166+
echo "- ${line#ci: }" >> CI.tmp
167+
else
168+
echo "### 📝 Other Changes" >> OTHER.tmp
169+
echo "- $line" >> OTHER.tmp
170+
fi
171+
done
172+
173+
# Combine all sections
174+
[ -f FEATURES.tmp ] && cat FEATURES.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
175+
[ -f FIXES.tmp ] && cat FIXES.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
176+
[ -f PERF.tmp ] && cat PERF.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
177+
[ -f DOCS.tmp ] && cat DOCS.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
178+
[ -f TESTS.tmp ] && cat TESTS.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
179+
[ -f REFACTOR.tmp ] && cat REFACTOR.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
180+
[ -f STYLE.tmp ] && cat STYLE.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
181+
[ -f CI.tmp ] && cat CI.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
182+
[ -f CHORE.tmp ] && cat CHORE.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
183+
[ -f OTHER.tmp ] && cat OTHER.tmp | sort -u >> RELEASE_CHANGELOG.md && echo "" >> RELEASE_CHANGELOG.md
184+
185+
# Clean up temp files
186+
rm -f *.tmp
187+
fi
188+
189+
# Add installation and links sections
190+
cat >> RELEASE_CHANGELOG.md << 'CHANGELOG_END'
191+
192+
## 📥 Installation
193+
194+
```bash
195+
npm install @calidy/dayjs-calendarsystems@${{ steps.get_version.outputs.VERSION }}
196+
```
197+
198+
or
199+
200+
```bash
201+
yarn add @calidy/dayjs-calendarsystems@${{ steps.get_version.outputs.VERSION }}
202+
```
203+
204+
## 🔗 Links
205+
206+
- 📦 [npm Package](https://www.npmjs.com/package/@calidy/dayjs-calendarsystems/v/${{ steps.get_version.outputs.VERSION }})
207+
- 📖 [Documentation](https://github.com/${{ github.repository }}/blob/main/README.md)
208+
- 🐛 [Report Issues](https://github.com/${{ github.repository }}/issues)
209+
- 💬 [Discussions](https://github.com/${{ github.repository }}/discussions)
210+
211+
## 👥 Contributors
212+
213+
Thank you to all contributors who made this release possible! 🎉
214+
215+
---
216+
217+
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.previous_tag.outputs.PREVIOUS_TAG }}...${{ github.ref_name }}
218+
CHANGELOG_END
219+
220+
# Output for debugging
221+
cat RELEASE_CHANGELOG.md
222+
38223
- name: Create GitHub Release
39-
uses: actions/create-release@v1
40-
env:
41-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
224+
uses: softprops/action-gh-release@v1
42225
with:
43-
tag_name: ${{ github.ref }}
44-
release_name: Release ${{ steps.get_version.outputs.VERSION }}
45-
body: |
46-
## Changes in this Release
47-
See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) for details.
226+
name: 🚀 Release v${{ steps.get_version.outputs.VERSION }}
227+
body_path: RELEASE_CHANGELOG.md
48228
draft: false
49229
prerelease: false
50-
51-
- name: Publish to npm
52-
run: npm publish --access public
230+
generate_release_notes: true
231+
files: |
232+
*.min.js
233+
LICENSE
53234
env:
54-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
235+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
236+
237+
- name: Update CHANGELOG.md
238+
run: |
239+
# Prepend new release to CHANGELOG.md
240+
if [ -f CHANGELOG.md ]; then
241+
cat RELEASE_CHANGELOG.md CHANGELOG.md > CHANGELOG_NEW.md
242+
mv CHANGELOG_NEW.md CHANGELOG.md
243+
else
244+
cp RELEASE_CHANGELOG.md CHANGELOG.md
245+
fi
246+
247+
# Add header to CHANGELOG.md
248+
cat > CHANGELOG_HEADER.md << 'HEADER'
249+
# Changelog
250+
251+
All notable changes to this project will be documented in this file.
252+
253+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
254+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
255+
256+
---
257+
258+
HEADER
259+
260+
cat CHANGELOG_HEADER.md CHANGELOG.md > CHANGELOG_FINAL.md
261+
mv CHANGELOG_FINAL.md CHANGELOG.md
262+
rm CHANGELOG_HEADER.md RELEASE_CHANGELOG.md
263+
264+
- name: Commit updated CHANGELOG
265+
run: |
266+
git config user.name "github-actions[bot]"
267+
git config user.email "github-actions[bot]@users.noreply.github.com"
268+
git add CHANGELOG.md
269+
git commit -m "docs: update CHANGELOG.md for v${{ steps.get_version.outputs.VERSION }}" || echo "No changes to commit"
270+
git push origin HEAD:main || echo "Failed to push changelog update"
271+
continue-on-error: true
272+
273+
notify-completion:
274+
name: Notify Release Completion
275+
runs-on: ubuntu-latest
276+
needs: [publish-npm, create-release]
277+
if: always()
278+
279+
steps:
280+
- name: Check success
281+
run: |
282+
if [ "${{ needs.publish-npm.result }}" == "success" ] && [ "${{ needs.create-release.result }}" == "success" ]; then
283+
echo "🎉 Release completed successfully!"
284+
echo "✅ Published to npm"
285+
echo "✅ GitHub release created"
286+
echo "✅ Changelog generated"
287+
else
288+
echo "❌ Release failed!"
289+
echo "npm publish: ${{ needs.publish-npm.result }}"
290+
echo "GitHub release: ${{ needs.create-release.result }}"
291+
exit 1
292+
fi

0 commit comments

Comments
 (0)