Skip to content

Commit cdad391

Browse files
committed
fix(ci): build and verify packaged third-party artifacts before publish
1 parent 21daed1 commit cdad391

7 files changed

Lines changed: 144 additions & 11 deletions

File tree

.github/workflows/ci.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,31 @@ jobs:
152152
if: always()
153153
run: rm -rf "$EXPO_WORK_DIR"
154154

155+
verify-packaged-artifacts:
156+
runs-on: macos-latest
157+
158+
steps:
159+
- name: Checkout
160+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
161+
162+
- name: Setup
163+
uses: ./.github/actions/setup
164+
165+
- name: Install Zig
166+
uses: ./.github/actions/setup-zig
167+
168+
- name: Build Zig prebuilts for Android
169+
run: ./scripts/build-zig-android.sh
170+
171+
- name: Build Zig prebuilts for iOS
172+
run: ./scripts/build-zig-ios.sh
173+
174+
- name: Build package
175+
run: yarn prepare
176+
177+
- name: Verify packaged artifacts
178+
run: yarn check:packaged-artifacts
179+
155180
build-android:
156181
runs-on: ubuntu-latest
157182

.github/workflows/manual-publish.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55

66
jobs:
77
publish:
8-
runs-on: ubuntu-latest
8+
runs-on: macos-latest
99
permissions:
1010
contents: read
1111
id-token: write
@@ -17,8 +17,11 @@ jobs:
1717
registry-url: 'https://registry.npmjs.org'
1818
cache: 'yarn'
1919
- run: corepack enable
20+
- name: Init submodules
21+
run: git submodule update --init --recursive
22+
- name: Install Zig
23+
uses: ./.github/actions/setup-zig
2024
- run: yarn install --immutable
21-
- run: yarn prepare
2225
- name: Ensure version not already on npm
2326
run: |
2427
NAME="$(node -p "require('./package.json').name")"
@@ -27,6 +30,13 @@ jobs:
2730
echo "::error::${NAME}@${VER} already exists on npm"
2831
exit 1
2932
fi
33+
- name: Build Zig prebuilts for Android
34+
run: ./scripts/build-zig-android.sh
35+
- name: Build Zig prebuilts for iOS
36+
run: ./scripts/build-zig-ios.sh
37+
- run: yarn prepare
38+
- name: Verify packaged artifacts
39+
run: yarn check:packaged-artifacts
3040
- name: Publish
3141
env:
3242
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.github/workflows/npm-publish.yml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66

77
jobs:
88
publish:
9-
runs-on: ubuntu-latest
9+
runs-on: macos-latest
1010
permissions:
1111
contents: read
1212
id-token: write
@@ -26,12 +26,15 @@ jobs:
2626
cache: 'yarn'
2727
- run: corepack enable
2828

29+
- name: Init submodules
30+
run: git submodule update --init --recursive
31+
32+
- name: Install Zig
33+
uses: ./.github/actions/setup-zig
34+
2935
- name: Install deps (Yarn 4 workspaces)
3036
run: yarn install --immutable
3137

32-
- name: Build (bob via prepare)
33-
run: yarn prepare
34-
3538
- name: Ensure version not already on npm
3639
run: |
3740
NAME="$(node -p "require('./package.json').name")"
@@ -41,6 +44,18 @@ jobs:
4144
exit 1
4245
fi
4346
47+
- name: Build Zig prebuilts for Android
48+
run: ./scripts/build-zig-android.sh
49+
50+
- name: Build Zig prebuilts for iOS
51+
run: ./scripts/build-zig-ios.sh
52+
53+
- name: Build package (bob via prepare)
54+
run: yarn prepare
55+
56+
- name: Verify packaged artifacts
57+
run: yarn check:packaged-artifacts
58+
4459
- name: Publish to npm
4560
env:
4661
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ Notes
7676

7777
## v1.1.1 – bundle native sources (XXH3/BLAKE3, HMAC/keyed)
7878

79-
## Fix
79+
### Fix
8080

8181
- Bundled native sources (xxhash/blake3) in the npm package so iOS builds no longer fail with `xxhash.h file not found` and the TurboModule registers correctly.
8282

83-
## Reminder (from 1.1.0)
83+
### Reminder (from 1.1.0)
8484

8585
- Native **XXH3-64/XXH3-128** and **BLAKE3** on iOS/Android.
8686
- `hashString(text, algorithm, encoding?, options?)` for small payloads (utf8/base64); for real files use `fileHash` (streams from disk).
@@ -89,7 +89,7 @@ Notes
8989
- Example app: hash file/string, switch modes, test utf8/hex/base64 keys. Migrated to `create-react-native-library` template (TurboModule, new/old arch).
9090
- README: algorithm table, output lengths, thread-safety note, submodule reminder.
9191

92-
## Notes
92+
### Notes
9393

9494
- After clone: `git submodule update --init --recursive`.
9595
- Tests: `yarn test`.

