GitHub Action that installs the Zig compiler, verifies the download against the official minisign signature, and caches the global Zig cache between runs.
- uses: actions/checkout@v4
- uses: xyzzylabs/setup-zig@v1
- run: zig build testThat's it — no inputs needed. The action reads minimum_zig_version (or
mach_zig_version) from your build.zig.zon and installs that. If no
build.zig.zon is present it falls back to the latest stable release.
All inputs are optional.
| Name | Default | What it does |
|---|---|---|
version |
auto | Explicit Zig version. Accepts 0.16.0, 0.17.0-dev.123+abcdef012, 2024.5.0-mach, master, or latest. Overrides all auto-resolution. |
zig-version-file |
auto | Path to a file containing the version (.zigversion, .tool-versions, etc.). Plain string or zig <version> line accepted. Ignored when version is set. |
mirror |
auto | Force a specific mirror, e.g. https://pkg.machengine.org/zig. Cannot be https://ziglang.org. |
libc |
glibc |
Linux only: glibc or musl. Ignored on macOS / Windows. |
use-cache |
true |
Cache the global Zig cache directory between workflow runs. |
cache-key |
'' |
Extra component appended to the cache key — set this when running a matrix that should partition the cache (target triple, optimize mode). OS is always part of the key. |
cache-size-limit |
2048 |
Cache size cap in MiB. Cache is cleared when it exceeds this. 0 disables the cap. |
use-tool-cache |
auto | true / false override of the tool-cache decision. Defaults to false on GitHub-hosted runners and true elsewhere. |
| Name | Example value | What it means |
|---|---|---|
zig-version |
0.16.0 |
The version that was resolved and installed. |
mirror-used |
https://pkg.machengine.org/zig, cache, tool-cache |
The mirror that served the tarball, or the cache layer that served the install. |
cache-hit |
true / false |
Whether Zig was served from a cache. |
- uses: xyzzylabs/setup-zig@v1
id: zig
- run: echo "Using Zig ${{ steps.zig.outputs.zig-version }} (cache-hit=${{ steps.zig.outputs.cache-hit }})"- uses: xyzzylabs/setup-zig@v1
with:
version: 0.16.0- uses: xyzzylabs/setup-zig@v1
with:
zig-version-file: .zigversion- uses: xyzzylabs/setup-zig@v1
with:
libc: musljobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
target: [x86_64-linux, aarch64-linux, riscv64-linux]
optimize: [Debug, ReleaseSafe]
steps:
- uses: actions/checkout@v4
- uses: xyzzylabs/setup-zig@v1
with:
cache-key: ${{ matrix.target }}-${{ matrix.optimize }}
- run: zig build -Dtarget=${{ matrix.target }} -Doptimize=${{ matrix.optimize }}- uses: xyzzylabs/setup-zig@v1
with:
use-cache: falseThis action declares using: 'node24' and therefore needs a runner
that supports the Node 24 action runtime — that means
Actions runner v2.327.0 or newer. GitHub-hosted runners have
shipped this since mid-2025; self-hosted fleets pinned to an older
runner image will fail with node24 is not a valid value for runs.using
and need to be upgraded first.
┌─ randomized community mirror list
│ (cached for 6h in the actions cache)
1. Resolve version ─→ 2. Pick 3 mirrors ─→ Promise.any race ─┐
├─→ verify minisign ─→ extract
fallback: rest sequentially │
last resort: ziglang.org canonical ────┘
On a cache hit, the cached tarball and its stored .minisig sidecar are
re-verified before the install is trusted. Per-mirror transient failures
(HTTP 5xx, abort, network reset) trigger one automatic retry with
jittered backoff; deterministic failures (signature mismatch, filename
mismatch) skip the retry.
The global Zig cache directory (~/.cache/zig on Linux) is cached
between runs, and ZIG_LOCAL_CACHE_DIR is redirected to the same path
so all caches benefit from cross-run preservation.
The list of tarball mirrors lives in the community mirror list on ziglang.org. If you want to host a mirror, see the documentation on the Zig website repository — your mirror benefits any tool that follows the list, not just this action.
- Every download is verified against the official Zig minisign key before extraction.
- Cached tarballs are re-verified on cache hit.
- The action makes no network calls beyond the resolved mirror, the
community mirror list on
ziglang.org, and the Actions cache backend; CI hardens egress withharden-runner. - Vulnerabilities: see SECURITY.md for the private disclosure path.
This project began as a fork of
mlugg/setup-zig and is now
maintained independently — we make our own design decisions and do not
backport changes from upstream. The substantive differences:
- GitHub Actions only. Forgejo Actions support and the related mirror notice are gone; the action targets the GitHub runner exclusively.
- TypeScript on Node 24, no build step. Sources are TypeScript under
src/, run directly by Node's native type stripping.tsgois used only for type checking; nothing is committed underdist/. - New inputs:
zig-version-file(read the version from.zigversion/.tool-versions/ any file) andlibc(glibc/muslon Linux runners). - New outputs:
zig-version,mirror-used,cache-hit. - Mirror racing with retry. The first three mirrors are raced with
Promise.any; per-mirror transient failures (HTTP 5xx, abort, network reset) get one jittered retry. Signature failures still short-circuit. - Cache-hit re-verification. Cached tarballs are stored alongside
their
.minisigsidecar and re-verified before being trusted. - Streaming minisign hash. Tarballs are hashed as they're read from disk rather than buffered into memory whole.
- Real ZON reader. A small hand-written parser replaces the regex,
so comments and nested structs no longer confuse
minimum_zig_versiondetection. dirSizebug fix. The post-step's directory walker now bindserrin its innercatch— previously aReferenceErrormasked the real per-file failure and the function returned size0, silently disabling thecache-size-limitcheck.
See CHANGELOG.md for the full changelog.
See CONTRIBUTING.md. The short version: edit
src/*.ts, run npm run verify, open a PR. There is no build step —
Node 24 runs the TypeScript source directly via native type stripping.
MIT. See LICENSE.