Skip to content

CI — eosllm

CI — eosllm #19

Workflow file for this run

name: ci
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
# Nightly run at 06:00 UTC. Catches drift from
# external dependencies (e.g. compiler updates on the GHA
# ubuntu-latest image) without slowing PR-gating.
- cron: '0 6 * * *'
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
host-build:
name: ${{ matrix.os }} / ${{ matrix.compiler }} / ${{ matrix.build }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
compiler: [ gcc, clang ]
build: [ debug, release ]
exclude:
# macOS runners ship clang as `cc`; gcc is a homebrew alias and we
# don't bother installing it here.
- os: macos-latest
compiler: gcc
# Windows runners under MSYS2 ship gcc; clang isn't part of the
# default mingw64 stack we install.
- os: windows-latest
compiler: clang
defaults:
run:
# On Windows, route every step through MSYS2 so `make`,
# `aarch64-linux-gnu-gcc`-style invocations, etc. work the same
# as on POSIX runners. Other OSes use the default bash.
shell: ${{ matrix.os == 'windows-latest' && 'msys2 {0}' || 'bash' }}
steps:
- uses: actions/checkout@v4
- name: Set up MSYS2 (windows only)
if: matrix.os == 'windows-latest'
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
base-devel
git
mingw-w64-x86_64-gcc
mingw-w64-x86_64-make
- name: Show toolchain
run: |
${{ matrix.compiler }} --version
make --version
- name: Show resolved feature flags
run: |
if [ "${{ matrix.os }}" = "windows-latest" ]; then
mingw32-make CC=${{ matrix.compiler }} BUILD=${{ matrix.build }} \
EOSLLM_HAVE_WIN32=1 EOSLLM_HAVE_POSIX=0 config
else
make CC=${{ matrix.compiler }} BUILD=${{ matrix.build }} config
fi
- name: Build static library
run: |
if [ "${{ matrix.os }}" = "windows-latest" ]; then
mingw32-make CC=${{ matrix.compiler }} BUILD=${{ matrix.build }} \
EOSLLM_HAVE_WIN32=1 EOSLLM_HAVE_POSIX=0 \
CFLAGS_EXTRA="-DWIN32_LEAN_AND_MEAN" lib
else
make CC=${{ matrix.compiler }} BUILD=${{ matrix.build }} lib
fi
- name: Build and run unit tests
run: |
if [ "${{ matrix.os }}" = "windows-latest" ]; then
mingw32-make CC=${{ matrix.compiler }} BUILD=${{ matrix.build }} \
EOSLLM_HAVE_WIN32=1 EOSLLM_HAVE_POSIX=0 \
CFLAGS_EXTRA="-DWIN32_LEAN_AND_MEAN" test
else
make CC=${{ matrix.compiler }} BUILD=${{ matrix.build }} test
fi
- name: Stripped library size
if: matrix.build == 'release' && matrix.os != 'windows-latest'
run: |
ls -l libeosllm.a
# When we add a shared-library target this will report the
# stripped binary size; for now it's just the archive size.
cross-aarch64:
name: ubuntu / aarch64 / qemu
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install cross toolchain and qemu
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user-static
- name: Build for aarch64 (static)
run: |
make CC=aarch64-linux-gnu-gcc BUILD=release \
CFLAGS_EXTRA="-static" \
LDFLAGS_EXTRA="-static" \
lib
- name: Build and run unit tests under qemu (static)
run: |
make CC=aarch64-linux-gnu-gcc BUILD=release \
CFLAGS_EXTRA="-static" \
LDFLAGS_EXTRA="-static" \
test
sanitize:
name: ubuntu / clang / asan + ubsan + leaksan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install clang
run: |
sudo apt-get update
sudo apt-get install -y clang
- name: Show toolchain
run: clang --version
- name: Build + run tests under sanitizers
env:
ASAN_OPTIONS: detect_leaks=1:abort_on_error=1:halt_on_error=1
UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1:halt_on_error=1
run: make CC=clang sanitize
determinism:
name: ubuntu / determinism (3-iteration bit-identical)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: make BUILD=release lib
- name: Run 3-iteration determinism check
run: make BUILD=release determinism
fuzz-eosm:
name: ubuntu / clang / libfuzzer + asan (eosm reader, 30s)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install clang
run: |
sudo apt-get update
sudo apt-get install -y clang
- name: Build seed corpus
run: make fuzz-corpus
- name: Build libFuzzer harness
run: make fuzz-eosm
- name: Run fuzz_eosm for 30 seconds
env:
ASAN_OPTIONS: detect_leaks=1:abort_on_error=1:halt_on_error=1
UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1:halt_on_error=1
run: |
./tests/fuzz/fuzz_eosm tests/fuzz/corpus \
-max_total_time=30 \
-print_final_stats=1 \
-timeout=5 \
-rss_limit_mb=512
fuzz-gguf:
name: ubuntu / clang / libfuzzer + asan (gguf reader, 30s)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install clang
run: |
sudo apt-get update
sudo apt-get install -y clang
- name: Build GGUF seed corpus
run: make fuzz-corpus-gguf
- name: Build libFuzzer harness
run: make fuzz-gguf
- name: Run fuzz_gguf for 30 seconds
env:
ASAN_OPTIONS: detect_leaks=1:abort_on_error=1:halt_on_error=1
UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1:halt_on_error=1
run: |
./tests/fuzz/fuzz_gguf tests/fuzz/corpus_gguf \
-max_total_time=30 \
-print_final_stats=1 \
-timeout=15 \
-rss_limit_mb=512
benchmark:
name: ubuntu / matmul microbenchmark (perf snapshot)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build + run benchmark
run: make benchmark
- name: Show JSON
run: cat docs/benchmarks/host.json
- name: Upload benchmark artifact
uses: actions/upload-artifact@v4
with:
name: bench-${{ github.sha }}
path: docs/benchmarks/host.json
if-no-files-found: error
static-checks:
name: ubuntu / static checks (error uniqueness + include firewall)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: make check-errors
run: make check-errors
- name: make check-includes
run: make check-includes
nightly-all-checks:
name: ubuntu / nightly all-checks (cron only)
runs-on: ubuntu-latest
if: ${{ github.event_name == 'schedule' }}
steps:
- uses: actions/checkout@v4
- name: Install clang (for sanitize chain)
run: |
sudo apt-get update
sudo apt-get install -y clang
- name: make all-checks
env:
EOSLLM_SKIP_BENCH_DIFF: '1'
run: make CC=clang all-checks
smoke-cli:
name: ubuntu / cli lifecycle smoke (synthetic GGUF)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install clang (for sanitize-cli)
run: |
sudo apt-get update
sudo apt-get install -y clang
- name: Build + run all three smoke variants (default build)
run: make smoke-all
- name: Build + run smoke under ASan + UBSan + LeakSan
env:
ASAN_OPTIONS: detect_leaks=1:abort_on_error=1:halt_on_error=1
UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1:halt_on_error=1
run: make CC=clang sanitize-cli
- name: Run --smoke-bad-magic + --last-error under sanitizers
env:
ASAN_OPTIONS: detect_leaks=1:abort_on_error=1:halt_on_error=1
UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1:halt_on_error=1
run: |
./tools/eosllm-cli/eosllm-cli --smoke-bad-magic > /dev/null
./tools/eosllm-cli/eosllm-cli --last-error > /dev/null
- name: Build + run bench under sanitizers
env:
ASAN_OPTIONS: detect_leaks=1:abort_on_error=1:halt_on_error=1
UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1:halt_on_error=1
run: make CC=clang sanitize-bench
server-smoke:
name: ubuntu / eosllm-server lifecycle smoke
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build server
run: make BUILD=release server
- name: make server-smoke
run: make server-smoke