CONTRIBUTING.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,17 +186,24 @@ xcrun simctl install "$SIMULATOR_ID" "$APP_PATH"
186186
MAESTRO_CLI_NO_ANALYTICS=1 maestro --device "$SIMULATOR_ID" test -e APP_ID="$APP_ID" .maestro/runtime-zig-smoke-ios.yaml
187187
```
188188

189+
### Package validation
190+
191+
Before publishing a release, run `yarn check:packaged-artifacts` from the repository root.
192+
This verifies that the npm tarball contains all required packaged third-party artifacts for both `native` and `zig` builds.
193+
189194
### Release checklist
190195

191-
Before publishing a release, run all four local Maestro smoke commands from the section above:
196+
Before publishing a release, run the packaging check and all four local Maestro smoke commands:
192197

198+
- `yarn check:packaged-artifacts`
193199
- Android / native
194200
- Android / zig
195201
- iOS / native
196202
- iOS / zig
197203

198204
Maestro smoke is intentionally not part of GitHub Actions CI for this repository.
199205
Hosted emulator/simulator runs were too slow and too flaky, so these checks are kept local before release.
206+
The packaged-artifacts check does run in CI, because it is deterministic and must fail before any broken npm publish.
200207

201208
### Commit message convention
202209

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
"compare:size:ios": "bash scripts/compare-size-ios.sh",
4848
"test": "jest",
4949
"test:e2e:maestro:native": "bash scripts/maestro-runtime-smoke.sh native",
50-
"test:e2e:maestro:zig": "bash scripts/maestro-runtime-smoke.sh zig"
50+
"test:e2e:maestro:zig": "bash scripts/maestro-runtime-smoke.sh zig",
51+
"check:packaged-artifacts": "bash scripts/check-packed-prebuilts.sh"
5152
},
5253
"keywords": [
5354
"react-native",

scripts/check-packed-prebuilts.sh

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5+
TMP_DIR="$(mktemp -d)"
6+
cleanup() {
7+
rm -rf "${TMP_DIR}"
8+
}
9+
trap cleanup EXIT
10+
11+
usage() {
12+
echo "Usage: $0 [path-to-tarball]" >&2
13+
}
14+
15+
if [[ $# -gt 1 ]]; then
16+
usage
17+
exit 1
18+
fi
19+
20+
if [[ $# -eq 1 ]]; then
21+
TARBALL="$1"
22+
else
23+
TARBALL_NAME="$(cd "${ROOT_DIR}" && npm pack --silent --ignore-scripts --pack-destination "${TMP_DIR}" | tail -n1)"
24+
TARBALL="${TMP_DIR}/${TARBALL_NAME}"
25+
fi
26+
27+
if [[ ! -f "${TARBALL}" ]]; then
28+
echo "Tarball not found: ${TARBALL}" >&2
29+
exit 1
30+
fi
31+
32+
REQUIRED_PATHS=$(cat <<'EOF'
33+
package/app.plugin.js
34+
package/FileHash.podspec
35+
package/third_party/xxhash/xxhash.c
36+
package/third_party/xxhash/xxhash.h
37+
package/third_party/blake3/c/blake3.c
38+
package/third_party/blake3/c/blake3.h
39+
package/third_party/blake3/c/blake3_dispatch.c
40+
package/third_party/blake3/c/blake3_impl.h
41+
package/third_party/blake3/c/blake3_portable.c
42+
package/third_party/blake3/c/blake3_neon.c
43+
package/third_party/zig-files-hash/build.zig.zon
44+
package/third_party/zig-files-hash/src/zig_files_hash_c_api.h
45+
package/third_party/zig-files-hash-prebuilt/android/arm64-v8a/libzig_files_hash.a
46+
package/third_party/zig-files-hash-prebuilt/android/armeabi-v7a/libzig_files_hash.a
47+
package/third_party/zig-files-hash-prebuilt/android/x86/libzig_files_hash.a
48+
package/third_party/zig-files-hash-prebuilt/android/x86_64/libzig_files_hash.a
49+
package/third_party/zig-files-hash-prebuilt/ios/ZigFilesHash.xcframework/Info.plist
50+
package/third_party/zig-files-hash-prebuilt/ios/ZigFilesHash.xcframework/ios-arm64/libzig_files_hash.a
51+
package/third_party/zig-files-hash-prebuilt/ios/ZigFilesHash.xcframework/ios-arm64_x86_64-simulator/libzig_files_hash.a
52+
EOF
53+
)
54+
55+
CONTENTS_FILE="${TMP_DIR}/tar-contents.txt"
56+
tar -tf "${TARBALL}" > "${CONTENTS_FILE}"
57+
58+
missing=()
59+
while IFS= read -r path; do
60+
[[ -n "${path}" ]] || continue
61+
if ! grep -Fxq "${path}" "${CONTENTS_FILE}"; then
62+
missing+=("${path}")
63+
fi
64+
done <<EOF
65+
${REQUIRED_PATHS}
66+
EOF
67+
68+
if (( ${#missing[@]} > 0 )); then
69+
echo "Packaged tarball is missing required artifacts:" >&2
70+
printf ' - %s
71+
' "${missing[@]}" >&2
72+
exit 1
73+
fi
74+
75+
echo "Verified packaged artifacts in: ${TARBALL}"

0 commit comments

Comments
 (0)