-
-
Notifications
You must be signed in to change notification settings - Fork 6
135 lines (110 loc) · 4.23 KB
/
stable-release.yml
File metadata and controls
135 lines (110 loc) · 4.23 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
name: Manual Release
on:
workflow_dispatch:
inputs:
version:
description: 'Target version (e.g. 1.0.0, 0.3.0)'
required: true
type: string
release_notes:
description: 'Curated release notes (markdown). Leave empty to auto-generate from changelog.'
required: false
type: string
permissions:
contents: write
pull-requests: write
jobs:
create-release-pr:
name: Create Release PR
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4
- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
with:
node-version: '20'
cache: 'pnpm'
- name: Validate version
env:
VERSION: ${{ inputs.version }}
run: |
# Must be valid semver (no prerelease suffix)
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Version must be valid semver (e.g. 1.0.0), got: $VERSION"
exit 1
fi
echo "Target version: $VERSION"
- name: Create release branch and PR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.version }}
CUSTOM_NOTES: ${{ inputs.release_notes }}
run: |
TODAY=$(date +%Y-%m-%d)
RELEASE_BRANCH="release/v${VERSION}"
# Configure git
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Create release branch from main
git checkout main
git pull origin main
git checkout -b "$RELEASE_BRANCH"
# Update package.json version
npm version "$VERSION" --no-git-tag-version
# Sync pnpm-lock.yaml with the updated package.json version
pnpm install --lockfile-only
# Update CHANGELOG.md if custom notes provided
if [ -n "$CUSTOM_NOTES" ]; then
node -e "
const fs = require('fs');
const version = process.env.VERSION;
const date = process.env.TODAY;
const notes = process.env.CUSTOM_NOTES;
const changelogPath = 'CHANGELOG.md';
let changelog = fs.readFileSync(changelogPath, 'utf8');
const lines = changelog.split('\n');
let insertIdx = lines.findIndex(l => l.trim().match(/^## \[\d/));
if (insertIdx === -1) insertIdx = 6;
const entry = '## [' + version + '] - ' + date + '\n\n' + notes + '\n\n';
const header = lines.slice(0, insertIdx).join('\n');
const rest = lines.slice(insertIdx).join('\n');
changelog = header + '\n\n' + entry + rest;
fs.writeFileSync(changelogPath, changelog);
console.log('Updated CHANGELOG.md with custom notes for v' + version);
"
fi
# Commit changes
git add package.json pnpm-lock.yaml CHANGELOG.md
git commit -m "chore(release): prepare release v${VERSION}"
# Push branch
git push origin "$RELEASE_BRANCH"
# Build PR body
TMPFILE=$(mktemp)
if [ -n "$CUSTOM_NOTES" ]; then
CHANGES_SECTION="$CUSTOM_NOTES"
else
CHANGES_SECTION="See CHANGELOG.md for full details."
fi
cat > "$TMPFILE" <<PRBODY
## Release v${VERSION}
This PR was manually triggered to prepare release v${VERSION}.
### Changes
${CHANGES_SECTION}
### What happens when this PR is merged
1. Git tag \`v${VERSION}\` will be created
2. GitHub Release will be published
3. Package will be published to npm with \`latest\` tag
---
This PR was generated by the manual release workflow.
PRBODY
gh pr create \
--title "chore(release): v${VERSION}" \
--body-file "$TMPFILE" \
--label "release" \
--base main
rm -f "$TMPFILE"