-
Notifications
You must be signed in to change notification settings - Fork 2
226 lines (218 loc) · 8.63 KB
/
Copy pathpublish-node.yml
File metadata and controls
226 lines (218 loc) · 8.63 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
# Build and publish the @offbit-ai/reflow Node SDK.
#
# Triggers
# --------
# - Tag push matching `node-v*` (e.g. `node-v0.2.0`) → build every
# platform addon, run tests, then publish to npm.
# - Manual `workflow_dispatch` → build + test only.
#
# Publishing auth
# ---------------
# Uses an automation token stored as the `NPM_TOKEN` secret. Flip to
# npm trusted publishing (OIDC) once the first release is up.
name: publish-node
on:
push:
tags:
- 'node-v*'
workflow_dispatch:
permissions:
contents: read
jobs:
build:
name: build / ${{ matrix.settings.target }}
runs-on: ${{ matrix.settings.host }}
strategy:
fail-fast: false
matrix:
settings:
# `napi build --target X` is required on every entry, not just
# cross-builds: without it the output `.node` file lacks the
# platform suffix that `napi artifacts` looks for in publish.
- host: macos-14
target: aarch64-apple-darwin
build: npm run build -- --target aarch64-apple-darwin
# macos-13 (Intel) runners have long queue times and the x86_64
# SDK is already present on macos-14, so we cross-compile the
# Intel addon from the aarch64 runner instead.
- host: macos-14
target: x86_64-apple-darwin
build: npm run build -- --target x86_64-apple-darwin
- host: ubuntu-latest
target: x86_64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
build: npm run build -- --target x86_64-unknown-linux-gnu
- host: ubuntu-latest
target: aarch64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64
build: npm run build -- --target aarch64-unknown-linux-gnu
- host: windows-latest
target: x86_64-pc-windows-msvc
build: npm run build -- --target x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Rust toolchain
if: ${{ !matrix.settings.docker }}
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.settings.target }}
- uses: mozilla-actions/sccache-action@v0.0.5
if: ${{ !matrix.settings.docker }}
- name: Install npm deps
working-directory: sdk/node
run: npm ci || npm install
- name: Build addon (host)
if: ${{ !matrix.settings.docker }}
working-directory: sdk/node
run: ${{ matrix.settings.build }}
- name: Build addon (docker)
if: ${{ matrix.settings.docker }}
uses: addnab/docker-run-action@v3
with:
image: ${{ matrix.settings.docker }}
options: -v ${{ github.workspace }}:/build -w /build/sdk/node
# The napi-rs nodejs-rust images invoke scripts through sh
# (dash), which rejects `set -o pipefail`. `-eux` is portable.
#
# The lts-debian images ship an older Rust (1.82 at time of
# writing); reflow_network requires edition 2024, which
# stabilized in 1.85. Bump the toolchain before building.
run: |
set -eux
# rquickjs-sys's build script patches QuickJS sources with
# `patch`, which isn't installed in the napi-rs base images.
(command -v patch >/dev/null) || (apt-get update && apt-get install -y patch)
rustup update stable
rustup default stable
rustup target add ${{ matrix.settings.target }}
npm ci || npm install
${{ matrix.settings.build }}
- uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix.settings.target }}
# napi build emits the .node addon plus a small JS/TS loader
# shim (index.js / index.d.ts) that tests `require()` to find
# the right native binary. Both are gitignored, so test jobs
# need them shipped via the artifact.
path: |
sdk/node/*.node
sdk/node/index.js
sdk/node/index.d.ts
if-no-files-found: error
test:
name: test / ${{ matrix.settings.host }}
needs: build
runs-on: ${{ matrix.settings.host }}
strategy:
fail-fast: false
matrix:
settings:
- host: macos-14
target: aarch64-apple-darwin
# No macos-13 test run — cross-compiled x86_64 addon would
# need Rosetta-Node to execute, and x86_64 code paths are
# exercised by the Linux x86_64 test anyway.
- host: ubuntu-latest
target: x86_64-unknown-linux-gnu
- host: windows-latest
target: x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Download addon for host
uses: actions/download-artifact@v4
with:
name: bindings-${{ matrix.settings.target }}
path: sdk/node
- name: Install + run tests
working-directory: sdk/node
shell: bash
run: |
npm ci || npm install
npm test
publish:
name: publish to npm
needs: [build, test]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/node-v')
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: 'https://registry.npmjs.org'
- name: Install + download all addons
working-directory: sdk/node
run: npm ci || npm install
- uses: actions/download-artifact@v4
with:
path: sdk/node/artifacts
# Build the wasm32 browser bundle and stage it into sdk/node/wasm/
# so it ships inside the same `@offbit-ai/reflow` npm package.
# The `"browser"` conditional export in package.json picks this
# up when bundlers target the browser; Node imports the napi
# addon as before.
- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- uses: jetli/wasm-pack-action@v0.4.0
with:
version: latest
- name: Build browser-WASM bundle
# `--target web` emits an ES module + .wasm pair that loads
# via `await init()`. wasm-pack also writes a per-package
# `package.json` and `.gitignore` into the out-dir; we strip
# them so the wasm/ subtree doesn't shadow the parent
# package.json or look like a standalone npm package.
run: |
wasm-pack build crates/reflow_rt_wasm \
--target web \
--release \
--out-dir ../../sdk/node/wasm
rm -f sdk/node/wasm/package.json sdk/node/wasm/.gitignore
- name: Distribute addons to per-platform npm packages
working-directory: sdk/node
# `napi create-npm-dir` scaffolds `npm/<platform>/` (one
# package.json per triple in package.json's napi.triples) with
# versions already matching the main package. `napi artifacts`
# copies the per-triple `.node` files in. After this step,
# each `npm/<platform>/` is a publishable package — we then
# `npm publish` them one by one in the next step.
#
# We deliberately don't run `napi prepublish` here: in v2.18 it
# also tries to `npm publish` each platform itself, doubling up
# with our manual loop and obscuring real failures.
run: |
npx napi create-npm-dir -t .
npx napi artifacts --dir artifacts
- name: Publish platform packages
working-directory: sdk/node
# No `--provenance`: would require `id-token: write` and a
# trusted-publisher OIDC token. We use a classic NPM_TOKEN here
# which can't sign provenance attestations. Add provenance once
# the org is set up for npm trusted publishing.
#
# First-publish of a new scoped package needs the NPM_TOKEN to
# have *write access to the scope* (granular tokens scoped to
# specific packages will return 404 here). Use a classic
# Automation token, or a granular token with the full scope.
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
set -e
for dir in npm/*/; do
[ -f "$dir/package.json" ] || continue
echo "::group::publish $(basename "$dir")"
(cd "$dir" && npm publish --access public)
echo "::endgroup::"
done
- name: Publish main package
working-directory: sdk/node
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish --access public