forked from gsd-build/gsd-2
-
Notifications
You must be signed in to change notification settings - Fork 0
295 lines (265 loc) · 11.1 KB
/
build-native.yml
File metadata and controls
295 lines (265 loc) · 11.1 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
name: Build Native Binaries
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
publish:
description: "Publish platform packages to npm"
required: false
default: "false"
type: choice
options:
- "false"
- "true"
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: macos-14
target: aarch64-apple-darwin
platform: darwin-arm64
- os: macos-14
target: x86_64-apple-darwin
platform: darwin-x64
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
platform: linux-x64-gnu
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
platform: linux-arm64-gnu
cross: true
- os: windows-latest
target: x86_64-pc-windows-msvc
platform: win32-x64-msvc
runs-on: ${{ matrix.os }}
name: Build ${{ matrix.platform }}
steps:
- uses: actions/checkout@v6
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Add Rust compilation target
run: rustup target add ${{ matrix.target }}
- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
shared-key: native-${{ matrix.platform }}
workspaces: |
native -> target
- name: Install cross-compilation tools (Linux ARM64)
if: matrix.cross
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
- name: Build native addon
working-directory: native/crates/engine
env:
# CARGO_ENCODED_RUSTFLAGS overrides target-specific rustflags in
# .cargo/config.toml, which sets -C target-cpu=native for dev builds.
# CI must produce portable binaries.
CARGO_ENCODED_RUSTFLAGS: ""
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: ${{ matrix.cross && 'aarch64-linux-gnu-gcc' || '' }}
run: cargo build --release --target ${{ matrix.target }}
- name: Prepare artifact (Unix)
if: runner.os != 'Windows'
run: |
mkdir -p artifacts
cp native/target/${{ matrix.target }}/release/libwtf_engine.dylib artifacts/wtf_engine.node 2>/dev/null || \
cp native/target/${{ matrix.target }}/release/libwtf_engine.so artifacts/wtf_engine.node 2>/dev/null || \
{ echo "::error::No library found for ${{ matrix.platform }}"; exit 1; }
ls -la artifacts/
- name: Prepare artifact (Windows)
if: runner.os == 'Windows'
run: |
mkdir artifacts
copy native\target\${{ matrix.target }}\release\wtf_engine.dll artifacts\wtf_engine.node
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: native-${{ matrix.platform }}
path: artifacts/wtf_engine.node
if-no-files-found: error
publish:
needs: build
if: startsWith(github.ref, 'refs/tags/v') || github.event.inputs.publish == 'true'
runs-on: blacksmith-4vcpu-ubuntu-2404
name: Publish platform packages
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Copy binaries to platform packages
run: |
for platform in darwin-arm64 darwin-x64 linux-x64-gnu linux-arm64-gnu win32-x64-msvc; do
cp "artifacts/native-${platform}/wtf_engine.node" "native/npm/${platform}/wtf_engine.node"
echo "Copied binary for ${platform}"
ls -la "native/npm/${platform}/"
done
- name: Sync platform package versions
run: node native/scripts/sync-platform-versions.cjs
- name: Detect prerelease version
id: version-check
run: |
VERSION=$(node -p "require('./package.json').version")
if echo "$VERSION" | grep -q '-next\.'; then
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
echo "tag_flag=--tag next" >> "$GITHUB_OUTPUT"
echo "Prerelease detected: ${VERSION} → publishing with --tag next"
else
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
echo "tag_flag=" >> "$GITHUB_OUTPUT"
echo "Stable release: ${VERSION} → publishing with --tag latest (default)"
fi
- name: Publish platform packages
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
for platform in darwin-arm64 darwin-x64 linux-x64-gnu linux-arm64-gnu win32-x64-msvc; do
echo "Publishing @igouss/engine-${platform}..."
cd "native/npm/${platform}"
OUTPUT=$(npm publish --access public ${{ steps.version-check.outputs.tag_flag }} 2>&1) && echo "$OUTPUT" || {
if echo "$OUTPUT" | grep -q "cannot publish over the previously published"; then
echo "Already published, skipping"
else
echo "::error::Failed to publish ${platform}: $OUTPUT"
exit 1
fi
}
cd "$GITHUB_WORKSPACE"
done
- name: Verify platform packages are published
run: |
VERSION=$(node -p "require('./package.json').version")
echo "Verifying platform packages at version ${VERSION}..."
# Exponential backoff: 5s, 10s, 20s, 30s, 30s (max 5 attempts, ~95s worst case vs fixed 30s + single check)
DELAY=5
for attempt in $(seq 1 5); do
FAILED=0
for platform in darwin-arm64 darwin-x64 linux-x64-gnu linux-arm64-gnu win32-x64-msvc; do
PKG="@igouss/engine-${platform}"
PUBLISHED=$(npm view "${PKG}@${VERSION}" version 2>/dev/null || echo "")
if [ "${PUBLISHED}" != "${VERSION}" ]; then
FAILED=1
break
fi
done
if [ "${FAILED}" = "0" ]; then
echo "All platform packages verified (attempt ${attempt})."
break
fi
if [ "$attempt" = "5" ]; then
echo "::error::One or more platform packages not found after 5 attempts. Aborting."
for platform in darwin-arm64 darwin-x64 linux-x64-gnu linux-arm64-gnu win32-x64-msvc; do
PKG="@igouss/engine-${platform}"
PUBLISHED=$(npm view "${PKG}@${VERSION}" version 2>/dev/null || echo "")
if [ "${PUBLISHED}" = "${VERSION}" ]; then
echo " ✓ ${PKG}@${VERSION}"
else
echo " ✗ ${PKG}@${VERSION} (got: '${PUBLISHED}')"
fi
done
exit 1
fi
echo " Attempt ${attempt}: not all packages visible yet, retrying in ${DELAY}s..."
sleep "$DELAY"
DELAY=$((DELAY * 2))
if [ "$DELAY" -gt 30 ]; then DELAY=30; fi
done
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Verify dist exists
run: test -s dist/loader.js || { echo "::error::dist/loader.js missing or empty after build"; exit 1; }
- name: Validate package is installable
run: npm run validate-pack
- name: Publish main package
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
# --ignore-scripts: skip prepublishOnly since we built explicitly above
OUTPUT=$(npm publish --ignore-scripts ${{ steps.version-check.outputs.tag_flag }} 2>&1) && echo "$OUTPUT" || {
if echo "$OUTPUT" | grep -q "cannot publish over the previously published\|You cannot publish over"; then
echo "Already published, skipping"
else
echo "$OUTPUT"
exit 1
fi
}
- name: Post-publish smoke test
run: |
VERSION=$(node -p "require('./package.json').version")
TMPDIR=$(mktemp -d)
cd "$TMPDIR"
npm init -y > /dev/null 2>&1
# Wait for npm registry with exponential backoff (5s, 10s, 20s, 30s, 30s, 30s, 30s — max ~155s vs fixed 5min)
echo "Waiting for wtf-pi@${VERSION} to appear on npm..."
DELAY=5
for attempt in $(seq 1 8); do
PUBLISHED=$(npm view "wtf-pi@${VERSION}" version 2>/dev/null || echo "")
if [ "${PUBLISHED}" = "${VERSION}" ]; then
echo " ✓ Version ${VERSION} visible on npm (attempt ${attempt})"
break
fi
if [ "$attempt" = "8" ]; then
echo "::warning::wtf-pi@${VERSION} not visible on npm after 8 attempts — skipping smoke test"
exit 0
fi
echo " Attempt ${attempt}: not yet visible, retrying in ${DELAY}s..."
sleep "$DELAY"
DELAY=$((DELAY * 2))
if [ "$DELAY" -gt 30 ]; then DELAY=30; fi
done
# Install and verify with backoff (5s, 10s, 20s)
echo "Installing wtf-pi@${VERSION}..."
DELAY=5
for attempt in 1 2 3; do
if npm install "wtf-pi@${VERSION}" 2>&1 | tee /tmp/install-output.txt; then
echo " ✓ Install succeeded"
RAW=$(node node_modules/wtf-pi/dist/loader.js --version 2>&1 || echo "FAILED")
ACTUAL=$(echo "$RAW" | sed 's/\x1b\[[0-9;]*m//g' | grep -oE "^${VERSION}$" | head -1)
if [ "$ACTUAL" = "$VERSION" ]; then
echo " ✓ wtf --version = ${VERSION}"
echo "Published package is functional"
exit 0
else
echo "::error::Version mismatch: expected ${VERSION} in output:"
echo "$RAW"
exit 1
fi
fi
echo "Install attempt ${attempt}/3 failed, retrying in ${DELAY}s..."
cat /tmp/install-output.txt
sleep "$DELAY"
DELAY=$((DELAY * 2))
done
echo "::error::Smoke test failed — wtf-pi@${VERSION} not installable"
exit 1
- name: Verify dist-tag after publish
if: steps.version-check.outputs.is_prerelease == 'false'
run: |
VERSION=$(node -p "require('./package.json').version")
echo "Verifying npm dist-tag 'latest' points to ${VERSION}..."
DELAY=5
for attempt in $(seq 1 6); do
LATEST=$(npm view wtf-pi dist-tags.latest 2>/dev/null || echo "")
if [ "${LATEST}" = "${VERSION}" ]; then
echo " ✓ npm dist-tags.latest = ${VERSION}"
exit 0
fi
echo " Attempt ${attempt}/6: latest=${LATEST}, expected=${VERSION}, retrying in ${DELAY}s..."
sleep "$DELAY"
DELAY=$((DELAY * 2))
if [ "$DELAY" -gt 30 ]; then DELAY=30; fi
done
echo "::error::dist-tags.latest is '${LATEST}' but expected '${VERSION}' — run: npm dist-tag add wtf-pi@${VERSION} latest"
exit 1