-
-
Notifications
You must be signed in to change notification settings - Fork 19
188 lines (176 loc) · 8.32 KB
/
Copy pathnpm_release.yml
File metadata and controls
188 lines (176 loc) · 8.32 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
# Publishes the @nativescript/canvas suite to npm from an existing release tag.
#
# Native artifacts (Android AAR + iOS xcframework) are committed under
# packages/canvas/platforms, so this is a publish-only workflow: it checks out
# the tag, builds the JS packages, and publishes each at the version committed
# in its package.json. No Rust/native rebuild.
#
# iOS SwiftPM distribution: canvas and audio-context each ship the header-only
# NativeScriptV8 SwiftPM shim (repo-root nativescript-v8/) INSIDE the npm
# package at platforms/ios/NativeScriptV8, referenced by their
# nativescript.config.ts as a local `path` package. Unlike font-manager, there
# is no GitHub-release binaryTarget to stamp: SwiftPM clones a repository's
# entire git history just to read Package.swift, and this repo's history is
# several GB — so ANY repositoryURL reference (source or binary target) stalls
# first builds for 20+ minutes. The shim is tiny (V8 headers + empty stub) and
# the heavy CanvasNative.xcframework already ships in the npm package, so
# nothing needs a release asset. The verify step below guards that the shim
# actually made it into the built packages.
#
# Authentication uses npm Trusted Publishing (OIDC) — no NPM_TOKEN required.
# This mirrors the proven publish flow in the @nativescript/ios and
# @nativescript/font-manager repos:
# * the job runs in the `npm-publish` environment, which MUST match the
# environment configured on the npm Trusted Publisher for EACH package
# (repo NativeScript/canvas + workflow npm_release.yml + env npm-publish).
# A Trusted Publisher must be configured on npmjs.com for every package
# listed in PACKAGES below, or its publish is rejected (404/ENEEDAUTH).
# * npm is upgraded to 11.5.1 via corepack (Trusted Publishing needs >=11.5.1;
# `npm i -g npm@latest` corrupts the global install and drops bundled deps
# like sigstore — npm/cli#9722).
# * the .npmrc that setup-node writes is removed and NODE_AUTH_TOKEN cleared
# before publish so an empty token can't shadow the OIDC exchange.
name: npm Release
on:
workflow_dispatch:
inputs:
version:
description: 'Release tag to publish from (e.g. 2.1.2). Must be an existing git tag. Defaults to packages/canvas/package.json version.'
required: false
type: string
concurrency:
group: npm-release
cancel-in-progress: false
jobs:
publish:
runs-on: ubuntu-latest
environment: npm-publish # must match the npm Trusted Publisher environment
permissions:
contents: read
id-token: write # required for npm Trusted Publishing (OIDC) + provenance
env:
# Single source of truth for the packages to publish (space separated).
PACKAGES: 'audio-context canvas canvas-babylon canvas-chartjs canvas-media canvas-phaser canvas-phaser-ce canvas-pixi canvas-polyfill canvas-svg canvas-three'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Resolve version
id: version
run: |
VERSION="${{ github.event.inputs.version }}"
if [ -z "$VERSION" ]; then
VERSION="$(node -p "require('./packages/canvas/package.json').version")"
fi
if ! git rev-parse -q --verify "refs/tags/$VERSION^{commit}" > /dev/null; then
echo "error: tag $VERSION not found — create and push the release tag first" >&2
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Checkout release tag
run: git checkout "refs/tags/${{ steps.version.outputs.version }}"
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: 'https://registry.npmjs.org'
- name: Update npm (required for OIDC trusted publishing)
run: |
corepack enable npm
corepack install -g npm@11.5.1
test "$(npm --version)" = "11.5.1"
# canvas commits no lockfile, so `npm install` (not `npm ci`).
- name: Install dependencies
run: npm install
- name: Build packages
run: npx nx run-many --target=build.all --projects="$(echo "$PACKAGES" | tr ' ' ',')"
# The iOS SwiftPM shim must ship inside the npm packages that declare a
# local-path SPM package in their nativescript.config.ts — if it's
# missing, every consumer's Xcode resolution fails (or worse, someone
# "fixes" it by reverting to a repositoryURL reference and reintroduces
# the 20+ minute full-history clone).
- name: Verify iOS SwiftPM shim in built packages
run: |
set -euo pipefail
for pkg in canvas audio-context; do
dir="dist/packages/$pkg/platforms/ios/NativeScriptV8"
for required in "$dir/Package.swift" "$dir/Headers" "$dir/Sources"; do
if [ ! -e "$required" ]; then
echo "error: $required missing — the NativeScriptV8 SPM shim was not packaged" >&2
exit 1
fi
done
# match only a real `repositoryURL:` key — the config's comments
# legitimately mention the word while explaining why it's banned
if grep -v -E '^[[:space:]]*(//|\*)' "dist/packages/$pkg/nativescript.config.ts" | grep -q -E 'repositoryURL[[:space:]]*:'; then
echo "error: dist/packages/$pkg/nativescript.config.ts declares a repositoryURL — plugin SPM packages must use a local path (full-history clone is 8+ GB)" >&2
exit 1
fi
echo "ok: $pkg ships the NativeScriptV8 shim with a local-path config"
done
if [ ! -d dist/packages/canvas/platforms/ios/CanvasNative.xcframework ]; then
echo "error: CanvasNative.xcframework missing from dist/packages/canvas" >&2
exit 1
fi
# Publish each package at its committed version via OIDC. The setup-node
# .npmrc and NODE_AUTH_TOKEN are cleared so npm performs the Trusted
# Publishing token exchange (per package) and generates provenance.
# Versions already on npm are skipped so the run is re-runnable and one
# unchanged package can't fail the whole release.
- name: Publish packages (OIDC trusted publishing)
env:
NODE_AUTH_TOKEN: ''
run: |
set -euo pipefail
unset NODE_AUTH_TOKEN
if [ -n "${NPM_CONFIG_USERCONFIG:-}" ]; then
rm -f "$NPM_CONFIG_USERCONFIG"
fi
published=""
skipped=""
for pkg in $PACKAGES; do
dir="dist/packages/$pkg"
if [ ! -f "$dir/package.json" ]; then
echo "error: $dir/package.json not found (build missing?)" >&2
exit 1
fi
name="$(node -p "require('./$dir/package.json').name")"
ver="$(node -p "require('./$dir/package.json').version")"
# dist-tag: prerelease label if the version has one, else latest
if [ "$ver" != "${ver#*-}" ]; then
tag="$(printf '%s' "${ver#*-}" | cut -d. -f1)"
else
tag="latest"
fi
if [ "$(npm view "$name@$ver" version 2>/dev/null || true)" = "$ver" ]; then
echo "==> $name@$ver already published — skipping"
skipped="$skipped $name@$ver"
continue
fi
echo "==> publishing $name@$ver (tag: $tag)"
( cd "$dir" && npm publish --access public --provenance --tag "$tag" )
published="$published $name@$ver"
done
echo ""
echo "published:${published:- none}"
echo "skipped:${skipped:- none}"
- name: Verify npm publish
run: |
set -euo pipefail
for pkg in $PACKAGES; do
name="$(node -p "require('./dist/packages/$pkg/package.json').name")"
ver="$(node -p "require('./dist/packages/$pkg/package.json').version")"
ok=false
for i in $(seq 1 10); do
if [ "$(npm view "$name@$ver" version 2>/dev/null || true)" = "$ver" ]; then
echo "ok: $name@$ver is live"
ok=true
break
fi
echo " $name@$ver not visible yet, retrying ($i/10)..."
sleep 15
done
if [ "$ok" != true ]; then
echo "error: $name@$ver not visible on the registry" >&2
exit 1
fi
done