Skip to content

Commit f7c383b

Browse files
seniorfishclaude
andcommitted
Consolidate ONNX CI into one matrix workflow with reusable composite actions
Replace onnx-build.yml (OpenVINO, from-source ORT) and onnx-cpu-build.yml (CPU, prebuilt ORT) with a single onnx-backend.yml that drives a matrix of execution providers. The only real difference between providers - how ONNX Runtime is obtained - is encapsulated in .github/actions/onnx-prepare-ort (prebuilt zip / DirectML NuGet / from-source build), and the shared configure-build-test-stage pipeline lives in .github/actions/onnx-build-katago. - Matrix rows today: cpu + directml (fast, prebuilt/nuget, minutes) under build-fast, openvino (from-source, 1-3h) under build-slow. - Trigger policy by tier: fast jobs run on PR + master push + dispatch so the ONNX backend keeps a cheap always-on regression guard; slow from-source jobs run only on workflow_dispatch so they never burn upstream CI minutes. - Adding a backend = one matrix row + a fetch/build recipe in onnx-prepare-ort. - GitHub-hosted runners have no GPU, so from-source jobs verify build + EP wiring only; real GPU inference must be validated on a GPU machine. - ci/onnx-windows stays in push.branches as a temporary trigger (dispatch needs the file on the default branch); remove it before merging to master. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e99d4d3 commit f7c383b

5 files changed

