-
Notifications
You must be signed in to change notification settings - Fork 0
221 lines (183 loc) · 7.38 KB
/
release.yml
File metadata and controls
221 lines (183 loc) · 7.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
name: Publish Package
on:
push:
tags:
- 'v*'
permissions:
id-token: write # Required for OIDC trusted publishing
contents: write # Required for creating GitHub releases
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # Fetch all history for changelog generation
persist-credentials: false
- name: Verify tag is on main branch
env:
COMMIT_SHA: ${{ github.sha }}
REF_NAME: ${{ github.ref_name }}
run: |
# Check if the tag is reachable from main branch
git fetch origin main
if ! git merge-base --is-ancestor "$COMMIT_SHA" origin/main; then
echo "❌ Error: This tag is not on the main branch"
echo "Tags must be created on the main branch to trigger a release"
echo "Current tag: $REF_NAME"
exit 1
fi
echo "✅ Tag is on main branch, proceeding with release"
- name: Setup pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
with:
version: 11.1.2
- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.14.0"
# Trusted publishing (OIDC) is an npm-registry feature; keep the
# publish step on the npm CLI even though deps use pnpm.
- name: Update npm for trusted publishing
run: npm install -g npm@latest
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Extract version from tag
id: version
env:
REF_NAME: ${{ github.ref_name }}
run: |
# Git ref names can legitimately contain shell metacharacters, and
# this value flows into later steps. Reject anything that is not a
# clean semver release tag before using it anywhere.
if [[ ! "$REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
echo "❌ Error: Tag '$REF_NAME' is not a valid release tag (expected vX.Y.Z)"
exit 1
fi
VERSION="${REF_NAME#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Publishing version: $VERSION"
- name: Verify tag matches package.json version
env:
TAG_VERSION: ${{ steps.version.outputs.version }}
run: |
PKG_VERSION=$(node -p "require('./package.json').version")
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "❌ Error: Tag version (v$TAG_VERSION) does not match package.json version ($PKG_VERSION)"
echo "Please ensure package.json version is updated before creating the tag"
exit 1
fi
echo "✅ Version match confirmed: $TAG_VERSION"
- name: Build SDK
run: pnpm build
- name: Run tests
run: pnpm test
- name: Generate release notes
id: release_notes
env:
CURRENT_TAG: ${{ github.ref_name }}
VERSION: ${{ steps.version.outputs.version }}
REPO: ${{ github.repository }}
run: |
# Get the previous version tag (second most recent v* tag by version order)
# This is more reliable than using git describe which follows commit ancestry
PREV_TAG=$(git tag -l 'v*' --sort=-version:refname | grep -v "^${CURRENT_TAG}$" | head -1)
if [ -z "$PREV_TAG" ]; then
echo "No previous tag found"
else
echo "Previous tag: $PREV_TAG"
fi
# Get current date
RELEASE_DATE=$(date +%Y-%m-%d)
# VERSION is provided via the validated env var declared above
# Generate changelog with PR links
if [ -n "$PREV_TAG" ]; then
echo "Generating changelog from $PREV_TAG to $GITHUB_REF_NAME"
# Extract commits with PR numbers and format them
# Use tab as delimiter to safely handle semicolons and special characters
COMMITS=$(git log "${PREV_TAG}..HEAD" --pretty=format:"%s %h" --no-merges)
else
echo "No previous tag found, using all commits"
COMMITS=$(git log --pretty=format:"%s %h" --no-merges)
fi
# Process commits and categorize them
FEATURES=""
FIXES=""
OTHER=""
while IFS=$'\t' read -r message hash; do
# Skip empty lines
[ -z "$message" ] && continue
# Extract PR number if exists
if [[ $message =~ \(#([0-9]+)\) ]]; then
PR_NUM="${BASH_REMATCH[1]}"
# Remove the (#PR_NUM) from message to avoid duplication (handles with or without space)
CLEAN_MESSAGE=$(echo "$message" | sed -E 's/ ?\(#[0-9]+\)//')
PR_LINK="[#$PR_NUM](https://github.com/$REPO/pull/$PR_NUM)"
COMMIT_LINK="[$hash](https://github.com/$REPO/commit/$hash)"
ITEM="$CLEAN_MESSAGE ($PR_LINK) ($COMMIT_LINK)"
else
COMMIT_LINK="[$hash](https://github.com/$REPO/commit/$hash)"
ITEM="$message ($COMMIT_LINK)"
fi
# Categorize by prefix and strip conventional commit prefix
if [[ $message =~ ^feat(\([^\)]+\))?: ]]; then
# Strip "feat:" or "feat(scope):" from the beginning of ITEM
STRIPPED_ITEM=$(echo "$ITEM" | sed -E 's/^feat(\([^)]+\))?: //')
FEATURES="${FEATURES}- ${STRIPPED_ITEM}
"
elif [[ $message =~ ^fix(\([^\)]+\))?: ]]; then
# Strip "fix:" or "fix(scope):" from the beginning of ITEM
STRIPPED_ITEM=$(echo "$ITEM" | sed -E 's/^fix(\([^)]+\))?: //')
FIXES="${FIXES}- ${STRIPPED_ITEM}
"
else
OTHER="${OTHER}- ${ITEM}
"
fi
done <<< "$COMMITS"
# Create release notes
cat > release_notes.md <<EOF
$VERSION ($RELEASE_DATE)
EOF
# Add Features section if exists
if [ -n "$FEATURES" ]; then
cat >> release_notes.md <<EOF
## Features
$FEATURES
EOF
fi
# Add Fixes section if exists
if [ -n "$FIXES" ]; then
cat >> release_notes.md <<EOF
## Bug Fixes
$FIXES
EOF
fi
# Add Other changes if exists
if [ -n "$OTHER" ]; then
cat >> release_notes.md <<EOF
## Changes
$OTHER
EOF
fi
# Add npm package link
cat >> release_notes.md <<EOF
## Install
\`\`\`bash
npm install @formo/analytics-node@$VERSION
\`\`\`
[@formo/analytics-node $VERSION npm package](https://www.npmjs.com/package/@formo/analytics-node/v/$VERSION)
EOF
- name: Publish to npm
run: npm publish --provenance
# Explicitly use --provenance flag for clarity
# OIDC trusted publishing (id-token: write) enables automatic provenance generation
- name: Create GitHub Release
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
with:
body_path: release_notes.md
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}