Skip to content

Release

Release #30

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
skip_publish:
description: 'Skip npm publish (for testing)'
type: boolean
default: true
jobs:
build-and-test:
name: Build & Test ${{ matrix.package }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# macOS
- os: macos-14
arch: arm64
gpu: metal
package: darwin-arm64
- os: macos-15-intel
arch: x64
gpu: cpu
package: darwin-x64
# Linux x64
- os: ubuntu-22.04
arch: x64
gpu: cpu
package: linux-x64
- os: ubuntu-22.04
arch: x64
gpu: cuda
package: linux-x64-cuda
- os: ubuntu-22.04
arch: x64
gpu: vulkan
package: linux-x64-vulkan
# Linux ARM64 (native runners)
- os: ubuntu-22.04-arm
arch: arm64
gpu: cpu
package: linux-arm64
- os: ubuntu-22.04-arm
arch: arm64
gpu: cuda
package: linux-arm64-cuda
- os: ubuntu-22.04-arm
arch: arm64
gpu: vulkan
package: linux-arm64-vulkan
# Windows x64
- os: windows-2022
arch: x64
gpu: cpu
package: win32-x64
- os: windows-2022
arch: x64
gpu: cuda
package: win32-x64-cuda
- os: windows-2022
arch: x64
gpu: vulkan
package: win32-x64-vulkan
# Windows ARM64 (cross-compiled from x64)
- os: windows-2022
arch: arm64
gpu: cpu
package: win32-arm64
cross_compile: true
- os: windows-2022
arch: arm64
gpu: vulkan
package: win32-arm64-vulkan
cross_compile: true
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
registry-url: 'https://registry.npmjs.org'
- name: Validate llama.cpp version
run: node scripts/sync-llama-cpp.js --check
shell: bash
# Platform-specific build dependencies
- name: Install build tools (Linux x64)
if: runner.os == 'Linux' && matrix.arch == 'x64' && matrix.gpu == 'cpu'
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake
- name: Install build tools (Linux ARM64)
if: runner.os == 'Linux' && matrix.arch == 'arm64'
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake
# CUDA 12.2.2 required for Cloud Run L4 GPU (driver 535.x)
- name: Provision CUDA toolkit (Linux)
if: matrix.gpu == 'cuda' && runner.os == 'Linux'
uses: ./.github/actions/provision-cuda
with:
version: '12.2.2'
arch: ${{ matrix.arch }}
- name: Install Vulkan SDK (Linux)
if: matrix.gpu == 'vulkan' && runner.os == 'Linux'
uses: jakoch/install-vulkan-sdk-action@v1.2.4
with:
vulkan_version: '1.3.296.0'
install_runtime: true
cache: false
# CUDA 12.2.2 for broad driver compatibility (matches Linux)
- name: Provision CUDA toolkit (Windows)
if: matrix.gpu == 'cuda' && runner.os == 'Windows'
uses: ./.github/actions/provision-cuda
with:
version: '12.2.2'
arch: ${{ matrix.arch }}
- name: Install Vulkan SDK (Windows)
if: matrix.gpu == 'vulkan' && runner.os == 'Windows'
uses: jakoch/install-vulkan-sdk-action@v1.2.4
with:
vulkan_version: '1.3.296.0'
install_runtime: true
cache: false
- name: Setup LLVM and Ninja for Windows ARM64 cross-compilation
if: runner.os == 'Windows' && matrix.cross_compile == true
shell: pwsh
run: |
choco install llvm ninja -y
echo "CC=clang-cl" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "CXX=clang-cl" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "CMAKE_GENERATOR=Ninja" | Out-File -FilePath $env:GITHUB_ENV -Append
# Build
- name: Install npm dependencies
run: npm install --ignore-scripts
- name: Build native module (Native builds)
if: matrix.cross_compile != true
run: npm run build
env:
LLOYAL_GPU: ${{ matrix.gpu }}
- name: Build native module (Windows ARM64 cross-compile)
if: runner.os == 'Windows' && matrix.cross_compile == true
shell: pwsh
run: |
$env:CMAKE_GENERATOR = "Ninja"
$env:CMAKE_TOOLCHAIN_FILE = "${{ github.workspace }}/cmake/arm64-cross.cmake"
npm run build
env:
LLOYAL_GPU: ${{ matrix.gpu }}
ARCH: arm64
# Create platform package
- name: Create platform package
shell: bash
run: |
node scripts/create-platform-package.js "${{ matrix.package }}" "${{ matrix.os }}" "${{ matrix.arch }}"
# Test platform package (skip for cross-compiled packages - can't run ARM64 on x64)
- name: Cache test models
if: matrix.cross_compile != true
uses: actions/cache@v4
with:
path: models/
key: test-models-v1
- name: Download test models
if: matrix.cross_compile != true
run: bash scripts/download-test-models.sh
- name: Install platform package locally
if: matrix.cross_compile != true
shell: bash
run: |
npm install ./packages/${{ matrix.package }}
rm -rf build/Release
echo "Installed package contents:"
ls -la node_modules/@lloyal-labs/lloyal.node-${{ matrix.package }}/bin/ || echo "Package not found in node_modules"
- name: Verify platform package loading (Unix)
if: runner.os != 'Windows' && matrix.cross_compile != true && matrix.gpu != 'cuda'
shell: bash
run: |
# Set LD_LIBRARY_PATH to find sibling .so files (Linux CUDA/Vulkan)
PKG_BIN="$PWD/node_modules/@lloyal-labs/lloyal.node-${{ matrix.package }}/bin"
export LD_LIBRARY_PATH="${PKG_BIN}:${LD_LIBRARY_PATH:-}"
echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
node -e "
const { loadBinary } = require('./lib');
const addon = loadBinary();
console.log('✓ Platform package loaded successfully');
console.log(' Exports:', Object.keys(addon));
"
env:
LLOYAL_GPU: ${{ matrix.gpu }}
LLOYAL_NO_FALLBACK: '1'
- name: Verify platform package loading (Windows)
if: runner.os == 'Windows' && matrix.cross_compile != true && matrix.gpu != 'cuda'
shell: pwsh
run: |
# Add package bin to PATH for DLL discovery
$pkgBin = "$PWD\node_modules\@lloyal-labs\lloyal.node-${{ matrix.package }}\bin"
$env:PATH = "$pkgBin;$env:PATH"
# Add Vulkan SDK runtime to PATH if available
if ($env:VULKAN_SDK) {
$env:PATH = "$env:VULKAN_SDK\Bin;$env:PATH"
# Vulkan runtime is in runtime\x64, not Bin
if (Test-Path "$env:VULKAN_SDK\runtime\x64\vulkan-1.dll") {
$env:PATH = "$env:VULKAN_SDK\runtime\x64;$env:PATH"
Write-Host "Added Vulkan runtime to PATH: $env:VULKAN_SDK\runtime\x64"
}
}
# Add CUDA runtime to PATH if available
if ($env:CUDA_PATH) {
$env:PATH = "$env:CUDA_PATH\bin;$env:PATH"
Write-Host "Added CUDA bin to PATH: $env:CUDA_PATH\bin"
}
Write-Host "Package bin: $pkgBin"
Write-Host "VULKAN_SDK: $env:VULKAN_SDK"
Write-Host "CUDA_PATH: $env:CUDA_PATH"
node -e "
const { loadBinary } = require('./lib');
const addon = loadBinary();
console.log('✓ Platform package loaded successfully');
console.log(' Exports:', Object.keys(addon));
"
env:
LLOYAL_GPU: ${{ matrix.gpu }}
LLOYAL_NO_FALLBACK: '1'
# Integration tests on GitHub runners (no GPU hardware)
# GPU tests (CUDA/Vulkan) run separately via gpu-test.yml on Cloud Run with NVIDIA L4
- name: Run integration tests (Windows)
if: runner.os == 'Windows' && matrix.gpu == 'cpu' && matrix.cross_compile != true
shell: pwsh
run: |
$pkgBin = "$PWD\node_modules\@lloyal-labs\lloyal.node-${{ matrix.package }}\bin"
$env:PATH = "$pkgBin;$env:PATH"
if ($env:VULKAN_SDK) {
$env:PATH = "$env:VULKAN_SDK\Bin;$env:PATH"
if (Test-Path "$env:VULKAN_SDK\runtime\x64\vulkan-1.dll") {
$env:PATH = "$env:VULKAN_SDK\runtime\x64;$env:PATH"
}
}
if ($env:CUDA_PATH) { $env:PATH = "$env:CUDA_PATH\bin;$env:PATH" }
npm run test:integration
timeout-minutes: 5
env:
LLOYAL_GPU: ${{ matrix.gpu }}
LLOYAL_NO_FALLBACK: '1'
- name: Run integration tests (Unix)
if: runner.os != 'Windows' && (matrix.gpu == 'cpu' || matrix.gpu == 'metal')
run: |
PKG_BIN="$PWD/node_modules/@lloyal-labs/lloyal.node-${{ matrix.package }}/bin"
export LD_LIBRARY_PATH="${PKG_BIN}:${LD_LIBRARY_PATH:-}"
npm run test:integration
timeout-minutes: 5
env:
LLOYAL_GPU: ${{ matrix.gpu }}
LLOYAL_NO_FALLBACK: '1'
# Upload package artifact for publish job
- name: Upload platform package artifact
uses: actions/upload-artifact@v4
with:
name: package-${{ matrix.package }}
path: packages/${{ matrix.package }}/
retention-days: 1
# GPU Integration Tests (reusable workflow)
gpu-tests:

Check failure on line 300 in .github/workflows/release.yml

View workflow run for this annotation

GitHub Actions / Release

Invalid workflow file

The workflow is not valid. .github/workflows/release.yml (Line: 300, Col: 3): Error calling workflow 'lloyal-ai/lloyal.node/.github/workflows/gpu-test.yml@de6d382c921f247aad96933814b684df424c7b6f'. The nested job 'gpu-integration' is requesting 'id-token: write', but is only allowed 'id-token: none'.
name: GPU Tests
needs: build-and-test
uses: ./.github/workflows/gpu-test.yml
secrets: inherit
publish:
name: Publish all packages
needs: [build-and-test, gpu-tests]
runs-on: ubuntu-latest
# Only run if ALL jobs succeeded AND either it's a tag push or manual run without skip
if: success() && (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && !inputs.skip_publish))
permissions:
contents: read
id-token: write # Required for npm provenance
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
registry-url: 'https://registry.npmjs.org'
# Download all platform package artifacts
- name: Download all platform packages
uses: actions/download-artifact@v4
with:
path: packages/
pattern: package-*
merge-multiple: false
- name: List downloaded packages
run: |
echo "Downloaded platform packages:"
ls -la packages/
for dir in packages/package-*/; do
echo " - $(basename $dir): $(ls $dir)"
done
# Publish platform packages
- name: Publish platform packages
shell: bash
run: |
VERSION=$(node -p "require('./package.json').version")
echo "Publishing version: $VERSION"
# Determine npm tag based on version
if [[ "$VERSION" == *-alpha* ]]; then
NPM_TAG="alpha"
elif [[ "$VERSION" == *-beta* ]]; then
NPM_TAG="beta"
elif [[ "$VERSION" == *-rc* ]]; then
NPM_TAG="rc"
else
NPM_TAG="latest"
fi
echo "Using npm tag: $NPM_TAG"
# Publish each platform package
for pkg_dir in packages/package-*/; do
pkg_name=$(basename "$pkg_dir" | sed 's/^package-//')
echo ""
echo "Publishing @lloyal-labs/lloyal.node-${pkg_name}..."
cd "$pkg_dir"
npm publish --access public --tag "$NPM_TAG" --provenance
cd - > /dev/null
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# Publish main package
- name: Sync package versions
run: node scripts/sync-versions.js
- name: Publish main package
shell: bash
run: |
VERSION=$(node -p "require('./package.json').version")
if [[ "$VERSION" == *-alpha* ]]; then
npm publish --tag alpha --access public --provenance
elif [[ "$VERSION" == *-beta* ]]; then
npm publish --tag beta --access public --provenance
elif [[ "$VERSION" == *-rc* ]]; then
npm publish --tag rc --access public --provenance
else
npm publish --access public --provenance
fi
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}