fix(serving): apply llama.cpp GPU profile placement #164
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: Build | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ['v*'] | |
| pull_request: | |
| branches: [main] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_TOOLCHAIN_VERSION: 1.92.0 | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| lint-workflows: | |
| name: Lint Workflows | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: rhysd/actionlint@v1.7.8 | |
| - name: Check workspace dependency ownership | |
| run: npm run check:dependency-ownership | |
| - name: Check release version alignment | |
| run: npm run check:release-versions | |
| # Build and test Rust backend on all platforms | |
| build-rust: | |
| name: Build Rust (${{ matrix.target }}) | |
| needs: [lint-workflows] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| - os: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| - os: macos-14 | |
| target: aarch64-apple-darwin | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_TOOLCHAIN_VERSION }} | |
| targets: ${{ matrix.target }} | |
| - name: Cache Cargo | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: rust -> target | |
| - name: Build Rust | |
| working-directory: ./rust | |
| run: cargo build --workspace --exclude pumas_rustler --release --target ${{ matrix.target }} | |
| - name: Run Rust tests | |
| working-directory: ./rust | |
| run: cargo test --workspace --exclude pumas_rustler --release | |
| - name: Upload Rust artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: rust-${{ matrix.target }} | |
| path: | | |
| rust/target/${{ matrix.target }}/release/libpumas_uniffi.so | |
| rust/target/${{ matrix.target }}/release/libpumas_uniffi.dylib | |
| rust/target/${{ matrix.target }}/release/pumas_uniffi.dll | |
| if-no-files-found: ignore | |
| - name: Upload pumas-rpc for Electron packaging | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: rpc-${{ matrix.target }} | |
| path: | | |
| rust/target/${{ matrix.target }}/release/pumas-rpc | |
| rust/target/${{ matrix.target }}/release/pumas-rpc.exe | |
| if-no-files-found: ignore | |
| rust-quality: | |
| name: Rust Quality | |
| needs: [lint-workflows] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_TOOLCHAIN_VERSION }} | |
| components: rustfmt, clippy | |
| - name: Cache Cargo | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: rust -> target | |
| - name: Run Rust verification contract | |
| run: ./scripts/rust/check.sh | |
| # Build and test frontend | |
| build-frontend: | |
| name: Build Frontend (${{ matrix.os }}) | |
| needs: [lint-workflows] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| upload_dist: true | |
| - os: windows-latest | |
| upload_dist: false | |
| - os: macos-14 | |
| upload_dist: false | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Windows RAM disk | |
| if: runner.os == 'Windows' | |
| uses: ./.github/actions/setup-windows-ramdisk | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: '.node-version' | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - name: Enable Corepack | |
| run: corepack enable | |
| - name: Install workspace dependencies | |
| run: corepack pnpm install --frozen-lockfile | |
| - name: Lint | |
| run: npm run -w frontend lint | |
| - name: Check file-size ratchet | |
| run: npm run -w frontend check:size | |
| - name: Type check | |
| run: npm run -w frontend check:types | |
| - name: Run tests | |
| if: matrix.upload_dist | |
| run: npm run -w frontend test:run | |
| - name: Build | |
| if: matrix.upload_dist | |
| run: npm run -w frontend build | |
| - name: Upload frontend artifact | |
| if: matrix.upload_dist | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: frontend-dist | |
| path: frontend/dist/ | |
| verify-launcher: | |
| name: Verify Launcher | |
| needs: [lint-workflows] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: '.node-version' | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - name: Enable Corepack | |
| run: corepack enable | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_TOOLCHAIN_VERSION }} | |
| - name: Setup Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version-file: '.python-version' | |
| - name: Cache Cargo | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: rust -> target | |
| - name: Install workspace dependencies | |
| run: corepack pnpm install --frozen-lockfile | |
| - name: Install Python development dependencies | |
| run: python -m pip install -r torch-server/requirements-dev.txt | |
| - name: Install Xvfb | |
| run: sudo apt-get update && sudo apt-get install -y xvfb | |
| - name: Build release artifacts for launcher verification | |
| run: bash launcher.sh --build-release | |
| - name: Run launcher tests | |
| run: npm run test:launcher | |
| - name: Lint Torch sidecar | |
| run: python -m ruff check torch-server | |
| - name: Check Torch sidecar formatting | |
| run: python -m ruff format --check torch-server | |
| - name: Run Torch sidecar tests | |
| run: python -m unittest discover -s torch-server/tests | |
| - name: Run bounded release smoke | |
| run: xvfb-run -a bash launcher.sh --release-smoke | |
| # Generate binding source files (platform-independent, only needs one OS) | |
| generate-bindings: | |
| name: Generate Binding Sources | |
| needs: [build-rust] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ env.RUST_TOOLCHAIN_VERSION }} | |
| - name: Download Linux Rust artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: rust-x86_64-unknown-linux-gnu | |
| path: rust-artifact | |
| - name: Package pumas-core crate | |
| working-directory: ./rust | |
| run: cargo package -p pumas-library --allow-dirty | |
| - name: Upload pumas-core crate | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: pumas-core-crate | |
| path: rust/target/package/pumas-library-*.crate | |
| - name: Install uniffi-bindgen | |
| run: cargo install --path rust/crates/pumas-uniffi --bin pumas-uniffi-bindgen --no-default-features --features cli | |
| - name: Install uniffi-bindgen-cs | |
| run: CARGO_NET_GIT_FETCH_WITH_CLI=true cargo install uniffi-bindgen-cs --git https://github.com/NordSecurity/uniffi-bindgen-cs --tag v0.9.0+v0.28.3 | |
| - name: Generate Python bindings | |
| working-directory: ./rust | |
| run: | | |
| mkdir -p ../bindings/python | |
| pumas-uniffi-bindgen generate \ | |
| --library \ | |
| --language python \ | |
| --out-dir ../bindings/python \ | |
| ../rust-artifact/libpumas_uniffi.so | |
| - name: Generate Kotlin bindings | |
| working-directory: ./rust | |
| run: | | |
| mkdir -p ../bindings/kotlin | |
| pumas-uniffi-bindgen generate \ | |
| --library \ | |
| --language kotlin \ | |
| --out-dir ../bindings/kotlin \ | |
| ../rust-artifact/libpumas_uniffi.so | |
| - name: Generate Swift bindings | |
| working-directory: ./rust | |
| run: | | |
| mkdir -p ../bindings/swift | |
| pumas-uniffi-bindgen generate \ | |
| --library \ | |
| --language swift \ | |
| --out-dir ../bindings/swift \ | |
| ../rust-artifact/libpumas_uniffi.so | |
| - name: Generate Ruby bindings | |
| working-directory: ./rust | |
| run: | | |
| mkdir -p ../bindings/ruby | |
| pumas-uniffi-bindgen generate \ | |
| --library \ | |
| --language ruby \ | |
| --out-dir ../bindings/ruby \ | |
| ../rust-artifact/libpumas_uniffi.so | |
| - name: Generate C# bindings | |
| working-directory: ./rust | |
| run: | | |
| mkdir -p ../bindings/csharp | |
| uniffi-bindgen-cs \ | |
| --library \ | |
| --out-dir ../bindings/csharp \ | |
| ../rust-artifact/libpumas_uniffi.so | |
| - name: Upload binding sources | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: binding-sources | |
| path: bindings/ | |
| # Package Electron app for each platform | |
| build-electron: | |
| name: Package Electron (${{ matrix.platform }}) | |
| needs: [build-rust, build-frontend, verify-launcher] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| platform: linux | |
| rust-target: x86_64-unknown-linux-gnu | |
| binary-name: pumas-rpc | |
| - os: windows-latest | |
| platform: win | |
| rust-target: x86_64-pc-windows-msvc | |
| binary-name: pumas-rpc.exe | |
| - os: macos-14 | |
| platform: mac | |
| rust-target: aarch64-apple-darwin | |
| binary-name: pumas-rpc | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Windows RAM disk | |
| if: runner.os == 'Windows' | |
| uses: ./.github/actions/setup-windows-ramdisk | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: '.node-version' | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - name: Enable Corepack | |
| run: corepack enable | |
| - name: Download pumas-rpc binary | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: rpc-${{ matrix.rust-target }} | |
| path: rust-artifact | |
| - name: Download frontend artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: frontend-dist | |
| path: frontend/dist | |
| - name: Stage Rust binary | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Force -Path "electron/resources/bin" | Out-Null | |
| Copy-Item -Path "rust-artifact/${{ matrix.binary-name }}" -Destination "electron/resources/bin/${{ matrix.binary-name }}" -Force | |
| if (-not $IsWindows) { | |
| chmod +x "electron/resources/bin/${{ matrix.binary-name }}" | |
| } | |
| - name: Install workspace dependencies | |
| run: corepack pnpm install --frozen-lockfile | |
| - name: Verify app icon assets | |
| shell: pwsh | |
| run: | | |
| $required = @( | |
| "electron/build/icons/Pumas-Library_05.png", | |
| "electron/build/icons/icon.ico", | |
| "electron/build/icons/icon.icns" | |
| ) | |
| foreach ($file in $required) { | |
| if (-not (Test-Path $file)) { | |
| throw "Missing required icon asset: $file" | |
| } | |
| } | |
| - name: Lint Electron | |
| run: corepack pnpm --filter ./electron lint | |
| - name: Test Electron IPC validation | |
| run: corepack pnpm --filter ./electron test | |
| - name: Build Electron TypeScript | |
| run: corepack pnpm --filter ./electron build | |
| - name: Package Electron app | |
| run: corepack pnpm --filter ./electron exec electron-builder --${{ matrix.platform }} --publish never | |
| - name: Upload Electron artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: electron-${{ matrix.platform }} | |
| path: | | |
| electron/release/*.AppImage | |
| electron/release/*.deb | |
| electron/release/*.exe | |
| electron/release/*.dmg | |
| electron/release/*.zip | |
| if-no-files-found: warn | |
| # Create release when a tag is pushed | |
| release: | |
| name: Create Release | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: [build-rust, rust-quality, build-electron, generate-bindings, verify-launcher] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Extract version from tag | |
| id: version | |
| run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" | |
| - name: Rename and organize release artifacts | |
| run: | | |
| mkdir -p release-artifacts | |
| VERSION=${{ steps.version.outputs.version }} | |
| # --- Per-language binding packages --- | |
| # Each package contains the generated source files + native libraries for all platforms | |
| # --- pumas-core source crate --- | |
| cp artifacts/pumas-core-crate/pumas-library-*.crate release-artifacts/ | |
| # Collect UniFFI native libraries by target. | |
| mkdir -p staging/uniffi | |
| for target_dir in artifacts/rust-*/; do | |
| TARGET=$(basename "$target_dir" | sed 's/^rust-//') | |
| mkdir -p "staging/uniffi/${TARGET}" | |
| for file in "$target_dir"*; do | |
| [ -f "$file" ] || continue | |
| BASENAME=$(basename "$file") | |
| case "$BASENAME" in | |
| libpumas_uniffi.*|pumas_uniffi.dll) | |
| cp "$file" "staging/uniffi/${TARGET}/" | |
| ;; | |
| esac | |
| done | |
| done | |
| # --- Per-language binding packages --- | |
| # Each package contains the generated source files + native libraries for all platforms | |
| for lang in python kotlin swift ruby csharp; do | |
| mkdir -p "staging/${lang}-pkg/native" | |
| cp -r "artifacts/binding-sources/${lang}/." "staging/${lang}-pkg/" | |
| cp -r staging/uniffi/* "staging/${lang}-pkg/native/" | |
| cd "staging/${lang}-pkg" | |
| zip -r "../../release-artifacts/pumas-bindings-${lang}-${VERSION}.zip" . | |
| cd ../.. | |
| done | |
| # --- Desktop application --- | |
| # Electron installers (already named with version by electron-builder) | |
| for electron_dir in artifacts/electron-*/; do | |
| for file in "$electron_dir"*; do | |
| [ -f "$file" ] || continue | |
| cp "$file" "release-artifacts/" | |
| done | |
| done | |
| - name: List release artifacts | |
| run: ls -la release-artifacts/ | |
| - name: Generate checksums | |
| working-directory: release-artifacts | |
| run: | | |
| mapfile -d '' artifacts < <( | |
| find . -maxdepth 1 -type f ! -name checksums-sha256.txt -printf '%P\0' | | |
| sort -z | |
| ) | |
| if (( ${#artifacts[@]} == 0 )); then | |
| echo "No release artifacts found for checksum generation" >&2 | |
| exit 1 | |
| fi | |
| sha256sum "${artifacts[@]}" > checksums-sha256.txt | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: release-artifacts/* | |
| draft: true | |
| generate_release_notes: true | |
| prerelease: ${{ startsWith(github.ref_name, 'v0.') }} |