ci: run on feature/** branches (quantization/dwconv/dbcache validation) #19
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 | |
| # Multi-platform build + oudep packaging for GAME-ggml CLI. | |
| # | |
| # Matrix: | |
| # linux-x64-vulkan — Ubuntu, Vulkan backend | |
| # linux-x64-cuda — Ubuntu 22.04, CUDA backend (CUDA 12.6) | |
| # macos-arm64-metal — Apple Silicon, Metal backend | |
| # macos-x64-metal — Intel Mac, Metal backend (cross-compiled on ARM runner) | |
| # windows-x64-vulkan — Windows, Vulkan backend | |
| # windows-x64-cuda — Windows Server 2022, CUDA backend (CUDA 12.6) | |
| # | |
| # On tag push, artifacts are bundled into a GitHub Release. | |
| on: | |
| push: | |
| branches: [main, master, 'feature/**'] | |
| tags: ['v*'] | |
| pull_request: {} | |
| workflow_dispatch: {} | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| prepare-model: | |
| name: prepare medium GGUF | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| cache: pip | |
| cache-dependency-path: scripts/requirements.txt | |
| - name: Install conversion dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -r scripts/requirements.txt | |
| - name: Download and verify medium checkpoint | |
| run: | | |
| curl -fL --retry 5 --retry-all-errors \ | |
| -o GAME-1.0-medium.zip \ | |
| https://github.com/openvpi/GAME/releases/download/v1.0.0/GAME-1.0-medium.zip | |
| echo "8c5b3e531e2905b935e664e2f533921cd637243770fab5282413bdb5051ca60c GAME-1.0-medium.zip" \ | |
| | sha256sum --check --strict | |
| unzip -q GAME-1.0-medium.zip | |
| - name: Convert checkpoint and prepare backend config | |
| run: | | |
| mkdir -p model | |
| python scripts/convert_pt_to_gguf.py \ | |
| --model-dir GAME-1.0-medium \ | |
| -o model/game_medium.gguf | |
| cat > model/config.json <<'EOF' | |
| { | |
| "samplerate": 44100, | |
| "timestep": 0.01, | |
| "languages": { | |
| "en": 1, | |
| "ja": 2, | |
| "yue": 3, | |
| "zh": 4 | |
| }, | |
| "loop": true | |
| } | |
| EOF | |
| - name: Verify model files | |
| run: | | |
| test -s model/game_medium.gguf | |
| python -m json.tool model/config.json >/dev/null | |
| ls -lh model/ | |
| - name: Upload model artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: game-ggml-medium-model | |
| path: model | |
| if-no-files-found: error | |
| retention-days: 7 | |
| build: | |
| name: ${{ matrix.name }} | |
| needs: prepare-model | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| name: linux-x64-vulkan | |
| backend: vulkan | |
| cmake_extra: "-DGAME_GGML_VULKAN=ON" | |
| build_jobs: 4 | |
| pkg_ext: "" | |
| lib_glob: "libggml*.so*" | |
| - os: ubuntu-22.04 | |
| name: linux-x64-cuda | |
| backend: cuda | |
| cmake_extra: '-DGAME_GGML_CUDA=ON -DGGML_NATIVE=OFF -DCMAKE_CUDA_ARCHITECTURES=75' | |
| build_jobs: 2 | |
| pkg_ext: "" | |
| lib_glob: "libggml*.so*" | |
| - os: macos-14 | |
| name: macos-arm64-metal | |
| backend: metal | |
| cmake_extra: "-DGAME_GGML_METAL=ON -DCMAKE_OSX_ARCHITECTURES=arm64" | |
| build_jobs: 4 | |
| pkg_ext: "" | |
| lib_glob: "libggml*.dylib" | |
| - os: macos-14 | |
| name: macos-x64-metal | |
| backend: metal | |
| cmake_extra: "-DGAME_GGML_METAL=ON -DCMAKE_OSX_ARCHITECTURES=x86_64" | |
| build_jobs: 4 | |
| pkg_ext: "" | |
| lib_glob: "libggml*.dylib" | |
| - os: windows-latest | |
| name: windows-x64-vulkan | |
| backend: vulkan | |
| cmake_extra: "-DGAME_GGML_VULKAN=ON" | |
| build_jobs: 4 | |
| pkg_ext: ".exe" | |
| lib_glob: "ggml*.dll" | |
| - os: windows-2022 | |
| name: windows-x64-cuda | |
| backend: cuda | |
| cmake_extra: '-DGAME_GGML_CUDA=ON -DGGML_NATIVE=OFF -DCMAKE_CUDA_ARCHITECTURES=75' | |
| build_jobs: 2 | |
| pkg_ext: ".exe" | |
| lib_glob: "ggml*.dll" | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install Vulkan SDK | |
| if: matrix.backend == 'vulkan' | |
| uses: humbletim/install-vulkan-sdk@30ba978f977e81b72d091fc8888feb1fb26f9aff | |
| with: | |
| version: 1.4.309.0 | |
| cache: true | |
| - name: Verify Vulkan shader compiler | |
| if: matrix.backend == 'vulkan' | |
| run: glslc --version | |
| - name: Install CUDA Toolkit (Linux) | |
| if: matrix.backend == 'cuda' && runner.os == 'Linux' | |
| uses: Jimver/cuda-toolkit@1a3c14e26833ccf292b268f9a790fb47dea7b2da # v0.2.28 | |
| with: | |
| cuda: "12.6.3" | |
| method: network | |
| log-file-suffix: "${{ matrix.name }}.txt" | |
| - name: Install CUDA Toolkit (Windows) | |
| if: matrix.backend == 'cuda' && runner.os == 'Windows' | |
| uses: Jimver/cuda-toolkit@b8bf9c6c28f8a92fbb04dcfcaee872e60c57462d # v0.2.36 | |
| with: | |
| cuda: "12.6.3" | |
| method: network | |
| sub-packages: '["nvcc", "cudart", "cublas", "cublas_dev", "visual_studio_integration"]' | |
| log-file-suffix: "${{ matrix.name }}.txt" | |
| - name: Verify CUDA compiler | |
| if: matrix.backend == 'cuda' | |
| run: nvcc --version | |
| - name: Disable native CPU for cross-compile (macOS x86_64 only) | |
| if: matrix.name == 'macos-x64-metal' | |
| run: echo "GGML_NATIVE=OFF" >> "$GITHUB_ENV" | |
| - name: Cache CMake FetchContent | |
| uses: actions/cache@v4 | |
| with: | |
| path: build/_deps | |
| # FetchContent stores generator-specific subbuild state here, so do not | |
| # share it between VS 2022/2026 runners or between different backends. | |
| key: ${{ matrix.name }}-deps-${{ hashFiles('cmake/Dependencies.cmake') }} | |
| restore-keys: | | |
| ${{ matrix.name }}-deps- | |
| - name: Configure | |
| run: | | |
| cmake -S . -B build \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DGAME_GGML_BUILD_CLI=ON \ | |
| -DGAME_GGML_BUILD_TESTS=OFF \ | |
| ${GGML_NATIVE:+-DGGML_NATIVE=$GGML_NATIVE} \ | |
| ${{ matrix.cmake_extra }} | |
| - name: Build | |
| # ggml-cuda expands many template instances. Unbounded parallel builds can | |
| # exhaust the memory of GitHub-hosted runners and terminate nvcc. | |
| run: cmake --build build --parallel ${{ matrix.build_jobs }} --config Release | |
| - name: Verify binary | |
| run: | | |
| set -euo pipefail | |
| ls -la build/bin/ | |
| # The CUDA CLI links ggml-cuda.dll directly (see src/backend.cpp), so | |
| # startup requires the Toolkit runtime DLLs. Git Bash does not always | |
| # forward its PATH to the Windows loader, so we dump the PE import | |
| # tables and run through PowerShell with a native Windows PATH. | |
| if [ "${{ matrix.backend }}" = "cuda" ] && [ "${{ runner.os }}" = "Windows" ]; then | |
| echo "== CUDA_PATH=$CUDA_PATH ==" | |
| CUDA_BIN="$(cygpath -u "$CUDA_PATH")/bin" | |
| echo "== CUDA Toolkit bin (first 60 entries) ==" | |
| ls -1 "$CUDA_BIN" 2>/dev/null | head -60 || echo "(cannot list $CUDA_BIN)" | |
| echo "== required runtime DLLs ==" | |
| for dll in cudart64_12.dll cublas64_12.dll cublasLt64_12.dll; do | |
| if [ -f "$CUDA_BIN/$dll" ]; then echo "OK $dll"; else echo "MISSING $dll"; fi | |
| done | |
| if python -m pip install --quiet pefile; then | |
| echo "== PE import tables ==" | |
| python scripts/dump_pe_imports.py build/bin/game_ggml_cli.exe build/bin/ggml-cuda.dll | |
| else | |
| echo "(pefile unavailable, skipping import dump)" | |
| fi | |
| fi | |
| # On Windows, ggml-cuda.dll imports nvcuda.dll (the NVIDIA driver | |
| # library) at load time. GitHub-hosted runners have no NVIDIA driver, | |
| # so the process cannot start there even for --version. When the | |
| # driver is present we run the real startup smoke test; otherwise the | |
| # PE dependency checks above are the verification and we report why. | |
| if [ "${{ runner.os }}" = "Windows" ]; then | |
| if [ -f "/c/Windows/System32/nvcuda.dll" ]; then | |
| powershell -NoProfile -ExecutionPolicy Bypass -Command ' | |
| $env:PATH = "$env:CUDA_PATH\bin;" + $env:PATH | |
| $exe = Join-Path (Get-Location) "build/bin/game_ggml_cli${{ matrix.pkg_ext }}" | |
| & $exe --version | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| ' | |
| else | |
| echo "no NVIDIA driver on this runner (nvcuda.dll not found); startup smoke test requires a GPU machine" | |
| fi | |
| else | |
| build/bin/game_ggml_cli${{ matrix.pkg_ext }} --version | |
| fi | |
| - name: Download medium GGUF | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: game-ggml-medium-model | |
| path: model | |
| - name: Package .oudep | |
| run: | | |
| set -euo pipefail | |
| BIN="game_ggml_cli${{ matrix.pkg_ext }}" | |
| PKG="game_ggml-${{ matrix.name }}" | |
| mkdir -p "$PKG" | |
| # CLI binary | |
| cp "build/bin/$BIN" "$PKG/" | |
| # Shared libraries | |
| find build/bin -maxdepth 1 -name "${{ matrix.lib_glob }}" -exec cp {} "$PKG/" \; | |
| compgen -G "$PKG/${{ matrix.lib_glob }}" >/dev/null | |
| # macOS: include the pre-compiled Metal shader cache. | |
| if [ "${{ runner.os }}" = "macOS" ]; then | |
| METALLIB=$(find build -name "default.metallib" -type f -print -quit) | |
| test -n "$METALLIB" | |
| cp "$METALLIB" "$PKG/" | |
| fi | |
| # Model and OpenUtau backend config. | |
| cp model/game_medium.gguf model/config.json "$PKG/" | |
| # oudep manifest | |
| cat > "$PKG/oudep.yaml" <<EOF | |
| id: game-ggml-medium | |
| version: 0.1.0 | |
| description: GAME GGML inference engine (${{ matrix.name }}) + medium GGUF weights | |
| entrypoints: | |
| - loader: Executable | |
| path: $BIN | |
| EOF | |
| # OpenUtau expects all of these files at the package root. | |
| test -x "$PKG/$BIN" | |
| test -s "$PKG/game_medium.gguf" | |
| test -s "$PKG/config.json" | |
| test -s "$PKG/oudep.yaml" | |
| grep -Fx "id: game-ggml-medium" "$PKG/oudep.yaml" | |
| grep -Fx " path: $BIN" "$PKG/oudep.yaml" | |
| ls -lh "$PKG/" | |
| echo "PKG_DIR=$PKG" >> "$GITHUB_ENV" | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.PKG_DIR }} | |
| path: ${{ env.PKG_DIR }} | |
| if-no-files-found: error | |
| retention-days: 30 | |
| release: | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download CI artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: game_ggml-* | |
| path: artifacts | |
| - name: Re-package all artifacts as .oudep | |
| run: | | |
| set -euo pipefail | |
| for dir in artifacts/*/; do | |
| name=$(basename "$dir") | |
| test -s "$dir/oudep.yaml" | |
| test -s "$dir/game_medium.gguf" | |
| test -s "$dir/config.json" | |
| ( | |
| cd "$dir" | |
| zip -r "../../${name}.oudep" . | |
| ) | |
| done | |
| # PackageManager requires oudep.yaml at the archive root. | |
| for package in *.oudep; do | |
| test "$(unzip -Z1 "$package" | grep -c '^oudep.yaml$')" -eq 1 | |
| test "$(unzip -Z1 "$package" | grep -c '^game_medium.gguf$')" -eq 1 | |
| test "$(unzip -Z1 "$package" | grep -c '^config.json$')" -eq 1 | |
| done | |
| ls -lh *.oudep | |
| - name: Publish release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: "*.oudep" | |
| generate_release_notes: true | |
| fail_on_unmatched_files: true |