Skip to content

v0.2.9

v0.2.9 #121

Workflow file for this run

name: ci
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
build:
name: build (${{ matrix.os }}, ${{ matrix.backend }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: macos-14 # Apple silicon
backend: metal
artifact: chimera-macos-arm64
- os: ubuntu-latest # x86_64
backend: cpu
artifact: chimera-linux-x86_64
- os: windows-latest # x86_64 MSVC
backend: cpu
artifact: chimera-windows-x86_64.exe
env:
# macOS binary stays portable to this minimum OS.
MACOSX_DEPLOYMENT_TARGET: "12.0"
# Default to bash on every leg so Makefile + scripts/test.py work
# uniformly. windows-latest ships git-bash; this avoids per-OS shell
# forks for build / smoke / stage-artifact steps.
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v6
- name: install linux deps
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential cmake git python3 libssl-dev
- name: install macos deps
if: runner.os == 'macOS'
run: |
# Xcode CLT ships clang, cmake-via-brew, git. cmake is usually
# pre-installed on GitHub runners; install only if absent.
if ! command -v cmake >/dev/null 2>&1; then brew install cmake; fi
- name: install windows deps
if: runner.os == 'Windows'
run: |
# windows-latest preinstalls cmake, git, python, MSVC, perl,
# OpenSSL, and a git-bash shell. We rely on the runner-provided
# OpenSSL for llama.cpp's LLAMA_OPENSSL=ON. If the build fails
# finding it, add `choco install openssl -y` here.
cmake --version
python --version
where cl.exe || true
- name: setup msvc
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
- name: cache thirdparty
uses: actions/cache@v5
with:
path: thirdparty
# Keyed on manage.py (which pins the three dep versions) + CMake
# files. Bust the cache on any dep-affecting change.
key: thirdparty-${{ runner.os }}-${{ matrix.backend }}-${{ hashFiles('scripts/manage.py', 'CMakeLists.txt', 'src/chimera/CMakeLists.txt') }}
- name: build
run: make build
- name: smoke
run: make smoke
# Combined-archive link contract: builds the three redistributable
# archives (libchimera{,_thirdparty,_ggml}.a) and links tests/external
# the way a non-CMake consumer does, exercising ggml backend
# registration + symbol resolution. This is the seam that `make smoke`
# (executable-only) does NOT cover -- the 0.2.3 libwebp/libwebm combine
# regression shipped silently for exactly this reason. No model files
# needed (the inference probe is gated behind CHIMERA_SMOKE_MODEL).
#
# Linux + macOS only for now. combine_archives.py's Windows path
# construction is wrong (it looks for src/libllama.lib but MSVC emits
# src/Release/llama.lib -- no lib prefix, extra config subdir), so the
# combined archives have never built on Windows. Tracked in TODO.md
# ("combine_archives.py Windows path support"); until then the Windows
# leg still covers build + smoke + db migration.
- name: combined-archive link contract
if: runner.os != 'Windows'
run: make test-external-smoke
# Schema migration ladder: v1 -> latest on a temp DB, asserting the
# upgrade advances user_version and preserves pre-existing rows. Guards
# every existing user's DB against a bad migration on version bumps.
- name: db migration ladder
run: make test-db-migrate
# Python bindings: provision the build toolchain via uv, build the
# nanobind module against the same three archives, and run the no-model
# pytest suite (module import, exported classes, option round-trips,
# live-handle semantics, bad-path error translation). Model-gated tests
# SKIP without model files. Non-Windows: the `make bindings` recipe uses
# the POSIX `bin/python` venv layout (uv on Windows emits Scripts/).
- name: install uv
if: runner.os != 'Windows'
uses: astral-sh/setup-uv@v6
- name: python bindings
if: runner.os != 'Windows'
run: make test-bindings-pytest
- name: stage artifact
run: |
mkdir -p dist
# MSVC produces build/Release/chimera.exe; everywhere else it's
# build/chimera. Probe and copy whichever exists.
if [[ -f build/chimera ]]; then
cp build/chimera "dist/${{ matrix.artifact }}"
elif [[ -f build/Release/chimera.exe ]]; then
cp build/Release/chimera.exe "dist/${{ matrix.artifact }}"
elif [[ -f build/chimera.exe ]]; then
cp build/chimera.exe "dist/${{ matrix.artifact }}"
else
echo "could not locate built chimera binary" >&2
ls -la build/ build/Release/ 2>&1 || true
exit 1
fi
(cd dist && \
(sha256sum "${{ matrix.artifact }}" 2>/dev/null || shasum -a 256 "${{ matrix.artifact }}") \
> "${{ matrix.artifact }}.sha256")
- uses: actions/upload-artifact@v7
with:
name: ${{ matrix.artifact }}
path: dist/${{ matrix.artifact }}*
if-no-files-found: error
# Roll the three per-OS artifacts (each a binary + its .sha256) into one
# downloadable bundle so a release-grabber can pull every platform in a
# single click instead of three. Uses the merge subaction, which stitches
# already-uploaded artifacts together over the API -- no rebuild, no
# re-download into the job. The per-OS artifacts are KEPT (delete-merged:
# false) so the single-platform download path still works.
#
# if: always() so a green leg still gets collected when another leg fails;
# the matrix is fail-fast: false, so partial bundles are the common case on
# a broken PR. The merge errors only if NO artifact matched the pattern
# (all legs failed) -- acceptable, there is nothing to collect then.
collect:
name: collect artifacts
needs: build
if: always()
runs-on: ubuntu-latest
steps:
- name: merge per-OS artifacts into one bundle
uses: actions/upload-artifact/merge@v7
with:
name: chimera-all
pattern: chimera-*
delete-merged: false