Fix: Subscription replacement instead of merge #138
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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!" |