-
Notifications
You must be signed in to change notification settings - Fork 0
166 lines (140 loc) · 4.82 KB
/
Copy pathrelease.yml
File metadata and controls
166 lines (140 loc) · 4.82 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
name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: "Tag to release (e.g., v1.0.1) — must already exist on origin"
required: true
type: string
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: write
jobs:
validate:
name: Validate (pre-release gate)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22"
cache: npm
- name: Install dependencies
run: npm ci || (sleep 10 && npm ci)
- name: Format check
run: npm run fmt:check
- name: Schema + invariant validation
run: npm run validate
- name: Tests
run: npm test
- name: Lockfile drift check
run: npm run lock:check
verify-tag:
name: Verify tag matches package.json + CHANGELOG
runs-on: ubuntu-latest
needs: validate
timeout-minutes: 5
outputs:
version: ${{ steps.extract.outputs.version }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Extract tag and package.json version
id: extract
shell: bash
run: |
# Resolve the tag from either the push event or workflow_dispatch input.
if [ -n "${{ github.event.inputs.tag }}" ]; then
TAG_REF="${{ github.event.inputs.tag }}"
else
TAG_REF="${GITHUB_REF#refs/tags/}"
fi
# Strip the leading 'v' so we can compare against package.json's plain semver.
TAG_VERSION="${TAG_REF#v}"
PKG_VERSION=$(node -p "require('./package.json').version")
echo "tag_ref=$TAG_REF" >> "$GITHUB_OUTPUT"
echo "tag_version=$TAG_VERSION" >> "$GITHUB_OUTPUT"
echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT"
echo "Tag: $TAG_REF (version: $TAG_VERSION)"
echo "package.json version: $PKG_VERSION"
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "::error::Tag version ($TAG_VERSION) does not match package.json version ($PKG_VERSION)"
exit 1
fi
{
echo "### Tag verification"
echo ""
echo "- Tag: \`$TAG_REF\`"
echo "- package.json version: \`$PKG_VERSION\`"
echo "- Match: yes"
} >> "$GITHUB_STEP_SUMMARY"
- name: Verify CHANGELOG has section for tag version
shell: bash
run: |
VERSION="${{ steps.extract.outputs.tag_version }}"
if [ ! -f CHANGELOG.md ]; then
echo "::error::CHANGELOG.md is missing"
exit 1
fi
# Look for either "## [VERSION]" or "## [VERSION] - YYYY-MM-DD".
if grep -E "^## \[$VERSION\]" CHANGELOG.md > /dev/null; then
echo "Found CHANGELOG section for $VERSION"
{
echo "### CHANGELOG verification"
echo ""
echo "- Section \`## [$VERSION]\` found"
} >> "$GITHUB_STEP_SUMMARY"
else
echo "::error::CHANGELOG.md has no section for [$VERSION]. Add a '## [$VERSION] - YYYY-MM-DD' header before tagging."
exit 1
fi
release:
name: Create GitHub Release
runs-on: ubuntu-latest
needs: [validate, verify-tag]
timeout-minutes: 5
permissions:
contents: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Resolve tag ref
id: tag
shell: bash
run: |
if [ -n "${{ github.event.inputs.tag }}" ]; then
echo "ref=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT"
else
echo "ref=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
fi
- name: Create release with auto-generated notes
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
TAG="${{ steps.tag.outputs.ref }}"
# If the release already exists, leave it alone — re-runs should be idempotent.
if gh release view "$TAG" > /dev/null 2>&1; then
echo "Release $TAG already exists; skipping creation."
{
echo "### Release"
echo ""
echo "- Existing release for \`$TAG\` left unchanged"
} >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
gh release create "$TAG" \
--title "$TAG" \
--generate-notes \
--verify-tag
{
echo "### Release"
echo ""
echo "- Created GitHub release \`$TAG\`"
} >> "$GITHUB_STEP_SUMMARY"