The reusable workflow passed free-disk-space: 'true' on the strength of one
claim, repeated in three places here: "ubuntu-latest ships ~14 GiB free". That
came from this project's notes, written before GitHub upgraded the hosted
runners. A real run of the Windows job reports
/dev/root 145G 37G 108G 26% /
108 GiB available. The step was deleting ~10 GiB into 108 GiB of slack and
charging ~20 s per job for it.
The input stays, still defaulting to false, so a job that is genuinely
disk-bound can opt in -- with the description now telling the next reader to
measure rather than inherit the number. The step itself prints df before it
deletes, so the same mistake cannot be made silently twice.
Not retagged: v1 still points at the previous commit. logos-package-manager's
merged doctests workflow consumes @v1, so moving the tag is a release affecting
a live caller rather than a repo-local change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
logos-windows-ci
Windows CI for the Logos fleet: cross-build a repo's x86_64-windows
target on an ordinary Linux runner, then run the result on a real
windows-latest runner. That hand-off is the whole design — Nix does not run on
Windows, so the build and the execution cannot be the same job.
One repo, one concern, one tag train — the same shape as setup-nix-cache-action
and logos-modules-release-action. A GitHub tag is repo-wide, so anything
sharing this repo shares v1, and a Linux or macOS harness has no reason to be
versioned in lockstep with a Windows one. When a second platform wants this
treatment it gets its own repo, not a wider tag here.
nix-setup is the one thing here that is not Windows-specific, and it stays for
now because it is two steps deep (disk reclaim and a read-only-cache warning
around logos-co/setup-nix-cache-action) — too little to justify a repo of its
own until a second consumer actually appears. It extracts cleanly when one does.
Using it
One file in your repo, from
.github/workflows/windows.yml.template:
jobs:
windows:
uses: logos-co/logos-windows-ci/.github/workflows/windows-ci.yml@v1
secrets: inherit
with:
targets: lgx
smoke-file: .github/smoke/lgx-cli.sh
That is the entire per-repo cost. The Nix install and cache, the target-existence guard, the cold-cache refusal, the PE-format and import-closure gates, the artifact hand-off and its round-trip check, the wine pre-filter and the real-Windows execution all live here.
Read docs/windows-ci.md before adding a caller.
It covers the staged-tree path contract (every smoke path starts with a target
name — lgx/bin/lgx.exe, never bin/lgx.exe), what run does and does not
claim, and why a repo with no packages.x86_64-windows must not get this file.
What is here
| path | what it is |
|---|---|
.github/workflows/windows-ci.yml |
the reusable workflow (workflow_call) |
.github/actions/nix-setup |
Nix + the Logos cache + disk reclaim |
.github/actions/windows-gates |
PE-format and import-closure gates |
.github/actions/windows-smoke |
runs a caller's smoke script on wine and on Windows |
.github/lint-actions.sh |
the lint actionlint cannot do — see below |
flake.nix |
pins the two tools the actions read (mingw objdump, wine) |
.github/actions/<name>/ is a required depth, not a style choice: two of
the actions resolve their tool from $GITHUB_ACTION_PATH/../../.., which is
this repo's checkout root only at that nesting.
Versioning
v1 is one train: the workflow and all three actions are tagged from the same
commit and move together. Callers use the tag. Pinning a caller to a SHA while
the workflow's internal refs still say @v1 silently mixes two commits.
Linting
.github/lint-actions.sh exists because "actionlint is clean" covers less than
it sounds like — actionlint's default scope is .github/workflows only, so
action.yml files go unlinted entirely, and it substitutes a placeholder for
every expression interpolation before handing a script to shellcheck, so it is
structurally incapable of catching interpolation-into-shell. Both linters run
in lint-ci.yml; neither subsumes the other.
nix develop -c bash .github/lint-actions.sh # lint
nix develop -c bash .github/lint-actions.sh --self-test # prove each rule fires
Relationship to logos-nix
logos-co/logos-nix owns the Windows
cross-compilation overlay and the fleet's nixpkgs/Qt pin, and is a flake
input of ~36 repos. This repo owns the CI harness and is a flake input of
nothing.
They were one repo and are separate because they need opposite change cadences on the same ref: nothing Nix-side reads a tag, so every consumer resolves logos-nix's default branch, and a CI-YAML commit there changes derivation hashes for anything that records the input's rev. The harness should be free to move on every fix.
logos-nix keeps windows-cache-prime.yml, which is genuinely bound to the
overlay — its trigger watches flake.lock and nix/windows/**, which no
external repo can express.
The flake.nix here is deliberately not built on logos-nix. It reproduces
the two attributes the actions read — the mingw objdump and wine — from stock
nixpkgs, verified byte-identical by drvPath. That equivalence holds under
buildPackages and for stock native attributes and does not generalise:
overlay-free pkgsWindows.qt6.qtbase does not even evaluate. If a gate ever
needs a real cross-compiled attribute, this flake stops being sufficient.
Status
Nothing here has ever run on a runner. It was extracted from an unmerged, unpushed branch of logos-nix, with the individual pieces exercised locally. Treat the first caller as the acceptance test, and enable exactly one.