Repository navigation
297 lines (256 loc) · 10.6 KB
/
Copy pathrelease.yml
File metadata and controls
297 lines (256 loc) · 10.6 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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
name: Release
on:
workflow_dispatch:
inputs:
version:
description: 'Version bump type'
required: true
type: choice
options:
- patch
- minor
- major
- prepatch
- preminor
- premajor
- prerelease
preid:
description: 'Pre-release identifier (e.g. alpha, beta, rc). Only used with pre* version types.'
required: false
default: 'alpha'
type: string
tag:
description: 'npm dist-tag'
required: true
type: choice
options:
- latest
- alpha
- beta
- rc
# One release at a time, shared with release-manual.yml. No
# `cancel-in-progress`: a cancelled run can leave a version on npm with no tag.
concurrency:
group: release
cancel-in-progress: false
jobs:
# The compat matrix gates the publish. compat.yml runs on push and pull
# request only, so without this job a release can ship from a commit whose
# matrix was red, or never ran. The candidate is the tree as dispatched,
# before the version bump; the bump changes the version field and the
# `@rootnative/core` floor, nothing the fixtures install differently.
pack:
name: Pack candidate
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup pnpm
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
- name: Setup Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version-file: .nvmrc
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
# components ships `dist` only, so the tarball must be built before it
# is packed.
- name: Build
run: pnpm run build
# Pack from the package directory; it works the same on every pnpm version.
- name: Pack components
working-directory: packages/components
run: pnpm pack --pack-destination ../../pack
- name: Upload candidate
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: release-candidate-components
path: pack/*.tgz
if-no-files-found: error
retention-days: 1
# A push to main during this run starts compat.yml, and the two matrix runs
# share one concurrency group in sdk-compat. If this job is cancelled, re-run
# the release.
compat:
name: Matrix
needs: pack
uses: rootnative/sdk-compat/.github/workflows/compat.yml@main
with:
package: '@rootnative/components'
tarball-artifact: release-candidate-components
enforce-range: true
release:
name: Release
needs: compat
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version-file: .nvmrc
registry-url: https://registry.npmjs.org
- name: Setup pnpm
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Format check
run: pnpm run format:check
- name: Lint
run: pnpm run lint
- name: Typecheck
run: pnpm run typecheck
- name: Test
run: pnpm run test
- name: Docs check
run: pnpm run docs:check
# `check-inertia-pins` reads the registry but only compares the inertia
# floor in each entry, so the `files` lists were unguarded: 21 of 29 were
# missing internal/pointerEvents.ts after somebody added the import
# without re-running the generator. The registry is what `rootnative add`
# copies into a consumer project, so a stale list hands them a component
# with a missing import. Needs no build.
- name: Registry drift check
run: pnpm run registry:check
- name: Inertia pin check
run: pnpm run check:inertia-pins
# The templates are not workspace members, so no install, typecheck or
# test run ever reads their pins. They sat a whole Expo SDK behind the
# library and every gate stayed green. Needs no build.
- name: Template pin check
run: pnpm run check:template-pins
# The mark and the docs accent tokens hold the same hex values in two
# files; the palette comment declares the CSS as the follower and nothing
# checked it, so both themes had drifted by one rung of the ramp while the
# token was unreferenced. Needs no build.
- name: Brand accent check
run: pnpm run check:brand-accent
- name: Build
run: pnpm run build
# Everything from here to `Configure git` mirrors the post-build gates in
# ci.yml, and the mirroring is load-bearing: these five checks read the
# built output, which is the only place their failure modes are
# observable. Releasing without them is how alpha.10 and alpha.11 shipped
# with every animated component dead on native — the worklet check existed
# in CI, but the release path never ran it, so a green CI on main said
# nothing about the artifact actually being published.
#
# Keep this list in sync with ci.yml. A guard that runs on PRs but not on
# release protects the branch and not the users.
- name: API surface
run: npx tsx scripts/build-api-surface.ts --check
- name: Singleton check
run: pnpm run check:singletons
- name: Worklet check
run: pnpm run check:worklets
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Discover public packages
id: packages
run: |
# Find all non-private packages under packages/
PUBLIC_PKGS=$(node -e "
const fs = require('fs');
const path = require('path');
const dirs = fs.readdirSync('packages', { withFileTypes: true })
.filter(d => d.isDirectory())
.map(d => d.name)
.filter(name => {
const pkgPath = path.join('packages', name, 'package.json');
if (!fs.existsSync(pkgPath)) return false;
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
return pkg.private !== true;
});
console.log(dirs.join(' '));
")
echo "packages=$PUBLIC_PKGS" >> "$GITHUB_OUTPUT"
echo "Discovered public packages: $PUBLIC_PKGS"
- name: Bump versions
id: version
run: |
VERSION_ARGS="${{ inputs.version }}"
if [[ "$VERSION_ARGS" == pre* ]]; then
VERSION_ARGS="$VERSION_ARGS --preid ${{ inputs.preid }}"
fi
NEW_VERSION=""
for PKG_DIR in ${{ steps.packages.outputs.packages }}; do
(cd "packages/$PKG_DIR" && npm version $VERSION_ARGS --no-git-tag-version)
if [ -z "$NEW_VERSION" ]; then
NEW_VERSION=$(node -p "require('./packages/$PKG_DIR/package.json').version")
fi
done
# Update @rootnative/core peer dep in any package that references it
for PKG_DIR in ${{ steps.packages.outputs.packages }}; do
node -e "
const fs = require('fs');
const pkgPath = 'packages/$PKG_DIR/package.json';
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
if (pkg.peerDependencies?.['@rootnative/core']) {
pkg.peerDependencies['@rootnative/core'] = '>=$NEW_VERSION';
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
}
"
done
# Update lockfile after version bumps
pnpm install --no-frozen-lockfile
echo "version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
- name: Regenerate LLM docs with new versions
run: npx tsx scripts/build-llms.ts
# The registry derives its `@rootnative/core` floor from the components
# peer range, which the bump above just moved — so it is generated output
# that goes stale on every release unless it is regenerated here. It was:
# alpha.10 and alpha.11 both shipped a registry still claiming
# `>=0.0.0-alpha.9`, because only `llms.txt` was regenerated. The CLI
# fetches `registry/index.json` from the release tag, so a stale floor
# reaches every scaffolded project.
- name: Regenerate registry with new versions
run: npx tsx scripts/build-registry.ts
- name: Commit and tag
run: |
git add pnpm-lock.yaml
git add packages/*/llms.txt docs/static/llms-full.txt
git add registry
for PKG_DIR in ${{ steps.packages.outputs.packages }}; do
git add "packages/$PKG_DIR/package.json"
done
git commit -m "release: v${{ steps.version.outputs.version }}"
git tag "v${{ steps.version.outputs.version }}"
# Push before publish. See the note in release-manual.yml.
- name: Push to main
run: |
git push origin main
git push origin "v${{ steps.version.outputs.version }}"
- name: Publish packages
run: |
# Publish core first (other packages may depend on it)
if [ -d packages/core ]; then
echo "Publishing @rootnative/core..."
(cd packages/core && pnpm publish --provenance --access public --tag ${{ inputs.tag }} --no-git-checks)
fi
# Publish remaining packages
for PKG_DIR in ${{ steps.packages.outputs.packages }}; do
if [ "$PKG_DIR" = "core" ]; then continue; fi
PKG_NAME=$(node -p "require('./packages/$PKG_DIR/package.json').name")
echo "Publishing $PKG_NAME..."
(cd "packages/$PKG_DIR" && pnpm publish --provenance --access public --tag ${{ inputs.tag }} --no-git-checks)
done
- name: Create GitHub Release
run: |
PRERELEASE_FLAG=""
if [[ "${{ inputs.tag }}" != "latest" ]]; then
PRERELEASE_FLAG="--prerelease"
fi
gh release create "v${{ steps.version.outputs.version }}" --generate-notes $PRERELEASE_FLAG
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}