Skip to content

Commit 19879dc

Browse files
AlexgodorojaAlex Godoroja
andauthored
fix: bundle macos on npm publish (#91)
Co-authored-by: Alex Godoroja <alex@vulturelabs.io>
1 parent a4da65b commit 19879dc

6 files changed

Lines changed: 211 additions & 71 deletions

File tree

.github/workflows/publish-node-sdk.yml

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,28 @@ name: Publish Node SDK
33
on:
44
release:
55
types: [published]
6+
workflow_dispatch:
7+
inputs:
8+
version:
9+
description: 'Version to publish (without leading v, e.g. 1.9.1)'
10+
required: true
11+
type: string
12+
prerelease:
13+
description: 'Treat as prerelease (skip publish; build only)'
14+
required: false
15+
type: boolean
16+
default: false
617

718
permissions:
819
contents: write
920
id-token: write
1021

22+
env:
23+
PILOT_VERSION: ${{ inputs.version || github.event.release.tag_name }}
24+
PILOT_PRERELEASE: ${{ inputs.prerelease || github.event.release.prerelease }}
25+
1126
jobs:
1227
test-sdk:
13-
if: "!github.event.release.prerelease"
1428
runs-on: ubuntu-latest
1529
defaults:
1630
run:
@@ -38,10 +52,10 @@ jobs:
3852
- name: Checkout repository
3953
uses: actions/checkout@v4
4054

41-
- name: Set version from release tag
55+
- name: Set version from release tag or workflow input
4256
shell: bash
4357
run: |
44-
VERSION="${{ github.event.release.tag_name }}"
58+
VERSION="${PILOT_VERSION}"
4559
VERSION="${VERSION#v}"
4660
echo "version=$VERSION" >> $GITHUB_ENV
4761
cd sdk/node
@@ -82,25 +96,63 @@ jobs:
8296
echo "Package contents:"
8397
npm pack --dry-run
8498
echo ""
85-
echo "Binary sizes:"
99+
echo "Built binary subdirs:"
86100
ls -lh bin/
87101
88-
- name: Upload package artifact
102+
# Upload only the platform-specific binary subdir; the publish job
103+
# downloads both and merges them into a single multi-platform npm package.
104+
- name: Upload platform binaries
105+
uses: actions/upload-artifact@v4
106+
with:
107+
name: node-bin-${{ matrix.platform }}
108+
path: sdk/node/bin/
109+
retention-days: 7
110+
111+
# Upload the full package layout (JS + bin/ + bin-stubs) once — the
112+
# Linux runner's copy is the publish base; macOS just contributes its
113+
# bin/ subdir to the merge.
114+
- name: Upload full package (Linux base)
115+
if: matrix.platform == 'linux'
89116
uses: actions/upload-artifact@v4
90117
with:
91-
name: npm-package-${{ matrix.platform }}
118+
name: npm-package-base
92119
path: sdk/node/
93120
retention-days: 7
94121

95122
publish:
96123
needs: build-packages
124+
if: ${{ !(inputs.prerelease || github.event.release.prerelease) }}
97125
runs-on: ubuntu-latest
98126
steps:
99-
- name: Download Linux package
127+
- name: Download package base (Linux build)
128+
uses: actions/download-artifact@v4
129+
with:
130+
name: npm-package-base
131+
path: sdk/node-pkg
132+
133+
- name: Download macOS binaries
100134
uses: actions/download-artifact@v4
101135
with:
102-
name: npm-package-linux
103-
path: sdk/node-linux
136+
name: node-bin-macos
137+
path: sdk/node-bin-macos
138+
139+
- name: Merge macOS binaries into package
140+
run: |
141+
# Linux base already contains bin/<linux subdirs>/. Layer in the
142+
# macOS subdirs so the published package is multi-platform.
143+
for sub in sdk/node-bin-macos/*/; do
144+
name=$(basename "$sub")
145+
# Skip the .pilot-version file which is at the root, not a subdir.
146+
[ "$name" = ".pilot-version" ] && continue
147+
echo " merging bin/$name"
148+
cp -R "$sub" "sdk/node-pkg/bin/$name"
149+
done
150+
echo ""
151+
echo "Final bin/ layout:"
152+
find sdk/node-pkg/bin -maxdepth 2 -type d | sort
153+
echo ""
154+
echo "Files included by npm pack:"
155+
cd sdk/node-pkg && npm pack --dry-run 2>&1 | grep -E "\.(js|so|dylib)" | head -30
104156
105157
- name: Set up Node.js
106158
uses: actions/setup-node@v4
@@ -111,7 +163,7 @@ jobs:
111163
- name: Extract version
112164
id: extract-version
113165
run: |
114-
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('sdk/node-linux/package.json', 'utf8')).version)")
166+
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('sdk/node-pkg/package.json', 'utf8')).version)")
115167
echo "version=$VERSION" >> $GITHUB_OUTPUT
116168
echo "Version: $VERSION"
117169
@@ -129,7 +181,7 @@ jobs:
129181
130182
- name: Publish to npm
131183
if: steps.check-npm.outputs.exists == 'false'
132-
working-directory: sdk/node-linux
184+
working-directory: sdk/node-pkg
133185
env:
134186
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
135187
run: |
@@ -147,9 +199,11 @@ jobs:
147199
echo "**Version:** ${{ steps.extract-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
148200
echo "**Install:** \`npm install pilotprotocol\`" >> $GITHUB_STEP_SUMMARY
149201
echo "**npm:** https://www.npmjs.com/package/pilotprotocol" >> $GITHUB_STEP_SUMMARY
202+
echo "**Platforms bundled:** linux-amd64, darwin-arm64" >> $GITHUB_STEP_SUMMARY
150203
151204
test-install:
152205
needs: publish
206+
if: ${{ !(inputs.prerelease || github.event.release.prerelease) }}
153207
strategy:
154208
matrix:
155209
os: [ubuntu-latest, macos-latest]

.github/workflows/publish-python-sdk.yml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,28 @@ name: Publish Python SDK
33
on:
44
release:
55
types: [published]
6+
workflow_dispatch:
7+
inputs:
8+
version:
9+
description: 'Version to publish (without leading v, e.g. 1.9.1)'
10+
required: true
11+
type: string
12+
prerelease:
13+
description: 'Treat as prerelease (skip publish; build only)'
14+
required: false
15+
type: boolean
16+
default: false
617

718
permissions:
819
contents: write
920
id-token: write
1021

22+
env:
23+
PILOT_VERSION: ${{ inputs.version || github.event.release.tag_name }}
24+
PILOT_PRERELEASE: ${{ inputs.prerelease || github.event.release.prerelease }}
25+
1126
jobs:
1227
test-sdk:
13-
if: "!github.event.release.prerelease"
1428
runs-on: ubuntu-latest
1529
steps:
1630
- name: Checkout repository
@@ -39,10 +53,10 @@ jobs:
3953
- name: Checkout repository
4054
uses: actions/checkout@v4
4155

42-
- name: Set version from release tag
56+
- name: Set version from release tag or workflow input
4357
shell: bash
4458
run: |
45-
VERSION="${{ github.event.release.tag_name }}"
59+
VERSION="${PILOT_VERSION}"
4660
VERSION="${VERSION#v}"
4761
echo "version=$VERSION" >> $GITHUB_ENV
4862
cd sdk/python
@@ -114,6 +128,7 @@ jobs:
114128

115129
publish:
116130
needs: build-wheels
131+
if: ${{ !(inputs.prerelease || github.event.release.prerelease) }}
117132
runs-on: ubuntu-latest
118133
steps:
119134
- name: Download all artifacts

sdk/node/scripts/build-binaries.sh

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,45 +31,47 @@ echo "Building Pilot Protocol Suite for ${OS}/${ARCH}"
3131
echo "================================================================"
3232
echo ""
3333

34-
OUTPUT_DIR="sdk/node/bin"
35-
mkdir -p "$OUTPUT_DIR"
34+
BIN_ROOT="sdk/node/bin"
35+
PLATFORM_DIR="$BIN_ROOT/${OS}-${ARCH}"
36+
mkdir -p "$PLATFORM_DIR"
3637

3738
# 1. Build daemon
3839
echo "1. Building pilot-daemon..."
39-
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$OUTPUT_DIR/pilot-daemon" ./cmd/daemon
40-
echo " ✓ Built: $OUTPUT_DIR/pilot-daemon"
40+
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$PLATFORM_DIR/pilot-daemon" ./cmd/daemon
41+
echo " ✓ Built: $PLATFORM_DIR/pilot-daemon"
4142
echo ""
4243

4344
# 2. Build pilotctl
4445
echo "2. Building pilotctl..."
45-
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$OUTPUT_DIR/pilotctl" ./cmd/pilotctl
46-
echo " ✓ Built: $OUTPUT_DIR/pilotctl"
46+
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$PLATFORM_DIR/pilotctl" ./cmd/pilotctl
47+
echo " ✓ Built: $PLATFORM_DIR/pilotctl"
4748
echo ""
4849

4950
# 3. Build gateway
5051
echo "3. Building pilot-gateway..."
51-
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$OUTPUT_DIR/pilot-gateway" ./cmd/gateway
52-
echo " ✓ Built: $OUTPUT_DIR/pilot-gateway"
52+
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$PLATFORM_DIR/pilot-gateway" ./cmd/gateway
53+
echo " ✓ Built: $PLATFORM_DIR/pilot-gateway"
5354
echo ""
5455

5556
# 4. Build updater
5657
echo "4. Building pilot-updater..."
57-
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$OUTPUT_DIR/pilot-updater" ./cmd/updater
58-
echo " ✓ Built: $OUTPUT_DIR/pilot-updater"
58+
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$PLATFORM_DIR/pilot-updater" ./cmd/updater
59+
echo " ✓ Built: $PLATFORM_DIR/pilot-updater"
5960
echo ""
6061

6162
# 5. Build CGO bindings
6263
echo "5. Building libpilot CGO bindings..."
6364
cd sdk/cgo
64-
CGO_ENABLED=1 GOOS="$OS" GOARCH="$ARCH" go build -buildmode=c-shared -ldflags="-s -w" -o "../../$OUTPUT_DIR/libpilot.$EXT" .
65+
CGO_ENABLED=1 GOOS="$OS" GOARCH="$ARCH" go build -buildmode=c-shared -ldflags="-s -w" -o "../../$PLATFORM_DIR/libpilot.$EXT" .
6566
cd ../..
66-
echo " ✓ Built: $OUTPUT_DIR/libpilot.$EXT"
67+
echo " ✓ Built: $PLATFORM_DIR/libpilot.$EXT"
6768
echo ""
6869

69-
# 6. Write .pilot-version marker so the runtime seeder can compare against
70-
# whatever's already installed at ~/.pilot/bin/.
71-
echo "$SDK_VERSION" > "$OUTPUT_DIR/.pilot-version"
72-
echo "6. Wrote $OUTPUT_DIR/.pilot-version → $SDK_VERSION"
70+
# 6. Write .pilot-version marker at the bin/ root (shared across all platform
71+
# subdirs). The runtime seeder reads this to compare against whatever's
72+
# already installed at ~/.pilot/bin/.
73+
echo "$SDK_VERSION" > "$BIN_ROOT/.pilot-version"
74+
echo "6. Wrote $BIN_ROOT/.pilot-version → $SDK_VERSION"
7375
echo ""
7476

7577
# 7. macOS ad-hoc codesign + strip quarantine. Mirrors the main release
@@ -78,7 +80,7 @@ echo ""
7880
# software" when downloaded via npm.
7981
if [ "$OS" = "darwin" ]; then
8082
echo "7. macOS ad-hoc codesign + strip quarantine..."
81-
for bin in "$OUTPUT_DIR/pilot-daemon" "$OUTPUT_DIR/pilotctl" "$OUTPUT_DIR/pilot-gateway" "$OUTPUT_DIR/pilot-updater" "$OUTPUT_DIR/libpilot.$EXT"; do
83+
for bin in "$PLATFORM_DIR/pilot-daemon" "$PLATFORM_DIR/pilotctl" "$PLATFORM_DIR/pilot-gateway" "$PLATFORM_DIR/pilot-updater" "$PLATFORM_DIR/libpilot.$EXT"; do
8284
codesign --force --deep --sign - "$bin"
8385
xattr -cr "$bin" || true
8486
codesign -dv "$bin" 2>&1 | grep -E "Signature|Authority|TeamIdentifier" | head -1 || true
@@ -91,10 +93,10 @@ fi
9193
echo "================================================================"
9294
echo "Build Summary:"
9395
echo "================================================================"
94-
du -h "$OUTPUT_DIR"/* | awk '{printf " %-30s %s\n", $2, $1}'
96+
du -h "$PLATFORM_DIR"/* | awk '{printf " %-30s %s\n", $2, $1}'
9597
echo ""
9698
echo "Total size:"
97-
du -sh "$OUTPUT_DIR" | awk '{printf " %s\n", $1}'
99+
du -sh "$PLATFORM_DIR" | awk '{printf " %s\n", $1}'
98100
echo ""
99101
echo "✓ All binaries built successfully for ${OS}/${ARCH}"
100102
echo ""

sdk/node/src/ffi.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,16 @@
1818

1919
import koffi from 'koffi';
2020
import { existsSync } from 'node:fs';
21-
import { homedir, platform } from 'node:os';
21+
import { homedir, arch, platform } from 'node:os';
2222
import { join, resolve } from 'node:path';
2323
import { fileURLToPath } from 'node:url';
2424
import { runtimeLibraryPath } from './runtime.js';
2525

26+
function platformSubdir(): string {
27+
const goArch = arch() === 'x64' ? 'amd64' : arch();
28+
return `${platform()}-${goArch}`;
29+
}
30+
2631
// ---------------------------------------------------------------------------
2732
// Error class (defined here to avoid circular deps with client.ts)
2833
// ---------------------------------------------------------------------------
@@ -69,9 +74,10 @@ export function findLibrary(): string {
6974
const pilotBin = join(homedir(), '.pilot', 'bin', libName);
7075
if (existsSync(pilotBin)) return pilotBin;
7176

72-
// 4. <package>/bin/ (npm package layout: dist/ffi.js → ../bin/).
77+
// 4. <package>/bin/<os>-<arch>/ (npm package layout: dist/ffi.js → ../bin/).
7378
const thisDir = resolve(fileURLToPath(import.meta.url), '..');
74-
const pkgBin = resolve(thisDir, '..', 'bin', libName);
79+
const sub = platformSubdir();
80+
const pkgBin = resolve(thisDir, '..', 'bin', sub, libName);
7581
if (existsSync(pkgBin)) return pkgBin;
7682

7783
// 5. Same directory as this file.
@@ -87,7 +93,7 @@ export function findLibrary(): string {
8793
'\n' +
8894
'Expected locations:\n' +
8995
` - ~/.pilot/bin/${libName}\n` +
90-
` - ${pkgBin} (npm package)\n` +
96+
` - ${pkgBin} (npm package, ${sub})\n` +
9197
` - ${colocated} (colocated)\n` +
9298
` - ${repoBin} (development)\n` +
9399
'\n' +

0 commit comments

Comments
 (0)