Skip to content

Fix: Subscription replacement instead of merge #138

Fix: Subscription replacement instead of merge

Fix: Subscription replacement instead of merge #138

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
release:
types: [published]
env:
DEBUG: napi:*
APP_NAME: laserstream-napi
MACOSX_DEPLOYMENT_TARGET: '10.13'
permissions:
contents: read
id-token: write
jobs:
build:
strategy:
fail-fast: false
matrix:
settings:
- host: macos-latest
target: x86_64-apple-darwin
build: npm run build -- --target x86_64-apple-darwin
- host: macos-latest
target: aarch64-apple-darwin
build: npm run build -- --target aarch64-apple-darwin
- host: ubuntu-latest
target: x86_64-unknown-linux-gnu
build: npm run build -- --target x86_64-unknown-linux-gnu
- host: ubuntu-latest
target: aarch64-unknown-linux-gnu
build: npm run build -- --target aarch64-unknown-linux-gnu
- host: ubuntu-latest
target: x86_64-unknown-linux-musl
docker: true
build: npm run build -- --target x86_64-unknown-linux-musl
- host: ubuntu-latest
target: aarch64-unknown-linux-musl
docker: true
build: npm run build -- --target aarch64-unknown-linux-musl
name: stable - ${{ matrix.settings.target }} - node@20
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
working-directory: javascript
- name: Install cross-compilation toolchains
if: matrix.settings.host == 'ubuntu-latest'
run: |
case ${{ matrix.settings.target }} in
aarch64-unknown-linux-gnu)
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
;;
esac
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: ${{ matrix.settings.target }}
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
javascript/target/
key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}-${{ hashFiles('javascript/Cargo.lock') }}
restore-keys: |
${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}-
${{ matrix.settings.target }}-cargo-
- name: Set up QEMU for cross-compilation
if: matrix.settings.docker == true
uses: docker/setup-qemu-action@v3
- name: Build in Docker (musl)
if: matrix.settings.docker == true
run: |
docker run --rm \
-v $(pwd):/workspace \
--platform ${{ startsWith(matrix.settings.target, 'aarch64') && 'linux/arm64' || 'linux/amd64' }} \
rust:alpine sh -c "
apk add --no-cache nodejs npm musl-dev gcc g++ openssl-dev perl make python3 && \
cd /workspace && \
rustup target add ${{ matrix.settings.target }} && \
npm install && \
export CC=gcc && \
export CXX=g++ && \
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=gcc && \
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=gcc && \
export RUSTFLAGS='-C target-feature=-crt-static' && \
npm run build -- --target ${{ matrix.settings.target }} && \
echo 'Build complete' && \
ls -la *.node
"
working-directory: javascript
- name: Build
if: matrix.settings.docker != true
run: ${{ matrix.settings.build }}
shell: bash
working-directory: javascript
env:
CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
TARGET_CC: ${{ matrix.settings.target == 'aarch64-unknown-linux-gnu' && 'aarch64-linux-gnu-gcc' || '' }}
- name: Verify build output
run: |
if [ ! -f *.node ]; then
echo "❌ Error: No .node file found after build"
exit 1
fi
echo "✅ Build output verified: $(ls -la *.node)"
# Note: musl binaries built in Alpine containers will have musl linking
# The verification would need to run inside an Alpine container to check properly
echo "ℹ️ Target: ${{ matrix.settings.target }}"
working-directory: javascript
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix.settings.target }}
path: |
javascript/**/*.node
if-no-files-found: error
publish:
name: Publish
runs-on: ubuntu-latest
needs: [build]
if: github.event_name == 'release'
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org/
- name: Install dependencies
run: npm ci
working-directory: javascript
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create platform packages
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
working-directory: javascript
run: |
# Get version from package.json
VERSION=$(node -p "require('./package.json').version")
# Check if artifacts directory exists
if [ ! -d "../artifacts" ]; then
echo "❌ Error: artifacts directory not found!"
exit 1
fi
# List artifacts for debugging
echo "📦 Available artifacts:"
ls -la ../artifacts/
# Track successful packages
PUBLISHED_COUNT=0
# Create platform-specific packages
for artifact in ../artifacts/bindings-*/; do
if [ ! -d "$artifact" ]; then
echo "❌ Error: artifact directory $artifact not found!"
continue
fi
target=$(basename "$artifact" | sed 's/bindings-//')
echo "🔨 Creating package for $target"
# Debug: List artifact contents
echo "🔍 Contents of $artifact:"
find "$artifact" -name "*.node" -type f
# Check if .node files exist (they should be in javascript/ subdirectory)
if ! find "$artifact" -name "*.node" -type f | head -1 > /dev/null; then
echo "❌ Error: No .node files found in $artifact"
exit 1
fi
# Create package directory
mkdir -p "platform-$target"
cd "platform-$target"
# Copy the .node file (from javascript/ subdirectory)
find "../$artifact" -name "*.node" -type f -exec cp {} ./ \; || {
echo "❌ Error: Failed to copy .node files from $artifact"
exit 1
}
# Verify .node file was copied
if ! ls *.node 1> /dev/null 2>&1; then
echo "❌ Error: No .node files found after copy"
exit 1
fi
# Determine package name and platform info based on target
case $target in
"x86_64-apple-darwin")
PACKAGE_NAME="helius-laserstream-darwin-x64"
OS_FIELD="darwin"
CPU_FIELD="x64"
MAIN_BINARY="laserstream-napi.darwin-x64.node"
;;
"aarch64-apple-darwin")
PACKAGE_NAME="helius-laserstream-darwin-arm64"
OS_FIELD="darwin"
CPU_FIELD="arm64"
MAIN_BINARY="laserstream-napi.darwin-arm64.node"
;;
"x86_64-unknown-linux-gnu")
PACKAGE_NAME="helius-laserstream-linux-x64-gnu"
OS_FIELD="linux"
CPU_FIELD="x64"
MAIN_BINARY="laserstream-napi.linux-x64-gnu.node"
;;
"aarch64-unknown-linux-gnu")
PACKAGE_NAME="helius-laserstream-linux-arm64-gnu"
OS_FIELD="linux"
CPU_FIELD="arm64"
MAIN_BINARY="laserstream-napi.linux-arm64-gnu.node"
;;
"x86_64-unknown-linux-musl")
PACKAGE_NAME="helius-laserstream-linux-x64-musl"
OS_FIELD="linux"
CPU_FIELD="x64"
MAIN_BINARY="laserstream-napi.linux-x64-musl.node"
;;
"aarch64-unknown-linux-musl")
PACKAGE_NAME="helius-laserstream-linux-arm64-musl"
OS_FIELD="linux"
CPU_FIELD="arm64"
MAIN_BINARY="laserstream-napi.linux-arm64-musl.node"
;;
*) echo "❌ Unknown target: $target"; exit 1 ;;
esac
# Create package.json for platform package
cat > package.json << EOF
{
"name": "$PACKAGE_NAME",
"version": "$VERSION",
"description": "Platform-specific binary for helius-laserstream ($target)",
"main": "$MAIN_BINARY",
"files": ["*.node"],
"os": ["$OS_FIELD"],
"cpu": ["$CPU_FIELD"],
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/helius-labs/laserstream.git"
},
"publishConfig": {
"access": "public"
}
}
EOF
# Publish platform package
echo "📤 Publishing $PACKAGE_NAME@$VERSION"
npm publish || {
echo "❌ Error: Failed to publish $PACKAGE_NAME"
exit 1
}
PUBLISHED_COUNT=$((PUBLISHED_COUNT + 1))
cd ..
done
# Verify we published expected number of packages
if [ "$PUBLISHED_COUNT" -ne 6 ]; then
echo "❌ Error: Expected 6 platform packages, but published $PUBLISHED_COUNT"
exit 1
fi
echo "✅ Successfully published $PUBLISHED_COUNT platform packages"
- name: Publish main package
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
working-directory: javascript
run: |
# Publish main package (without .node files)
echo "📤 Publishing main package helius-laserstream"
npm publish || {
echo "❌ Error: Failed to publish main package"
exit 1
}
echo "✅ Successfully published main package"
- name: Verify publication
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
working-directory: javascript
run: |
VERSION=$(node -p "require('./package.json').version")
echo "🔍 Verifying publication of version $VERSION"
# Wait a moment for NPM to propagate
sleep 10
# Check main package
if ! npm view helius-laserstream@$VERSION version > /dev/null 2>&1; then
echo "❌ Error: Main package helius-laserstream@$VERSION not found on NPM"
exit 1
fi
# Check platform packages
PLATFORM_PACKAGES=(
"helius-laserstream-darwin-x64"
"helius-laserstream-darwin-arm64"
"helius-laserstream-linux-x64-gnu"
"helius-laserstream-linux-arm64-gnu"
"helius-laserstream-linux-x64-musl"
"helius-laserstream-linux-arm64-musl"
)
for package in "${PLATFORM_PACKAGES[@]}"; do
if ! npm view "$package@$VERSION" version > /dev/null 2>&1; then
echo "❌ Error: Platform package $package@$VERSION not found on NPM"
exit 1
fi
echo "✅ Verified: $package@$VERSION"
done
echo "🎉 All packages successfully published and verified!"