Skip to content

Commit 0ccd84b

Browse files
Merge pull request #8 from auth0/release/auto_npm_release
chore: GH workflow to auto publish to NPM
2 parents d5e9f77 + f6dcd83 commit 0ccd84b

File tree

1 file changed

+247
-0
lines changed

1 file changed

+247
-0
lines changed

.github/workflows/publish-npm.yml

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
name: Publish to Public NPM
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
push:
7+
branches:
8+
- master
9+
workflow_dispatch:
10+
inputs:
11+
dry_run:
12+
description: "Dry run (preview without publishing)"
13+
required: false
14+
type: boolean
15+
default: true
16+
17+
permissions:
18+
contents: write
19+
id-token: write
20+
21+
jobs:
22+
publish:
23+
name: Build & Publish to Public NPM
24+
runs-on: ubuntu-latest
25+
permissions:
26+
contents: write
27+
id-token: write
28+
29+
steps:
30+
- name: Determine dry run mode
31+
id: dry_run_mode
32+
run: |
33+
if [ "${{ github.event_name }}" = "pull_request" ]; then
34+
echo "DRY_RUN=true" >> $GITHUB_ENV
35+
echo "Running in DRY RUN mode (PR)"
36+
elif [ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref }}" = "refs/heads/master" ]; then
37+
echo "DRY_RUN=false" >> $GITHUB_ENV
38+
echo "Running in PUBLISH mode (merged to master)"
39+
elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
40+
echo "DRY_RUN=${{ github.event.inputs.dry_run }}" >> $GITHUB_ENV
41+
echo "Running in MANUAL mode (dry_run=${{ github.event.inputs.dry_run }})"
42+
else
43+
echo "DRY_RUN=true" >> $GITHUB_ENV
44+
echo "Running in DRY RUN mode (default)"
45+
fi
46+
47+
- name: Checkout repository
48+
uses: actions/checkout@v4
49+
with:
50+
fetch-depth: 0
51+
52+
- name: Setup Node.js
53+
uses: actions/setup-node@v4
54+
with:
55+
node-version: "20"
56+
cache: "yarn"
57+
registry-url: "https://registry.npmjs.org"
58+
59+
- name: Install dependencies
60+
run: yarn install --frozen-lockfile
61+
62+
- name: Detect version and npm tag from package.json
63+
id: detect
64+
run: |
65+
PACKAGE_NAME=$(node -p "require('./package.json').name")
66+
VERSION=$(node -p "require('./package.json').version")
67+
68+
determine_tag() {
69+
local version=$1
70+
if [[ "$version" == *"alpha"* ]]; then
71+
echo "alpha"
72+
elif [[ "$version" == *"beta"* ]]; then
73+
echo "beta"
74+
elif [[ "$version" == *"rc"* ]]; then
75+
echo "next"
76+
else
77+
echo "latest"
78+
fi
79+
}
80+
81+
NPM_TAG=$(determine_tag "$VERSION")
82+
83+
echo "Detected from package.json:"
84+
echo "Package: $PACKAGE_NAME"
85+
echo "Version: $VERSION"
86+
echo "NPM Tag: ${NPM_TAG}"
87+
88+
echo "PACKAGE_NAME=${PACKAGE_NAME}" >> $GITHUB_ENV
89+
echo "VERSION=${VERSION}" >> $GITHUB_ENV
90+
echo "NPM_TAG=${NPM_TAG}" >> $GITHUB_ENV
91+
92+
- name: Check if version already exists on npm
93+
env:
94+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
95+
run: |
96+
echo "Checking if ${PACKAGE_NAME}@${VERSION} already exists on npm..."
97+
98+
# Check if the specific version exists
99+
if npm view "${PACKAGE_NAME}@${VERSION}" version 2>/dev/null; then
100+
echo "❌ ERROR: Version ${VERSION} already exists on npm!"
101+
echo "Please bump the version in package.json before publishing."
102+
exit 1
103+
else
104+
echo "✅ Version ${VERSION} does not exist on npm. Safe to publish."
105+
fi
106+
107+
- name: Check if git tag already exists
108+
run: |
109+
TAG_NAME="v${VERSION}"
110+
echo "Checking if git tag ${TAG_NAME} already exists..."
111+
112+
if git rev-parse "${TAG_NAME}" >/dev/null 2>&1; then
113+
echo "❌ ERROR: Git tag ${TAG_NAME} already exists!"
114+
echo "Please use a different version or delete the existing tag."
115+
exit 1
116+
else
117+
echo "✅ Git tag ${TAG_NAME} does not exist. Safe to proceed."
118+
fi
119+
120+
- name: Update package for public npm
121+
run: |
122+
node -e "
123+
const pkg = require('./package.json');
124+
125+
pkg.publishConfig = {
126+
access: 'public',
127+
registry: 'https://registry.npmjs.org/'
128+
};
129+
130+
require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n');
131+
"
132+
133+
- name: Publish package to public npm
134+
id: publish
135+
env:
136+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
137+
run: |
138+
echo "Publishing ${PACKAGE_NAME}@${VERSION} with tag: ${NPM_TAG}"
139+
echo "Dry run mode: ${DRY_RUN}"
140+
141+
if [ "$DRY_RUN" = "true" ]; then
142+
echo "DRY RUN - Skipping publish"
143+
npm publish --dry-run --tag="${NPM_TAG}"
144+
echo "published=dry-run" >> $GITHUB_OUTPUT
145+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
146+
echo "package_name=${PACKAGE_NAME}" >> $GITHUB_OUTPUT
147+
148+
echo "Published ${PACKAGE_NAME}@${VERSION} (dry run)"
149+
else
150+
npm publish --tag="${NPM_TAG}"
151+
echo "published=true" >> $GITHUB_OUTPUT
152+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
153+
echo "package_name=${PACKAGE_NAME}" >> $GITHUB_OUTPUT
154+
echo "Published ${PACKAGE_NAME}@${VERSION}"
155+
fi
156+
157+
- name: Generate Summary
158+
run: |
159+
echo "## Public NPM Publication Summary" >> $GITHUB_STEP_SUMMARY
160+
echo "" >> $GITHUB_STEP_SUMMARY
161+
162+
if [ "$DRY_RUN" = "true" ]; then
163+
echo "### DRY RUN MODE" >> $GITHUB_STEP_SUMMARY
164+
echo "No packages were published. This was a test run." >> $GITHUB_STEP_SUMMARY
165+
echo "" >> $GITHUB_STEP_SUMMARY
166+
fi
167+
168+
echo "### Published Package" >> $GITHUB_STEP_SUMMARY
169+
echo "" >> $GITHUB_STEP_SUMMARY
170+
171+
if [ "${{ steps.publish.outputs.published }}" != "" ]; then
172+
echo "- \`${{ steps.publish.outputs.package_name }}@${VERSION}\`" >> $GITHUB_STEP_SUMMARY
173+
echo " - Tag: \`${NPM_TAG}\`" >> $GITHUB_STEP_SUMMARY
174+
echo " - Registry: https://registry.npmjs.org" >> $GITHUB_STEP_SUMMARY
175+
echo " - Install: \`npm install ${{ steps.publish.outputs.package_name }}@${NPM_TAG}\`" >> $GITHUB_STEP_SUMMARY
176+
echo "" >> $GITHUB_STEP_SUMMARY
177+
fi
178+
179+
echo "### Links" >> $GITHUB_STEP_SUMMARY
180+
echo "" >> $GITHUB_STEP_SUMMARY
181+
182+
if [ "${{ steps.publish.outputs.published }}" != "" ]; then
183+
echo "- [View ${{ steps.publish.outputs.package_name }} on npm](https://www.npmjs.com/package/${{ steps.publish.outputs.package_name }})" >> $GITHUB_STEP_SUMMARY
184+
fi
185+
186+
- name: Create Git tag
187+
if: env.DRY_RUN != 'true'
188+
run: |
189+
git config user.name "github-actions[bot]"
190+
git config user.email "github-actions[bot]@users.noreply.github.com"
191+
192+
if [ "${{ steps.publish.outputs.published }}" = "true" ]; then
193+
TAG_NAME="v${VERSION}"
194+
git tag -a "$TAG_NAME" -m "Release ${PACKAGE_NAME}@${VERSION}"
195+
git push origin "$TAG_NAME"
196+
echo "Created tag: $TAG_NAME"
197+
fi
198+
199+
- name: Create GitHub Release
200+
if: |
201+
env.DRY_RUN != 'true' &&
202+
steps.publish.outputs.published == 'true'
203+
uses: softprops/action-gh-release@v2
204+
with:
205+
tag_name: v${{ env.VERSION }}
206+
name: "${{ env.PACKAGE_NAME }}@${{ env.VERSION }}"
207+
body: |
208+
Published to NPM
209+
210+
**Package**: `${{ env.PACKAGE_NAME }}`
211+
**Version**: `${{ env.VERSION }}`
212+
**NPM Tag**: `${{ env.NPM_TAG }}`
213+
214+
```bash
215+
npm install ${{ env.PACKAGE_NAME }}@${{ env.VERSION }}
216+
```
217+
218+
[View on NPM](https://www.npmjs.com/package/${{ env.PACKAGE_NAME }}/v/${{ env.VERSION }})
219+
prerelease: ${{ env.NPM_TAG != 'latest' }}
220+
draft: false
221+
222+
- name: Restore package.json file
223+
if: always()
224+
run: |
225+
git checkout package.json || true
226+
227+
- name: Handle workflow failure
228+
if: failure()
229+
run: |
230+
echo "## Workflow Failed" >> $GITHUB_STEP_SUMMARY
231+
echo "" >> $GITHUB_STEP_SUMMARY
232+
echo "The workflow encountered an error. Please check the logs above for details." >> $GITHUB_STEP_SUMMARY
233+
echo "" >> $GITHUB_STEP_SUMMARY
234+
echo "### Common Issues" >> $GITHUB_STEP_SUMMARY
235+
echo "" >> $GITHUB_STEP_SUMMARY
236+
echo "- **Authentication**: Verify NPM_TOKEN secret is configured correctly" >> $GITHUB_STEP_SUMMARY
237+
echo "- **Version conflict**: Package version may already exist on npm" >> $GITHUB_STEP_SUMMARY
238+
echo "- **Tests failure**: Check if tests pass successfully" >> $GITHUB_STEP_SUMMARY
239+
echo "- **Network issues**: NPM registry may be unreachable" >> $GITHUB_STEP_SUMMARY
240+
echo "" >> $GITHUB_STEP_SUMMARY
241+
echo "### Next Steps" >> $GITHUB_STEP_SUMMARY
242+
echo "" >> $GITHUB_STEP_SUMMARY
243+
echo "1. Review the error logs in this workflow run" >> $GITHUB_STEP_SUMMARY
244+
echo "2. Fix the issue and retry the workflow" >> $GITHUB_STEP_SUMMARY
245+
echo "3. If needed, manually publish using: \`npm publish\`" >> $GITHUB_STEP_SUMMARY
246+
echo "" >> $GITHUB_STEP_SUMMARY
247+
echo "**Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)