Lines changed: 459 additions & 302 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Build and test KataGo (ONNX backend)
2+
description: >
3+
Configure, build, run `katago runtests`, verify the ORT backend is wired up, and stage a
4+
self-contained runnable directory under release/ (katago binary + ORT runtime + EP
5+
runtimes + example config). Expects onnx-prepare-ort to have populated
6+
deps/install/{ort,protobuf,zlib} and the MSVC environment to be ready on Windows.
7+
inputs:
8+
ort_root:
9+
description: Path to the ORT install tree (deps/install/ort)
10+
required: true
11+
ep:
12+
description: Execution provider, used for EP-specific runtime staging
13+
required: true
14+
15+
runs:
16+
using: composite
17+
steps:
18+
- name: Configure KataGo (Windows)
19+
if: runner.os == 'Windows'
20+
shell: pwsh
21+
run: |
22+
cmake -S cpp -B cpp\build -G Ninja -DCMAKE_BUILD_TYPE=Release -DUSE_BACKEND=ONNX `
23+
-DONNXRUNTIME_ROOT=${{ inputs.ort_root }} `
24+
-DProtobuf_PROTOC_EXECUTABLE=${{ github.workspace }}\deps\install\protobuf\bin\protoc.exe `
25+
-DProtobuf_INCLUDE_DIR=${{ github.workspace }}\deps\install\protobuf\include `
26+
-DProtobuf_LIBRARY=${{ github.workspace }}\deps\install\protobuf\lib\libprotobuf.lib `
27+
-DZLIB_INCLUDE_DIR=${{ github.workspace }}\deps\install\zlib\include `
28+
-DZLIB_LIBRARY=${{ github.workspace }}\deps\install\zlib\lib\zlibstatic.lib
29+
30+
- name: Configure KataGo (Linux)
31+
if: runner.os == 'Linux'
32+
shell: bash
33+
run: |
34+
cmake -S cpp -B cpp/build -G Ninja -DCMAKE_BUILD_TYPE=Release -DUSE_BACKEND=ONNX \
35+
-DONNXRUNTIME_ROOT="${{ inputs.ort_root }}" \
36+
-DProtobuf_PROTOC_EXECUTABLE="${{ github.workspace }}/deps/install/protobuf/bin/protoc" \
37+
-DProtobuf_INCLUDE_DIR="${{ github.workspace }}/deps/install/protobuf/include" \
38+
-DProtobuf_LIBRARY="${{ github.workspace }}/deps/install/protobuf/lib/libprotobuf.a" \
39+
-DZLIB_INCLUDE_DIR="${{ github.workspace }}/deps/install/zlib/include" \
40+
-DZLIB_LIBRARY="${{ github.workspace }}/deps/install/zlib/lib/libz.a"
41+
42+
- name: Build KataGo
43+
shell: bash
44+
run: cmake --build cpp/build
45+
46+
- name: Run tests
47+
shell: bash
48+
run: |
49+
if [ "${{ runner.os }}" = "Windows" ]; then ./cpp/build/katago.exe runtests; else ./cpp/build/katago runtests; fi
50+
51+
- name: Verify backend wiring
52+
shell: bash
53+
run: |
54+
# Command substitution flattens multi-line output: testing the raw array for a
55+
# substring is unreliable, so check the flattened string with grep.
56+
if [ "${{ runner.os }}" = "Windows" ]; then OUT=$(cpp/build/katago.exe version 2>&1); else OUT=$(cpp/build/katago version 2>&1); fi
57+
if ! echo "$OUT" | grep -q "ONNX Runtime"; then
58+
echo "unexpected backend version output: $OUT"
59+
exit 1
60+
fi
61+
echo "$OUT" | head -8
62+
63+
- name: Stage release directory (Windows)
64+
if: runner.os == 'Windows'
65+
shell: pwsh
66+
run: |
67+
New-Item -ItemType Directory -Force -Path "release" | Out-Null
68+
Copy-Item "cpp\build\katago.exe" "release\"
69+
Get-ChildItem "deps\install\ort\bin\*.dll" -ErrorAction SilentlyContinue | Copy-Item -Destination "release\" -Force
70+
# EP-specific runtime DLLs
71+
if ("${{ inputs.ep }}" -eq "openvino") {
72+
Get-ChildItem "deps\install\ort\lib\onnxruntime_providers_openvino.dll" -ErrorAction SilentlyContinue | Copy-Item -Destination "release\" -Force
73+
$ovBin = "deps\openvino\runtime\bin\intel64\Release"
74+
if (Test-Path $ovBin) {
75+
Copy-Item "$ovBin\*.dll" "release\"
76+
Copy-Item "$ovBin\*.json" "release\"
77+
} else {
78+
Write-Warning "OpenVINO runtime bin dir not found at $ovBin"
79+
}
80+
$tbb = Get-ChildItem "deps\openvino" -Recurse -Filter "tbb12.dll" -ErrorAction SilentlyContinue | Select-Object -First 1
81+
if ($tbb) { Copy-Item $tbb.FullName "release\" }
82+
}
83+
Copy-Item "cpp\configs\gtp_example.cfg" "release\"
84+
Write-Output "--- release contents ---"
85+
Get-ChildItem "release" | Select-Object Name, Length
86+
87+
- name: Stage release directory (Linux)
88+
if: runner.os == 'Linux'
89+
shell: bash
90+
run: |
91+
mkdir -p release
92+
cp cpp/build/katago release/
93+
cp deps/install/ort/lib/libonnxruntime*.so* release/ 2>/dev/null || true
94+
# EP-specific runtime libs (TensorRT/CUDA/ROCm, etc.) go here once wired up.
95+
cp cpp/configs/gtp_example.cfg release/
96+
ls -la release
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
name: Prepare ONNX Runtime
2+
description: >
3+
Fetch or build an ONNX Runtime install tree carrying the requested execution provider,
4+
plus KataGo's own zlib/protobuf deps. Everything lands under deps/install/ and is
5+
cached, so only the first run pays for ORT acquisition (from-source ORT builds are the
6+
expensive case, 1-3h; prebuilt/nuget are minutes).
7+
inputs:
8+
ep:
9+
description: Execution provider to wire up (cpu, directml, openvino, ...)
10+
required: true
11+
mode:
12+
description: >
13+
How to obtain ORT. 'prebuilt' = official release zip (CPU EP ships inside it),
14+
'nuget' = Microsoft.ML.OnnxRuntime.DirectML package, 'from-source' = build ORT
15+
ourselves with the EP.
16+
required: true
17+
ort_version:
18+
description: ORT release version for prebuilt/nuget modes
19+
required: false
20+
default: "1.28.0"
21+
ort_ref:
22+
description: ORT git ref (tag/SHA) for from-source mode
23+
required: false
24+
default: ""
25+
ov_version:
26+
description: OpenVINO toolkit version (from-source/openvino only)
27+
required: false
28+
default: ""
29+
ov_url:
30+
description: OpenVINO toolkit download URL (from-source/openvino only)
31+
required: false
32+
default: ""
33+
pb_version:
34+
description: protobuf version built for KataGo (3.x, no abseil dependency)
35+
required: false
36+
default: "3.21.12"
37+
pb_tag:
38+
description: >
39+
protobuf release tag for pb_version. protobuf 3.x tags drop the major (3.21.12
40+
-> v21.12), so this cannot be derived from pb_version.
41+
required: false
42+
default: "21.12"
43+
zlib_version:
44+
description: zlib version built for KataGo
45+
required: false
46+
default: "1.3.1"
47+
48+
outputs:
49+
ort_root:
50+
description: Path to the prepared ORT install tree
51+
value: ${{ github.workspace }}/deps/install/ort
52+
53+
runs:
54+
using: composite
55+
steps:
56+
# ---------------------------------------------------------------------------
57+
# Common deps: zlib + protobuf, always built from source and cached separately
58+
# from the ORT tree so a from-source ORT cache miss does not rebuild them.
59+
# ---------------------------------------------------------------------------
60+
- name: Restore common-dep cache
61+
id: cache-common
62+
uses: actions/cache@v4
63+
with:
64+
path: |
65+
deps/install/zlib
66+
deps/install/protobuf
67+
key: onnx-common-${{ runner.os }}-pb-${{ inputs.pb_version }}-zl-${{ inputs.zlib_version }}
68+
69+
- name: Build zlib (static, Windows)
70+
if: steps.cache-common.outputs.cache-hit != 'true' && runner.os == 'Windows'
71+
shell: pwsh
72+
run: |
73+
curl.exe -L -o "$env:RUNNER_TEMP\zlib.tar.gz" "https://github.com/madler/zlib/releases/download/v${{ inputs.zlib_version }}/zlib-${{ inputs.zlib_version }}.tar.gz"
74+
tar -xzf "$env:RUNNER_TEMP\zlib.tar.gz" -C "$env:RUNNER_TEMP"
75+
cmake -S "$env:RUNNER_TEMP\zlib-${{ inputs.zlib_version }}" -B "$env:RUNNER_TEMP\zlib-build" -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}\deps\install\zlib
76+
cmake --build "$env:RUNNER_TEMP\zlib-build"
77+
cmake --install "$env:RUNNER_TEMP\zlib-build"
78+
79+
- name: Build zlib (static, Linux)
80+
if: steps.cache-common.outputs.cache-hit != 'true' && runner.os == 'Linux'
81+
shell: bash
82+
run: |
83+
curl -L -o "$RUNNER_TEMP/zlib.tar.gz" "https://github.com/madler/zlib/releases/download/v${{ inputs.zlib_version }}/zlib-${{ inputs.zlib_version }}.tar.gz"
84+
tar -xzf "$RUNNER_TEMP/zlib.tar.gz" -C "$RUNNER_TEMP"
85+
cmake -S "$RUNNER_TEMP/zlib-${{ inputs.zlib_version }}" -B "$RUNNER_TEMP/zlib-build" -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/deps/install/zlib"
86+
cmake --build "$RUNNER_TEMP/zlib-build"
87+
cmake --install "$RUNNER_TEMP/zlib-build"
88+
89+
- name: Build protobuf (static, /MD, Windows)
90+
if: steps.cache-common.outputs.cache-hit != 'true' && runner.os == 'Windows'
91+
shell: pwsh
92+
run: |
93+
curl.exe -L -o "$env:RUNNER_TEMP\pb.tar.gz" "https://github.com/protocolbuffers/protobuf/releases/download/v${{ inputs.pb_tag }}/protobuf-cpp-${{ inputs.pb_version }}.tar.gz"
94+
tar -xzf "$env:RUNNER_TEMP\pb.tar.gz" -C "$env:RUNNER_TEMP"
95+
# protobuf_MSVC_STATIC_RUNTIME=OFF is REQUIRED: the protobuf default (/MT) would
96+
# clash with KataGo's /MD Release build (LNK2038) when linking libprotobuf statically.
97+
cmake -S "$env:RUNNER_TEMP\protobuf-${{ inputs.pb_version }}" -B "$env:RUNNER_TEMP\pb-build" -G Ninja `
98+
-DCMAKE_BUILD_TYPE=Release `
99+
-Dprotobuf_BUILD_TESTS=OFF `
100+
-Dprotobuf_BUILD_SHARED_LIBS=OFF `
101+
-Dprotobuf_MSVC_STATIC_RUNTIME=OFF `
102+
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}\deps\install\protobuf
103+
cmake --build "$env:RUNNER_TEMP\pb-build"
104+
cmake --install "$env:RUNNER_TEMP\pb-build"
105+
106+
- name: Build protobuf (static, Linux)
107+
if: steps.cache-common.outputs.cache-hit != 'true' && runner.os == 'Linux'
108+
shell: bash
109+
run: |
110+
curl -L -o "$RUNNER_TEMP/pb.tar.gz" "https://github.com/protocolbuffers/protobuf/releases/download/v${{ inputs.pb_tag }}/protobuf-cpp-${{ inputs.pb_version }}.tar.gz"
111+
tar -xzf "$RUNNER_TEMP/pb.tar.gz" -C "$RUNNER_TEMP"
112+
cmake -S "$RUNNER_TEMP/protobuf-${{ inputs.pb_version }}" -B "$RUNNER_TEMP/pb-build" -G Ninja \
113+
-DCMAKE_BUILD_TYPE=Release \
114+
-Dprotobuf_BUILD_TESTS=OFF \
115+
-Dprotobuf_BUILD_SHARED_LIBS=OFF \
116+
-DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/deps/install/protobuf"
117+
cmake --build "$RUNNER_TEMP/pb-build"
118+
cmake --install "$RUNNER_TEMP/pb-build"
119+
120+
# ---------------------------------------------------------------------------
121+
# ONNX Runtime install tree, cached per (os, ep, version/ref).
122+
# ---------------------------------------------------------------------------
123+
- name: Restore ORT cache
124+
id: cache-ort
125+
uses: actions/cache@v4
126+
with:
127+
path: deps/install/ort
128+
key: onnx-ort-${{ runner.os }}-${{ inputs.ep }}-${{ inputs.ort_version }}-${{ inputs.ort_ref }}
129+
130+
# --- prebuilt: official ORT release zip (CPU EP) ---
131+
- name: Fetch prebuilt ORT (Windows)
132+
if: inputs.mode == 'prebuilt' && runner.os == 'Windows' && steps.cache-ort.outputs.cache-hit != 'true'
133+
shell: pwsh
134+
run: |
135+
New-Item -ItemType Directory -Force -Path "deps\install\ort" | Out-Null
136+
curl.exe -sfL -o "$env:RUNNER_TEMP\ort.zip" "https://github.com/microsoft/onnxruntime/releases/download/v${{ inputs.ort_version }}/onnxruntime-win-x64-${{ inputs.ort_version }}.zip"
137+
Expand-Archive -Path "$env:RUNNER_TEMP\ort.zip" -DestinationPath "$env:RUNNER_TEMP\ort" -Force
138+
$inner = Get-ChildItem "$env:RUNNER_TEMP\ort" -Directory | Select-Object -First 1
139+
if ($inner) {
140+
Get-ChildItem $inner.FullName | Move-Item -Destination "deps\install\ort" -Force
141+
Remove-Item $inner.FullName -Recurse -Force
142+
}
143+
Remove-Item "$env:RUNNER_TEMP\ort.zip" -Force
144+
# Hoist lib/*.dll into bin/ too: the release-staging step globs bin/.
145+
New-Item -ItemType Directory -Force -Path "deps\install\ort\bin" | Out-Null
146+
Get-ChildItem "deps\install\ort\lib\*.dll" -ErrorAction SilentlyContinue | Copy-Item -Destination "deps\install\ort\bin" -Force
147+
148+
# --- nuget: Microsoft.ML.OnnxRuntime.DirectML package (DirectML EP) ---
149+
- name: Fetch DirectML NuGet package (Windows)
150+
if: inputs.mode == 'nuget' && runner.os == 'Windows' && steps.cache-ort.outputs.cache-hit != 'true'
151+
shell: pwsh
152+
run: |
153+
$src = "$env:RUNNER_TEMP\dml"
154+
New-Item -ItemType Directory -Force -Path "$src" | Out-Null
155+
curl.exe -sfL -o "$src\dml.nupkg" "https://api.nuget.org/v3-flatcontainer/microsoft.ml.onnxruntime.directml/${{ inputs.ort_version }}/microsoft.ml.onnxruntime.directml.${{ inputs.ort_version }}.nupkg"
156+
tar -xzf "$src\dml.nupkg" -C "$src"
157+
$root = "deps\install\ort"
158+
New-Item -ItemType Directory -Force -Path "$root\include","$root\lib","$root\bin" | Out-Null
159+
Copy-Item "$src\build\native\include\*" "$root\include" -Force
160+
Copy-Item "$src\runtimes\win-x64\native\onnxruntime.lib" "$root\lib" -Force
161+
Get-ChildItem "$src\runtimes\win-x64\native\*.dll" | Copy-Item -Destination "$root\lib" -Force
162+
Get-ChildItem "$root\lib\*.dll" | Copy-Item -Destination "$root\bin" -Force
163+
164+
# --- from-source: build ORT ourselves with the requested EP ---
165+
- name: Checkout ONNX Runtime source
166+
if: inputs.mode == 'from-source' && steps.cache-ort.outputs.cache-hit != 'true'
167+
uses: actions/checkout@v4
168+
with:
169+
repository: microsoft/onnxruntime
170+
ref: ${{ inputs.ort_ref }}
171+
path: deps/onnxruntime
172+
submodules: recursive
173+
174+
- name: Fetch OpenVINO toolkit (Windows)
175+
if: inputs.mode == 'from-source' && inputs.ep == 'openvino' && runner.os == 'Windows' && steps.cache-ort.outputs.cache-hit != 'true'
176+
shell: pwsh
177+
run: |
178+
$zip = "$env:RUNNER_TEMP\openvino.zip"
179+
$dest = "deps\openvino"
180+
Invoke-WebRequest -Uri "${{ inputs.ov_url }}" -OutFile $zip
181+
Expand-Archive -Path $zip -DestinationPath $dest
182+
# The zip contains a single top-level directory of the same name; hoist its contents up.
183+
$inner = Get-ChildItem -Path $dest -Directory | Select-Object -First 1
184+
if ($inner) {
185+
Get-ChildItem -Path $inner.FullName | Move-Item -Destination $dest -Force
186+
Remove-Item -Path $inner.FullName -Recurse -Force
187+
}
188+
Remove-Item -Path $zip -Force
189+
$sv = Get-ChildItem "deps\openvino" -Recurse -Filter "setupvars.bat" | Select-Object -First 1
190+
if (-not $sv) { throw "setupvars.bat not found under deps\openvino" }
191+
echo "OV_SETUPVARS=$($sv.FullName)" >> $env:GITHUB_ENV
192+
193+
- name: Build ONNX Runtime with OpenVINO EP
194+
if: inputs.mode == 'from-source' && inputs.ep == 'openvino' && steps.cache-ort.outputs.cache-hit != 'true'
195+
shell: cmd
196+
working-directory: deps/onnxruntime
197+
run: |
198+
call "%OV_SETUPVARS%"
199+
python tools\ci_build\build.py --build_dir build --config Release --use_openvino GPU --build_shared_lib --skip_tests --parallel --compile_no_warning_as_error --cmake_generator Ninja --cmake_extra_defines CMAKE_INSTALL_PREFIX=%CD%\..\install\ort
200+
if errorlevel 1 exit /b 1
201+
cmake --install build\Release --config Release
202+
if errorlevel 1 exit /b 1
203+
204+
# NOTE: TensorRT / MIGraphX from-source builds slot in here once validated. They need
205+
# CUDA+TensorRT SDK (ubuntu) / ROCm respectively, and github-hosted runners have no GPU,
206+
# so each should be smoke-validated on a GPU machine before being wired into the matrix.
207+
208+
- name: Report ORT install tree
209+
shell: bash
210+
run: |
211+
ls -la deps/install/ort
212+
ls deps/install/ort/bin 2>/dev/null || ls deps/install/ort/lib 2>/dev/null || true

0 commit comments

Comments
 (0)