1+ name : Release
2+
3+ on :
4+ pull_request :
5+ branches :
6+ - master
7+ - main
8+ types :
9+ - closed
10+ workflow_dispatch :
11+ inputs :
12+ version :
13+ description : ' Version to publish (e.g., 1.2.3)'
14+ required : false
15+ type : string
16+
17+ jobs :
18+ release :
19+ if : |
20+ (github.event_name == 'pull_request' &&
21+ github.event.pull_request.merged == true &&
22+ contains(github.event.pull_request.labels.*.name, 'Type: Release')) ||
23+ github.event_name == 'workflow_dispatch'
24+ runs-on : ubuntu-latest
25+ permissions :
26+ contents : write
27+ id-token : write # OIDC
28+ pull-requests : write # PR comment
29+ steps :
30+ - name : Checkout
31+ uses : actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
32+ with :
33+ fetch-depth : 0
34+ persist-credentials : false
35+
36+ - name : Get package info
37+ id : package
38+ run : |
39+ if [ "$EVENT_NAME" = "workflow_dispatch" ] && [ -n "$INPUT_VERSION" ]; then
40+ VERSION="$INPUT_VERSION"
41+ else
42+ VERSION=$(node -p "require('./package.json').version")
43+ fi
44+ PACKAGE_NAME=$(node -p "require('./package.json').name")
45+ echo "version=$VERSION" >> $GITHUB_OUTPUT
46+ echo "name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
47+ env :
48+ EVENT_NAME : ${{ github.event_name }}
49+ INPUT_VERSION : ${{ github.event.inputs.version }}
50+
51+ - name : Check if tag exists
52+ id : tag-check
53+ run : |
54+ if git rev-parse "v$VERSION" >/dev/null 2>&1; then
55+ echo "exists=true" >> $GITHUB_OUTPUT
56+ else
57+ echo "exists=false" >> $GITHUB_OUTPUT
58+ fi
59+ env :
60+ VERSION : ${{ steps.package.outputs.version }}
61+
62+ - name : Setup Node.js
63+ if : steps.tag-check.outputs.exists == 'false'
64+ uses : actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1
65+ with :
66+ node-version : 22
67+ registry-url : ' https://registry.npmjs.org'
68+
69+ - name : Ensure npm 11.5.1 or later is installed
70+ if : steps.tag-check.outputs.exists == 'false'
71+ run : |
72+ NPM_VERSION=$(npm -v)
73+ echo "Current npm version: $NPM_VERSION"
74+ if ! npx semver -r ">=11.5.1" "$NPM_VERSION"; then
75+ echo "npm version $NPM_VERSION is too old. Installing latest npm..."
76+ npm install -g npm@latest
77+ echo "Updated npm version: $(npm -v)"
78+ fi
79+
80+ - name : Install dependencies
81+ if : steps.tag-check.outputs.exists == 'false'
82+ run : npm ci
83+
84+ - name : Build package
85+ if : steps.tag-check.outputs.exists == 'false'
86+ run : npm run build || true
87+
88+ - name : Publish to npm with provenance
89+ if : steps.tag-check.outputs.exists == 'false'
90+ run : npm publish --provenance --access public
91+
92+ - name : Create GitHub Release with tag
93+ id : create-release
94+ if : steps.tag-check.outputs.exists == 'false'
95+ run : |
96+ if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
97+ RELEASE_URL=$(gh release create "v$VERSION" \
98+ --title "v$VERSION" \
99+ --target "$SHA" \
100+ --generate-notes)
101+ else
102+ RELEASE_URL=$(gh release create "v$VERSION" \
103+ --title "v$VERSION" \
104+ --target "$SHA" \
105+ --notes "$PR_BODY")
106+ fi
107+ echo "url=$RELEASE_URL" >> $GITHUB_OUTPUT
108+ env :
109+ GH_TOKEN : ${{ github.token }}
110+ VERSION : ${{ steps.package.outputs.version }}
111+ SHA : ${{ github.sha }}
112+ EVENT_NAME : ${{ github.event_name }}
113+ PR_BODY : ${{ github.event.pull_request.body }}
114+
115+ - name : Comment on PR - Success
116+ if : |
117+ always() &&
118+ github.event_name == 'pull_request' &&
119+ steps.tag-check.outputs.exists == 'false' &&
120+ success()
121+ run : |
122+ gh pr comment "$PR_NUMBER" \
123+ --body "✅ **Release v$VERSION completed successfully!**
124+
125+ - 📦 npm package: https://www.npmjs.com/package/$PACKAGE_NAME/v/$VERSION
126+ - 🏷️ GitHub Release: $RELEASE_URL
127+ - 🔗 Workflow run: $SERVER_URL/$REPOSITORY/actions/runs/$RUN_ID"
128+ env :
129+ GH_TOKEN : ${{ github.token }}
130+ PR_NUMBER : ${{ github.event.pull_request.number }}
131+ VERSION : ${{ steps.package.outputs.version }}
132+ PACKAGE_NAME : ${{ steps.package.outputs.name }}
133+ RELEASE_URL : ${{ steps.create-release.outputs.url }}
134+ SERVER_URL : ${{ github.server_url }}
135+ REPOSITORY : ${{ github.repository }}
136+ RUN_ID : ${{ github.run_id }}
137+
138+ - name : Comment on PR - Failure
139+ if : |
140+ always() &&
141+ github.event_name == 'pull_request' &&
142+ steps.tag-check.outputs.exists == 'false' &&
143+ failure()
144+ run : |
145+ gh pr comment "$PR_NUMBER" \
146+ --body "❌ **Release v$VERSION failed**
147+
148+ Please check the workflow logs for details.
149+ 🔗 Workflow run: $SERVER_URL/$REPOSITORY/actions/runs/$RUN_ID"
150+ env :
151+ GH_TOKEN : ${{ github.token }}
152+ PR_NUMBER : ${{ github.event.pull_request.number }}
153+ VERSION : ${{ steps.package.outputs.version }}
154+ SERVER_URL : ${{ github.server_url }}
155+ REPOSITORY : ${{ github.repository }}
156+ RUN_ID : ${{ github.run_id }}
0 commit comments