Repository navigation
ci: decouple builds into actions and test every package in Build and Test - #875
Merged
Merged
Conversation
Split the build logic out of windows-build.yml, ubuntu-build.yml and debian-portable.yml into composite actions, driven by two matrix workflows: - .github/actions/win-build: builds one Windows variant (XRT, HRX, Source); build only. - .github/actions/win-msi: builds the MSI around an already-built flm.exe. - .github/actions/lin-build: builds one Linux variant (XRT-deb, HRX-deb, XRT-portable, HRX-portable, Source-portable) in the build-environment container. - win-build.yml / lin-build.yml: expand "all" (or a variant list) into a matrix, package, upload, and publish releases on tags. Artifact names are unchanged. The CPU-only d3-contract and chat-continue tests move to cpu-tests.yml. New HRX .deb: debian/rules takes FLM_USE_HRX and FLM_CMAKE_ARGS from the environment, and Depends on libxrt-npu2 only for the XRT package. HRX debs are built but not released yet. asr-test.yml, model-sweep.yml and resolve_build.sh still look up the removed workflow files and are aligned in a follow-up. Co-Authored-By: Claude <noreply@anthropic.com>
release.yml builds the tagged commit (XRT and HRX for both platforms, no models-from-source) by calling win-build.yml and lin-build.yml, then publishes every asset to the tag's release. It builds the tag itself rather than reusing main's artifacts, since the version comes from git describe at build time. The XRT and HRX assets publish in two jobs so a failed HRX build cannot hold back the default release. The HRX job runs after the XRT one so the two never race to create the release. The HRX .debs are now released too. win-build.yml and lin-build.yml no longer run on tags or publish, and lin-build.yml drops test-summary, which reported success even when the build failed. Co-Authored-By: Claude <noreply@anthropic.com>
The HRX package ships its own libtinfo, libedit, curl and others next to libhrx, and that directory is on flm's BUILD_RPATH. The linker searches BUILD_RPATH for the dependencies of shared libraries, so in non-portable HRX builds the system libedit resolved its libtinfo.so.6 to the HRX copy, which has no NCURSES6_TINFO symbol versions, and the link failed with undefined tgoto/tgetent/... references. Put the system library directory on -rpath-link, which the linker searches before the rpath. It applies only at link time, so the installed RPATH is unchanged. XRT and portable builds are not affected. Co-Authored-By: Claude <noreply@anthropic.com>
Build and Test (build-and-test.yml) replaces Model Sweep and ASR Test. It builds each package with its own call of lin-build.yml / win-build.yml and tests it on the NPU runners as soon as that build finishes, instead of a separate workflow polling for the build run: - Linux XRT and HRX portable: the pr-tier suites on gpt and strix runners. - Windows XRT and HRX zip: the pr-tier suites on gpt runners (the only Windows strix runner is offline). - Ubuntu 24.04 .deb and the MSI: an install test, falling back to the unpacked payload when the runner cannot install software. - models-from-source: the Gemma 4 engines. XRT tests gate the HRX ones on the same platform, since HRX is a preview. Docs-only changes build and test nothing, a new commit cancels a pull request's previous run, and a nightly run tests every model. The tests are a new stdlib-only harness, .github/script/npu_test, with suites for chat (one model per engine family, plus every model of a family the change touches), serving (queue, cancel, disconnect, model switch), prefix_cache (multi-slot KV cache hits and LRU eviction), api (src/test/openai_api_test and openai_usage, never run in CI before), embedding, decision (d3, no longer tied to the docs) and asr (Whisper plus chat transcription for Gemma 4 and Nemotron 3.5). release.yml runs the same build and tests on the tag and publishes each backend only when all of its packages passed. lin-build.yml and win-build.yml become dispatch/call only. The old sweep and ASR scripts, resolve_build.sh and asr_gate.sh are removed; the CI helpers move to .github/script/ci and the test assets under npu_test/assets. Co-Authored-By: Claude <noreply@anthropic.com>
The script moved into .github/script/ci and still looked for windows-deps one directory up, so every Windows build failed at the dependency step. Co-Authored-By: Claude <noreply@anthropic.com>
The models-from-source test asked for gemma4-it:e2b and e4b, but the list only filtered the tier's own pick, which has e2b alone. Co-Authored-By: Claude <noreply@anthropic.com>
FLM_CONFIG_PATH names the model_list.json file, not its directory, so pointing it at share/flm made flm list abort. flm already finds ../share/flm next to its binary, so the unpacked tree needs no overrides. A catalog that cannot be read is now a failed case in the report instead of a traceback with no report. Co-Authored-By: Claude <noreply@anthropic.com>
- detect-changes: diff a pull request's own head against its base. Its merge commit also carried main's newer d3 changes, so the pr tier tested every d3 model for a PR that touched none. - serving/concurrent-complete: route-check with echoed words instead of capitals; qwen3:0.6b named Verona the capital of Italy on both gpt and strix, which says nothing about request routing. - decision/goldens: warn, not fail, for a model with no goldens yet (d3:flash, new on main); its other cases still run. Co-Authored-By: Claude <noreply@anthropic.com>
qwen3:0.6b gets both capitals and echo prompts wrong, so asserting the answer tested the model, not the queue. Each prompt is now sent alone for its greedy reference reply, then all together: a reply matching another prompt's reference is a mix-up and fails, one that merely differs warns, since NPU greedy decoding is not always reproducible. Co-Authored-By: Claude <noreply@anthropic.com>
gpt and strix runners gave identical results (337 cases each), so the second leg only cost NPU time. Windows keeps asking for a gpt runner, which is what keeps its jobs off xsjnuckrck01: that runner carries the npu and sweep labels but has dropped every job since 2026-10-28. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
On strix the serving suite hit a server bug: after "Client disconnected; cancelling active request" the NPU lock was never released. The stuck process then survived SIGKILL and kept port 52625, so every later suite failed to start with "Address already in use". - Each server starts on a free port unless --port fixes one. - A server that survives SIGKILL is reported as a server-stop failure. - serving restarts its server when the NPU stays busy after the disconnect or cancel case, instead of timing out case after case. Co-Authored-By: Claude <noreply@anthropic.com>
On xconucstr260 a server from the previous run got stuck in the NPU driver; the next job's server then hung at start for 300 s. npu-test now kills flm processes left under the runner's work directory first, and fails at once, naming the runner to reboot, when one survives. Co-Authored-By: Claude <noreply@anthropic.com>
/api/cancel registers itself under the request_id it names and cancels itself (server.cpp, process_task), so the case can only report that bug. It is skipped with that reason; deleting the skip() turns it back on once the server is fixed. Co-Authored-By: Claude <noreply@anthropic.com>
The Windows runner xconucgpt1-21 sets FLM_SERVE_PORT=52625, which the harness honoured, and something on that machine holds 52625, so every server failed to bind (WSAEACCES). Only --port fixes a port now. Co-Authored-By: Claude <noreply@anthropic.com>
- changes.py outputs the suites a change can affect: an ASR-only change runs asr, a d3-only change decision, an engine change chat and prefix_cache (and asr for engines with an audio encoder), a test script its own suite. Any shared file runs every suite, as do the nightly, dispatch and release runs. - HRX packages skip api and serving, which test server logic the backend does not touch; the XRT run covers them. - HRX tests no longer wait for the XRT tests, so both run at once. - The models-from-source tests run only when the chat suite does. - The .deb and MSI install tests are off unless the repository variable FLM_INSTALL_TESTS is "true", since the runners cannot install yet. - The release verdict counts each backend's builds and portable tests; a test skipped because the change did not touch it counts as passed. Co-Authored-By: Claude <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Restructures CI around one workflow, Build and Test, that builds every FastFlowLM package and tests each one on the NPU runners as soon as its own build finishes.
Builds
.github/actions/win-buildXRT,HRX, orSource(engines built from source). Build only..github/actions/win-msiflm.exe..github/actions/lin-buildXRT-deb,HRX-deb,XRT-portable,HRX-portable,Source-portable) in the build-environment container.lin-build.yml/win-build.ymlworkflow_callonly: expand a variant (orall) into a matrix, package, upload. Artifact names unchanged..debfor every distro:debian/rulesreadsFLM_USE_HRX/FLM_CMAKE_ARGS,Depends: libxrt-npu2only for XRT, andsrc/CMakeLists.txtlinks non-portable HRX builds with-rpath-linkto the system lib dir (the HRX SDK ships an unversionedlibtinfothat broke the link).Build and Test (
build-and-test.yml)apiandserving, which test server logic the backend does not touch..github/script/ci/changes.py): an ASR-only change runsasr, a d3-only changedecision, an engine changechat+prefix_cache; shared code runs everything. Docs-only changes build and test nothing.fulltier) tests every catalog model and every suite..deb/ MSI install tests are off unless the repository variableFLM_INSTALL_TESTSistrue(the runners cannot install yet: no passwordless sudo on Linux, an FLM already installed on Windows).flmprocesses left by earlier jobs are cleared before testing; a runner whose NPU is held by an unkillable one fails at once, named.detect-changes,install-package,remove-package,npu-test.NPU test harness (
.github/script/npu_test)Stdlib-only Python, server mode, replaces
sweep_*.pyandasr_test.py:chatserving/api/cancelskipped until fixed)prefix_cache--prefix-slots 2, cached vs cold replyapisrc/test/openai_api_test+src/test/openai_usage(tools, logprobs, response_format, reasoning, sampling, continue_final_message, errors), never run in CI beforeembeddingdecisionasrexpected.json, formats, segments, language, prompt; chat transcription for gemma4-it e2b/e4b/12b and nemotron3.5-boltRelease
release.ymlruns Build and Test on the tag (no models-from-source) and publishes each backend only when all of its packages passed. HRX debs are now released with the HRX assets.Removed
windows-build.yml,ubuntu-build.yml,debian-portable.yml,model-sweep.yml,asr-test.yml,resolve_build.sh,asr_gate.sh,sweep_*.py,asr_test.py,asr_summary.py. The CPU-only d3-contract / chat-continue tests move tocpu-tests.ymlunchanged.Known server bugs found by the new tests (not fixed here)
/api/cancelregisters itself under therequest_idit names and cancels itself (src/server/server.cpp,process_task);serving/api-cancelis skipped until fixed.HttpSession::send_chunk_dataskipsactive_connections_.fetch_sub).min_pis read as an integer (rest_handler.cpp:815).Notes for reviewers
Test Linux XRT portable); update branch protection if any are required.expected.jsoninstead of re-running main's build as a baseline.xsjnuckrck01drops every job ("lost communication");xconucgpt1-21setsFLM_SERVE_PORT=52625and something there holds that port (the harness now always picks a free port).d3:flashhas no goldens file yet, so its goldens case warns.Test plan
actionlintclean;changes.pyunit tests (17)flm.debon 4 distrosfulltier) after mergerelease.yml🤖 Generated with Claude Code