From 5fbd4ed3154e4b0602dcd47da0adbbc2997863ee Mon Sep 17 00:00:00 2001 From: Abhishek Rai Date: Sun, 19 Apr 2026 12:41:44 -0700 Subject: [PATCH 1/4] ci: add GitHub Actions matrix --- .github/workflows/ci.yml | 54 ++++++++++++++++++++++++++++++++++++++++ README.md | 16 ++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f73d5c4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,54 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + name: bazel ${{ matrix.bazel }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - macos-latest + bazel: + - 9.0.1 + - 9.1.0 + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Bazelisk + uses: bazelbuild/setup-bazelisk@v3 + + - name: Select Bazel version + run: echo "USE_BAZEL_VERSION=${{ matrix.bazel }}" >> "$GITHUB_ENV" + + - name: Show Bazel version + run: bazel version + + - name: Build all targets + run: bazel build //... + + - name: Run test targets if present + shell: bash + run: | + set -euo pipefail + TEST_TARGETS="$(bazel query 'kind(".*_test rule", //...)' || true)" + if [[ -z "${TEST_TARGETS}" ]]; then + echo "No Bazel test targets found yet; skipping bazel test." + exit 0 + fi + + bazel test ${TEST_TARGETS} diff --git a/README.md b/README.md index e03a116..e99711b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,22 @@ Bazel rules for building [Zig](https://ziglang.org/) projects. - Zig: 0.13.0 - Bazel: 9.0+ +## CI and support matrix + +The repository currently runs CI on: + +- Bazel 9.0.1 on Linux and macOS +- Bazel 9.1.0 on Linux and macOS + +This gives us coverage for the current minimum supported Bazel 9 release line and the latest Bazel 9 minor release. + +CI currently runs: + +- `bazel build //...` +- `bazel test ...` when Bazel test targets are present + +As the ruleset grows, this matrix can expand to include more Bazel versions, additional examples, and stricter validation. + ## Setup ### Bzlmod (MODULE.bazel) From 93b03613c94a6f6a9c63264f9feca9cf79ef883b Mon Sep 17 00:00:00 2001 From: Abhishek Rai Date: Sun, 19 Apr 2026 12:43:46 -0700 Subject: [PATCH 2/4] ci: use released Bazel patch versions --- .github/workflows/ci.yml | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f73d5c4..1eec597 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - macos-latest bazel: - 9.0.1 - - 9.1.0 + - 9.0.2 steps: - name: Check out repository diff --git a/README.md b/README.md index e99711b..f21325c 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ Bazel rules for building [Zig](https://ziglang.org/) projects. The repository currently runs CI on: - Bazel 9.0.1 on Linux and macOS -- Bazel 9.1.0 on Linux and macOS +- Bazel 9.0.2 on Linux and macOS -This gives us coverage for the current minimum supported Bazel 9 release line and the latest Bazel 9 minor release. +This gives us coverage for the minimum supported Bazel 9 line and a newer Bazel 9 patch release that is currently available on GitHub-hosted runners. CI currently runs: From 7faa689f20a2acf32e084ed661ed5ef8066842b4 Mon Sep 17 00:00:00 2001 From: Abhishek Rai Date: Sun, 19 Apr 2026 12:55:17 -0700 Subject: [PATCH 3/4] test: add basic zig_test support --- .github/workflows/ci.yml | 16 +------- examples/math_lib/BUILD.bazel | 10 ++++- examples/math_lib/math_test.zig | 8 ++++ zig/defs.bzl | 3 +- zig/rules.bzl | 71 +++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 examples/math_lib/math_test.zig diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1eec597..3d6d5c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,17 +38,5 @@ jobs: - name: Show Bazel version run: bazel version - - name: Build all targets - run: bazel build //... - - - name: Run test targets if present - shell: bash - run: | - set -euo pipefail - TEST_TARGETS="$(bazel query 'kind(".*_test rule", //...)' || true)" - if [[ -z "${TEST_TARGETS}" ]]; then - echo "No Bazel test targets found yet; skipping bazel test." - exit 0 - fi - - bazel test ${TEST_TARGETS} + - name: Run test suite + run: bazel test //... diff --git a/examples/math_lib/BUILD.bazel b/examples/math_lib/BUILD.bazel index f5a33ee..3b2f882 100644 --- a/examples/math_lib/BUILD.bazel +++ b/examples/math_lib/BUILD.bazel @@ -1,6 +1,14 @@ -load("//zig:defs.bzl", "zig_library") +load("//zig:defs.bzl", "zig_library", "zig_test") zig_library( name = "math", srcs = ["math.zig"], ) + +zig_test( + name = "math_test", + srcs = [ + "math_test.zig", + "math.zig", + ], +) diff --git a/examples/math_lib/math_test.zig b/examples/math_lib/math_test.zig new file mode 100644 index 0000000..d54201c --- /dev/null +++ b/examples/math_lib/math_test.zig @@ -0,0 +1,8 @@ +const std = @import("std"); +const math = @import("math.zig"); + +test "basic arithmetic helpers" { + try std.testing.expectEqual(@as(i32, 5), math.add(2, 3)); + try std.testing.expectEqual(@as(i32, 6), math.multiply(2, 3)); + try std.testing.expectEqual(@as(i32, -1), math.subtract(2, 3)); +} diff --git a/zig/defs.bzl b/zig/defs.bzl index e76baea..b6dd43d 100644 --- a/zig/defs.bzl +++ b/zig/defs.bzl @@ -1,6 +1,7 @@ """Public API for rules_zig.""" -load("//zig:rules.bzl", _zig_binary = "zig_binary", _zig_library = "zig_library") +load("//zig:rules.bzl", _zig_binary = "zig_binary", _zig_library = "zig_library", _zig_test = "zig_test") zig_binary = _zig_binary zig_library = _zig_library +zig_test = _zig_test diff --git a/zig/rules.bzl b/zig/rules.bzl index 7acbbc8..2044d6d 100644 --- a/zig/rules.bzl +++ b/zig/rules.bzl @@ -134,3 +134,74 @@ zig_library = rule( }, toolchains = ["//zig:toolchain_type"], ) + +def _zig_test_impl(ctx): + zig_toolchain = ctx.toolchains["//zig:toolchain_type"] + zig_info = zig_toolchain.zig_info + zig_exe = zig_info.zig_exe + + srcs = ctx.files.srcs + if len(srcs) == 0: + fail("zig_test requires at least one source file in srcs.") + + main_filename = ctx.attr.main if ctx.attr.main else srcs[0].basename + main_src = None + for src in srcs: + if src.basename == main_filename or src.short_path.endswith(main_filename): + main_src = src + break + if not main_src: + fail("main file '{}' not found in srcs.".format(main_filename)) + + out = ctx.actions.declare_file(ctx.label.name) + src_tree = ctx.actions.declare_directory(ctx.label.name + "_srcs") + zig_link = ctx.actions.declare_file(ctx.label.name + "_zig") + + ctx.actions.symlink( + output = zig_link, + target_file = zig_exe, + is_executable = True, + ) + + copy_commands = [] + for src in srcs: + copy_commands.append("cp '{}' '{}/{}'".format(src.path, src_tree.path, src.basename)) + + command = "set -euo pipefail\nROOT=\"$PWD\"\nmkdir -p '{src_tree}'\n{copies}\ncd '{src_tree}'\n\"$ROOT/{zig}\" test '{main}' -femit-bin=\"$ROOT/{out}\" --cache-dir /tmp/zig-cache --global-cache-dir /tmp/zig-global-cache".format( + src_tree = src_tree.path, + copies = "\n".join(copy_commands), + zig = zig_link.path, + main = main_src.basename, + out = out.path, + ) + + ctx.actions.run_shell( + outputs = [out, src_tree], + inputs = srcs + [zig_link], + command = command, + mnemonic = "ZigCompileTest", + progress_message = "Compiling Zig test %{label}", + ) + + return [ + DefaultInfo( + files = depset([out]), + executable = out, + ), + ] + +zig_test = rule( + implementation = _zig_test_impl, + attrs = { + "srcs": attr.label_list( + doc = "Zig test source files to compile.", + allow_files = [".zig"], + mandatory = True, + ), + "main": attr.string( + doc = "The root source file for the test. Defaults to the first file in srcs.", + ), + }, + test = True, + toolchains = ["//zig:toolchain_type"], +) From c3558b9da76566b1e9faec188233e512d45af086 Mon Sep 17 00:00:00 2001 From: Abhishek Rai Date: Sun, 19 Apr 2026 12:57:22 -0700 Subject: [PATCH 4/4] docs: document zig_test --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index f21325c..8997454 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Bazel rules for building [Zig](https://ziglang.org/) projects. - `zig_binary` — compile Zig source files into an executable - `zig_library` — compile Zig source files into a static library (`.a`) +- `zig_test` — compile and run Zig tests with `bazel test` - Bazel toolchain integration with platform-aware compiler resolution ## Requirements @@ -95,3 +96,24 @@ zig_library( |-----------|-------------|----------| | `srcs` | List of `.zig` source files | Yes | | `main` | Root source file for the library. Defaults to the first file in `srcs`. | No | + +### `zig_test` example + +Compiles and runs Zig tests through `bazel test`. + +```starlark +load("@rules_zig//zig:defs.bzl", "zig_test") + +zig_test( + name = "math_test", + srcs = [ + "math_test.zig", + "math.zig", + ], +) +``` + +| Attribute | Description | Required | +|-----------|-------------|----------| +| `srcs` | List of `.zig` source files needed by the test, including imported sibling files | Yes | +| `main` | Root test source file. Defaults to the first file in `srcs`. | No |