Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 65 additions & 11 deletions .github/workflows/publish-node-sdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,28 @@ name: Publish Node SDK
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version to publish (without leading v, e.g. 1.9.1)'
required: true
type: string
prerelease:
description: 'Treat as prerelease (skip publish; build only)'
required: false
type: boolean
default: false

permissions:
contents: write
id-token: write

env:
PILOT_VERSION: ${{ inputs.version || github.event.release.tag_name }}
PILOT_PRERELEASE: ${{ inputs.prerelease || github.event.release.prerelease }}

jobs:
test-sdk:
if: "!github.event.release.prerelease"
runs-on: ubuntu-latest
defaults:
run:
Expand Down Expand Up @@ -38,10 +52,10 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set version from release tag
- name: Set version from release tag or workflow input
shell: bash
run: |
VERSION="${{ github.event.release.tag_name }}"
VERSION="${PILOT_VERSION}"
VERSION="${VERSION#v}"
echo "version=$VERSION" >> $GITHUB_ENV
cd sdk/node
Expand Down Expand Up @@ -82,25 +96,63 @@ jobs:
echo "Package contents:"
npm pack --dry-run
echo ""
echo "Binary sizes:"
echo "Built binary subdirs:"
ls -lh bin/

- name: Upload package artifact
# Upload only the platform-specific binary subdir; the publish job
# downloads both and merges them into a single multi-platform npm package.
- name: Upload platform binaries
uses: actions/upload-artifact@v4
with:
name: node-bin-${{ matrix.platform }}
path: sdk/node/bin/
retention-days: 7

# Upload the full package layout (JS + bin/ + bin-stubs) once — the
# Linux runner's copy is the publish base; macOS just contributes its
# bin/ subdir to the merge.
- name: Upload full package (Linux base)
if: matrix.platform == 'linux'
uses: actions/upload-artifact@v4
with:
name: npm-package-${{ matrix.platform }}
name: npm-package-base
path: sdk/node/
retention-days: 7

publish:
needs: build-packages
if: ${{ !(inputs.prerelease || github.event.release.prerelease) }}
runs-on: ubuntu-latest
steps:
- name: Download Linux package
- name: Download package base (Linux build)
uses: actions/download-artifact@v4
with:
name: npm-package-base
path: sdk/node-pkg

- name: Download macOS binaries
uses: actions/download-artifact@v4
with:
name: npm-package-linux
path: sdk/node-linux
name: node-bin-macos
path: sdk/node-bin-macos

