-
Notifications
You must be signed in to change notification settings - Fork 8
312 lines (279 loc) · 11.9 KB
/
Copy pathnightly.yml
File metadata and controls
312 lines (279 loc) · 11.9 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
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
name: Nightly release
on:
push:
branches:
- "**"
tags:
- "!**"
pull_request:
branches:
- main
workflow_dispatch:
inputs:
skip_build:
description: "Skip the build-napi job. Requires napi_run_id."
type: boolean
default: false
skip_release:
description: "Skip the release (publish) job; only build NAPI artifacts."
type: boolean
default: false
napi_run_id:
description: "Existing run ID to download NAPI artifacts from (only used when skip_build is true)."
type: string
default: ""
permissions:
contents: read
actions: read
env:
CARGO_TERM_COLOR: always
LINUX_GLIBC_VERSION: "2.17"
jobs:
build-napi:
name: Build NAPI - ${{ matrix.target }}
if: github.event_name != 'workflow_dispatch' || inputs.skip_build != true
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
target: x86_64-apple-darwin
platform: darwin-x64
- os: macos-latest
target: aarch64-apple-darwin
platform: darwin-arm64
- os: ubuntu-22.04
target: x86_64-unknown-linux-gnu
platform: linux-x64-gnu
- os: ubuntu-22.04
target: x86_64-unknown-linux-musl
platform: linux-x64-musl
- os: blacksmith-32vcpu-ubuntu-2404
target: aarch64-unknown-linux-gnu
platform: linux-arm64-gnu
- os: blacksmith-32vcpu-ubuntu-2404
target: aarch64-unknown-linux-musl
platform: linux-arm64-musl
- os: windows-latest
target: x86_64-pc-windows-msvc
platform: win32-x64-msvc
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Vite+
uses: voidzero-dev/setup-vp@250f29ce396baf5e8f24498e17c0dfdebabc26eb # v1.15.0
with:
node-version-file: ".node-version"
cache: true
run-install: true
- name: Setup Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
targets: ${{ matrix.target }}
- name: Mount sticky cache
if: startsWith(matrix.os, 'blacksmith-')
uses: ./.github/actions/mount-sticky-cache
with:
key-prefix: ${{ github.repository }}-nightly-${{ github.job }}-${{ matrix.target }}
cargo: "true"
target: target
- name: Cache cargo build
if: ${{ !startsWith(matrix.os, 'blacksmith-') }}
# zizmor: ignore[cache-poisoning] save-if restricts writes to main pushes, so PR runs cannot poison release builds.
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2.9.1
with:
shared-key: nightly-${{ matrix.target }}
# Only save cache on main pushes to prevent PR runs from poisoning the cache used by release builds.
save-if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
- name: Install zig (Linux)
if: contains(matrix.target, 'unknown-linux')
run: |
curl -fsSL https://ziglang.org/download/0.13.0/zig-linux-x86_64-0.13.0.tar.xz -o zig.tar.xz
tar -xf zig.tar.xz
echo "$PWD/zig-linux-x86_64-0.13.0" >> "$GITHUB_PATH"
- name: Install cargo-zigbuild (Linux)
if: contains(matrix.target, 'unknown-linux')
run: cargo install cargo-zigbuild
- name: Build NAPI (Linux)
if: contains(matrix.target, 'unknown-linux')
working-directory: crates/ox_content_napi
shell: bash
run: |
set -euo pipefail
build_target="${{ matrix.target }}"
if [[ "${{ matrix.target }}" == *-unknown-linux-gnu ]]; then
build_target="${build_target}.${LINUX_GLIBC_VERSION}"
else
export RUSTFLAGS="${RUSTFLAGS:-} -C target-feature=-crt-static"
fi
cargo zigbuild --release --target "$build_target"
src="../../target/${{ matrix.target }}/release/libox_content_napi.so"
if [[ ! -f "$src" ]]; then
src="../../target/${build_target}/release/libox_content_napi.so"
fi
cp "$src" "ox-content.${{ matrix.platform }}.node"
- name: Verify Linux native dependencies
if: contains(matrix.target, 'unknown-linux')
shell: bash
run: |
set -euo pipefail
node_file="crates/ox_content_napi/ox-content.${{ matrix.platform }}.node"
if [[ "${{ matrix.target }}" == *-unknown-linux-gnu ]]; then
max_glibc="$(
readelf --version-info "$node_file" |
sed -n 's/.*Name: GLIBC_\([0-9.]*\).*/\1/p' |
sort -V |
tail -1
)"
echo "max GLIBC version: ${max_glibc:-none}"
if [[ -n "$max_glibc" ]] &&
[[ "$(printf '%s\n' "$LINUX_GLIBC_VERSION" "$max_glibc" | sort -V | tail -1)" != "$LINUX_GLIBC_VERSION" ]]; then
echo "::error::${node_file} requires GLIBC_${max_glibc}, expected <= GLIBC_${LINUX_GLIBC_VERSION}"
exit 1
fi
else
if readelf --version-info "$node_file" | grep -q 'GLIBC_'; then
echo "::error::${node_file} unexpectedly references GLIBC symbols"
exit 1
fi
fi
- name: Build NAPI
if: ${{ !contains(matrix.target, 'unknown-linux') }}
working-directory: crates/ox_content_napi
run: vp exec -- napi build --release --target ${{ matrix.target }}
- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: napi-${{ matrix.target }}
path: crates/ox_content_napi/*.node
if-no-files-found: error
release:
name: Publish preview via pkg-pr-new
runs-on: blacksmith-32vcpu-ubuntu-2404
needs: build-napi
# Skip when explicitly disabled via workflow_dispatch.
# Use always() so this still runs when build-napi was skipped (skip_build mode).
if: |
always() &&
(github.event_name != 'workflow_dispatch' || inputs.skip_release != true) &&
(needs.build-napi.result == 'success' ||
(github.event_name == 'workflow_dispatch' && inputs.skip_build == true))
steps:
- name: Validate napi_run_id when skip_build is true
if: github.event_name == 'workflow_dispatch' && inputs.skip_build == true
env:
NAPI_RUN_ID: ${{ inputs.napi_run_id }}
run: |
if [ -z "$NAPI_RUN_ID" ]; then
echo "::error::napi_run_id input is required when skip_build is true."
exit 1
fi
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Vite+
uses: voidzero-dev/setup-vp@250f29ce396baf5e8f24498e17c0dfdebabc26eb # v1.15.0
with:
node-version-file: ".node-version"
cache: true
run-install: true
- name: Download artifacts (same run)
if: github.event_name != 'workflow_dispatch' || inputs.skip_build != true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: napi-*
path: crates/ox_content_napi/artifacts
- name: Download artifacts (from previous run)
if: github.event_name == 'workflow_dispatch' && inputs.skip_build == true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: napi-*
path: crates/ox_content_napi/artifacts
run-id: ${{ inputs.napi_run_id }}
github-token: ${{ github.token }}
# napi-cli 3.8 rejects managed paths that escape the boundary it discovers
# from its cwd, so point --cwd at the workspace root and keep every path
# relative to it. `binding-packages` then resolves inside the pnpm
# workspace instead of escaping the crate directory.
- name: Create npm sub-package directories
working-directory: crates/ox_content_napi
run: >-
vp exec -- napi create-npm-dirs --cwd ../..
--package-json-path crates/ox_content_napi/package.json
--npm-dir binding-packages
- name: Move artifacts to sub-packages
working-directory: crates/ox_content_napi
run: |
declare -A target_map=(
["x86_64-apple-darwin"]="darwin-x64"
["aarch64-apple-darwin"]="darwin-arm64"
["x86_64-unknown-linux-gnu"]="linux-x64-gnu"
["x86_64-unknown-linux-musl"]="linux-x64-musl"
["aarch64-unknown-linux-gnu"]="linux-arm64-gnu"
["aarch64-unknown-linux-musl"]="linux-arm64-musl"
["x86_64-pc-windows-msvc"]="win32-x64-msvc"
)
for dir in artifacts/napi-*; do
target="${dir##*/napi-}"
platform="${target_map[$target]}"
if [ -n "$platform" ]; then
for f in "$dir"/*.node; do
cp "$f" "../../binding-packages/${platform}/ox-content.${platform}.node"
done
fi
done
echo "=== Verify binding packages ==="
for pkg in ../../binding-packages/*/; do
ls -la "$pkg"*.node 2>/dev/null || echo "WARNING: No .node file in $pkg"
done
# Same step as publish.yml: rewrite the main package's
# optionalDependencies to reference the binding sub-packages.
# Without this, consumers installing @ox-content/napi cannot
# resolve the matching binding. --skip-optional-publish tells
# napi-cli not to publish the optional sub-packages itself
# (pkg-pr-new handles that downstream).
- name: Update optionalDependencies (napi pre-publish)
working-directory: crates/ox_content_napi
run: >-
vp exec -- napi pre-publish -t npm --cwd ../..
--package-json-path crates/ox_content_napi/package.json
--npm-dir binding-packages --no-gh-release --skip-optional-publish
# `pnpm build` recompiles @ox-content/napi via `napi build --release`,
# so the job needs a Rust toolchain. Pin stable instead of relying on the
# runner image's preinstalled rustc: the Blacksmith image ships an older
# rustc than the oxc dependencies' MSRV (1.93).
- name: Setup Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- name: Mount sticky cache
uses: ./.github/actions/mount-sticky-cache
with:
key-prefix: ${{ github.repository }}-nightly-${{ github.job }}
cargo: "true"
target: target
- name: Build TS packages
run: vp exec -- pnpm --filter "@ox-content/*" build
- name: Publish to pkg-pr-new
id: publish-pkg-pr-new
continue-on-error: ${{ github.event_name == 'pull_request' }}
run: |
vp exec -- pnpx pkg-pr-new publish --compact --pnpm \
./crates/ox_content_napi \
./binding-packages/darwin-x64 \
./binding-packages/darwin-arm64 \
./binding-packages/linux-x64-gnu \
./binding-packages/linux-x64-musl \
./binding-packages/linux-arm64-gnu \
./binding-packages/linux-arm64-musl \
./binding-packages/win32-x64-msvc \
./npm/ox-content-islands \
./npm/unplugin-ox-content \
./npm/vite-plugin-ox-content \
./npm/vite-plugin-ox-content-react \
./npm/vite-plugin-ox-content-solid \
./npm/vite-plugin-ox-content-svelte \
./npm/vite-plugin-ox-content-vue
- name: Warn when preview publish is unavailable
if: github.event_name == 'pull_request' && steps.publish-pkg-pr-new.outcome == 'failure'
run: echo "::warning::pkg-pr-new preview publish failed; keeping pull request CI non-blocking for the external preview service."