- name: Merge macOS binaries into package
run: |
# Linux base already contains bin/<linux subdirs>/. Layer in the
# macOS subdirs so the published package is multi-platform.
for sub in sdk/node-bin-macos/*/; do
name=$(basename "$sub")
# Skip the .pilot-version file which is at the root, not a subdir.
[ "$name" = ".pilot-version" ] && continue
echo " merging bin/$name"
cp -R "$sub" "sdk/node-pkg/bin/$name"
done
echo ""
echo "Final bin/ layout:"
find sdk/node-pkg/bin -maxdepth 2 -type d | sort
echo ""
echo "Files included by npm pack:"
cd sdk/node-pkg && npm pack --dry-run 2>&1 | grep -E "\.(js|so|dylib)" | head -30

- name: Set up Node.js
uses: actions/setup-node@v4
Expand All @@ -111,7 +163,7 @@ jobs:
- name: Extract version
id: extract-version
run: |
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('sdk/node-linux/package.json', 'utf8')).version)")
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('sdk/node-pkg/package.json', 'utf8')).version)")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Version: $VERSION"

Expand All @@ -129,7 +181,7 @@ jobs:

- name: Publish to npm
if: steps.check-npm.outputs.exists == 'false'
working-directory: sdk/node-linux
working-directory: sdk/node-pkg
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
Expand All @@ -147,9 +199,11 @@ jobs:
echo "**Version:** ${{ steps.extract-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "**Install:** \`npm install pilotprotocol\`" >> $GITHUB_STEP_SUMMARY
echo "**npm:** https://www.npmjs.com/package/pilotprotocol" >> $GITHUB_STEP_SUMMARY
echo "**Platforms bundled:** linux-amd64, darwin-arm64" >> $GITHUB_STEP_SUMMARY

test-install:
needs: publish
if: ${{ !(inputs.prerelease || github.event.release.prerelease) }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
Expand Down
21 changes: 18 additions & 3 deletions .github/workflows/publish-python-sdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,28 @@ name: Publish Python SDK
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version to publish (without leading v, e.g. 1.9.1)'
required: true
type: string
prerelease:
description: 'Treat as prerelease (skip publish; build only)'
required: false
type: boolean
default: false

permissions:
contents: write
id-token: write

env:
PILOT_VERSION: ${{ inputs.version || github.event.release.tag_name }}
PILOT_PRERELEASE: ${{ inputs.prerelease || github.event.release.prerelease }}

jobs:
test-sdk:
if: "!github.event.release.prerelease"
runs-on: ubuntu-latest
steps:
- name: Checkout repository
Expand Down Expand Up @@ -39,10 +53,10 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set version from release tag
- name: Set version from release tag or workflow input
shell: bash
run: |
VERSION="${{ github.event.release.tag_name }}"
VERSION="${PILOT_VERSION}"
VERSION="${VERSION#v}"
echo "version=$VERSION" >> $GITHUB_ENV
cd sdk/python
Expand Down Expand Up @@ -114,6 +128,7 @@ jobs:

publish:
needs: build-wheels
if: ${{ !(inputs.prerelease || github.event.release.prerelease) }}
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
Expand Down
40 changes: 21 additions & 19 deletions sdk/node/scripts/build-binaries.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,45 +31,47 @@ echo "Building Pilot Protocol Suite for ${OS}/${ARCH}"
echo "================================================================"
echo ""

OUTPUT_DIR="sdk/node/bin"
mkdir -p "$OUTPUT_DIR"
BIN_ROOT="sdk/node/bin"
PLATFORM_DIR="$BIN_ROOT/${OS}-${ARCH}"
mkdir -p "$PLATFORM_DIR"

# 1. Build daemon
echo "1. Building pilot-daemon..."
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$OUTPUT_DIR/pilot-daemon" ./cmd/daemon
echo " ✓ Built: $OUTPUT_DIR/pilot-daemon"
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$PLATFORM_DIR/pilot-daemon" ./cmd/daemon
echo " ✓ Built: $PLATFORM_DIR/pilot-daemon"
echo ""

# 2. Build pilotctl
echo "2. Building pilotctl..."
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$OUTPUT_DIR/pilotctl" ./cmd/pilotctl
echo " ✓ Built: $OUTPUT_DIR/pilotctl"
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$PLATFORM_DIR/pilotctl" ./cmd/pilotctl
echo " ✓ Built: $PLATFORM_DIR/pilotctl"
echo ""

# 3. Build gateway
echo "3. Building pilot-gateway..."
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$OUTPUT_DIR/pilot-gateway" ./cmd/gateway
echo " ✓ Built: $OUTPUT_DIR/pilot-gateway"
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$PLATFORM_DIR/pilot-gateway" ./cmd/gateway
echo " ✓ Built: $PLATFORM_DIR/pilot-gateway"
echo ""

# 4. Build updater
echo "4. Building pilot-updater..."
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$OUTPUT_DIR/pilot-updater" ./cmd/updater
echo " ✓ Built: $OUTPUT_DIR/pilot-updater"
CGO_ENABLED=0 GOOS="$OS" GOARCH="$ARCH" go build -ldflags="-s -w" -o "$PLATFORM_DIR/pilot-updater" ./cmd/updater
echo " ✓ Built: $PLATFORM_DIR/pilot-updater"
echo ""

# 5. Build CGO bindings
echo "5. Building libpilot CGO bindings..."
cd sdk/cgo
CGO_ENABLED=1 GOOS="$OS" GOARCH="$ARCH" go build -buildmode=c-shared -ldflags="-s -w" -o "../../$OUTPUT_DIR/libpilot.$EXT" .
CGO_ENABLED=1 GOOS="$OS" GOARCH="$ARCH" go build -buildmode=c-shared -ldflags="-s -w" -o "../../$PLATFORM_DIR/libpilot.$EXT" .
cd ../..
echo " ✓ Built: $OUTPUT_DIR/libpilot.$EXT"
echo " ✓ Built: $PLATFORM_DIR/libpilot.$EXT"
echo ""

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

# 7. macOS ad-hoc codesign + strip quarantine. Mirrors the main release
Expand All @@ -78,7 +80,7 @@ echo ""
# software" when downloaded via npm.
if [ "$OS" = "darwin" ]; then
echo "7. macOS ad-hoc codesign + strip quarantine..."
for bin in "$OUTPUT_DIR/pilot-daemon" "$OUTPUT_DIR/pilotctl" "$OUTPUT_DIR/pilot-gateway" "$OUTPUT_DIR/pilot-updater" "$OUTPUT_DIR/libpilot.$EXT"; do
for bin in "$PLATFORM_DIR/pilot-daemon" "$PLATFORM_DIR/pilotctl" "$PLATFORM_DIR/pilot-gateway" "$PLATFORM_DIR/pilot-updater" "$PLATFORM_DIR/libpilot.$EXT"; do
codesign --force --deep --sign - "$bin"
xattr -cr "$bin" || true
codesign -dv "$bin" 2>&1 | grep -E "Signature|Authority|TeamIdentifier" | head -1 || true
Expand All @@ -91,10 +93,10 @@ fi
echo "================================================================"
echo "Build Summary:"
echo "================================================================"
du -h "$OUTPUT_DIR"/* | awk '{printf " %-30s %s\n", $2, $1}'
du -h "$PLATFORM_DIR"/* | awk '{printf " %-30s %s\n", $2, $1}'
echo ""
echo "Total size:"
du -sh "$OUTPUT_DIR" | awk '{printf " %s\n", $1}'
du -sh "$PLATFORM_DIR" | awk '{printf " %s\n", $1}'
echo ""
echo "✓ All binaries built successfully for ${OS}/${ARCH}"
echo ""
Expand Down
14 changes: 10 additions & 4 deletions sdk/node/src/ffi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@

import koffi from 'koffi';
import { existsSync } from 'node:fs';
import { homedir, platform } from 'node:os';
import { homedir, arch, platform } from 'node:os';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { runtimeLibraryPath } from './runtime.js';

function platformSubdir(): string {
const goArch = arch() === 'x64' ? 'amd64' : arch();
return `${platform()}-${goArch}`;
}

// ---------------------------------------------------------------------------
// Error class (defined here to avoid circular deps with client.ts)
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -69,9 +74,10 @@ export function findLibrary(): string {
const pilotBin = join(homedir(), '.pilot', 'bin', libName);
if (existsSync(pilotBin)) return pilotBin;

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

// 5. Same directory as this file.
Expand All @@ -87,7 +93,7 @@ export function findLibrary(): string {
'\n' +
'Expected locations:\n' +
` - ~/.pilot/bin/${libName}\n` +
` - ${pkgBin} (npm package)\n` +
` - ${pkgBin} (npm package, ${sub})\n` +
` - ${colocated} (colocated)\n` +
` - ${repoBin} (development)\n` +
'\n' +
Expand Down
Loading
Loading