From d614885eb25a1dd8793705f3e39c99bf88ee63c7 Mon Sep 17 00:00:00 2001 From: glennmichael123 Date: Tue, 29 Sep 2026 22:54:23 +0800 Subject: [PATCH 1/2] fix: support current Zig 0.17 development APIs --- build.zig | 4 +--- src/compat.zig | 12 ++++++------ src/snapshot.zig | 16 ++++++++-------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/build.zig b/build.zig index a1d5381..67cb776 100644 --- a/build.zig +++ b/build.zig @@ -27,9 +27,7 @@ pub fn build(b: *std.Build) void { const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } + run_cmd.addPassthruArgs(); const run_step = b.step("run", "Run the test framework"); run_step.dependOn(&run_cmd.step); diff --git a/src/compat.zig b/src/compat.zig index eec0703..bce2ea5 100644 --- a/src/compat.zig +++ b/src/compat.zig @@ -113,7 +113,7 @@ fn closeFd(fd: std.posix.fd_t) void { /// Read entire file contents using POSIX APIs. /// Replaces std.fs.cwd().openFile() + file.readToEndAlloc(). pub fn readFileAlloc(allocator: std.mem.Allocator, path: []const u8) ![]const u8 { - const path_z = try allocator.dupeZ(u8, path); + const path_z = try allocator.dupeSentinel(u8, path, 0); defer allocator.free(path_z); const fd = std.posix.openatZ(std.posix.AT.FDCWD, path_z, .{}, 0) catch |err| { @@ -139,7 +139,7 @@ pub fn readFileAlloc(allocator: std.mem.Allocator, path: []const u8) ![]const u8 /// Write content to a file using POSIX APIs. /// Replaces std.fs.cwd().createFile() + file.writeAll(). pub fn writeFile(allocator: std.mem.Allocator, path: []const u8, content: []const u8) !void { - const path_z = try allocator.dupeZ(u8, path); + const path_z = try allocator.dupeSentinel(u8, path, 0); defer allocator.free(path_z); const fd = std.posix.openatZ(std.posix.AT.FDCWD, path_z, .{ @@ -161,7 +161,7 @@ pub fn writeFile(allocator: std.mem.Allocator, path: []const u8, content: []cons /// Delete a file using POSIX APIs. /// Replaces std.fs.cwd().deleteFile(). pub fn deleteFile(allocator: std.mem.Allocator, path: []const u8) !void { - const path_z = try allocator.dupeZ(u8, path); + const path_z = try allocator.dupeSentinel(u8, path, 0); defer allocator.free(path_z); const rc = std.c.unlink(path_z); if (rc != 0) { @@ -175,7 +175,7 @@ pub fn deleteFile(allocator: std.mem.Allocator, path: []const u8) !void { /// Create directories recursively using POSIX APIs. /// Replaces std.fs.cwd().makePath(). pub fn makePath(allocator: std.mem.Allocator, path: []const u8) !void { - const path_z = try allocator.dupeZ(u8, path); + const path_z = try allocator.dupeSentinel(u8, path, 0); defer allocator.free(path_z); const rc = std.c.mkdir(path_z, 0o755); @@ -189,7 +189,7 @@ pub fn makePath(allocator: std.mem.Allocator, path: []const u8) !void { if (sep > 0) { try makePath(allocator, path[0..sep]); // Retry creating the directory - const retry_z = try allocator.dupeZ(u8, path); + const retry_z = try allocator.dupeSentinel(u8, path, 0); defer allocator.free(retry_z); const rc2 = std.c.mkdir(retry_z, 0o755); if (rc2 != 0 and std.c.errno(rc2) != .EXIST) { @@ -298,7 +298,7 @@ pub fn spawnAndWait( defer allocator.free(c_argv); for (argv, 0..) |arg, i| { - const z = try allocator.dupeZ(u8, arg); + const z = try allocator.dupeSentinel(u8, arg, 0); c_argv[i] = z.ptr; } c_argv[argv.len] = null; diff --git a/src/snapshot.zig b/src/snapshot.zig index 47c21af..a114295 100644 --- a/src/snapshot.zig +++ b/src/snapshot.zig @@ -251,16 +251,16 @@ pub const Snapshot = struct { }, .@"struct" => { try writer.writeAll("{\n"); - inline for (type_info.@"struct".fields, 0..) |field, i| { + inline for (type_info.@"struct".field_names, 0..) |field_name, i| { if (self.options.pretty_print) { try writer.writeAll(" "); } - try writer.print("\"{s}\": ", .{field.name}); + try writer.print("\"{s}\": ", .{field_name}); - const field_value = @field(value, field.name); + const field_value = @field(value, field_name); try self.formatJsonValue(writer, field_value); - if (i < type_info.@"struct".fields.len - 1) { + if (i < type_info.@"struct".field_names.len - 1) { try writer.writeAll(","); } if (self.options.pretty_print) { @@ -307,10 +307,10 @@ pub const Snapshot = struct { try writer.writeAll("{\n"); - inline for (type_info.@"struct".fields, 0..) |field, i| { - try writer.print(" \"{s}\": ", .{field.name}); + inline for (type_info.@"struct".field_names, 0..) |field_name, i| { + try writer.print(" \"{s}\": ", .{field_name}); - const field_value = @field(value, field.name); + const field_value = @field(value, field_name); const FieldType = @TypeOf(field_value); const field_info = @typeInfo(FieldType); @@ -328,7 +328,7 @@ pub const Snapshot = struct { else => try writer.print("{any}", .{field_value}), } - if (i < type_info.@"struct".fields.len - 1) { + if (i < type_info.@"struct".field_names.len - 1) { try writer.writeAll(",\n"); } else { try writer.writeAll("\n"); From d435ce4228deac79f3ca3abdb4df04d0a55622ff Mon Sep 17 00:00:00 2001 From: glennmichael123 Date: Tue, 29 Sep 2026 23:05:34 +0800 Subject: [PATCH 2/2] ci: pin and monitor the supported Zig toolchain --- .github/workflows/ci.yml | 57 +++++++++++++++++++++++++++++++++++----- .zig-version | 1 + CONTRIBUTING.md | 2 +- README.md | 5 +++- TOOLCHAIN.md | 23 ++++++++++++++++ build.zig.zon | 2 ++ 6 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 .zig-version create mode 100644 TOOLCHAIN.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2fcde5..6cee217 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,25 +5,31 @@ on: branches: [main, develop] pull_request: branches: [main, develop] + schedule: + - cron: '17 6 * * 1' + workflow_dispatch: jobs: test: - name: Test on ${{ matrix.os }} with Zig ${{ matrix.zig-version }} + name: Test on ${{ matrix.os }} with supported Zig runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest] - zig-version: ['0.17.0-dev'] fail-fast: false steps: - name: Checkout code uses: actions/checkout@v6 + - name: Read supported Zig version + id: zig-version + run: echo "version=$(cat .zig-version)" >> "$GITHUB_OUTPUT" + - name: Setup Zig uses: pantry-pm/pantry/packages/action@main with: - packages: zig@0.17.0-dev + packages: zig@${{ steps.zig-version.outputs.version }} - name: Verify Zig installation run: zig version @@ -45,10 +51,14 @@ jobs: - name: Checkout code uses: actions/checkout@v6 + - name: Read supported Zig version + id: zig-version + run: echo "version=$(cat .zig-version)" >> "$GITHUB_OUTPUT" + - name: Setup Zig uses: pantry-pm/pantry/packages/action@main with: - packages: zig@0.17.0-dev + packages: zig@${{ steps.zig-version.outputs.version }} - name: Check formatting run: zig fmt --check . @@ -61,10 +71,14 @@ jobs: - name: Checkout code uses: actions/checkout@v6 + - name: Read supported Zig version + id: zig-version + run: echo "version=$(cat .zig-version)" >> "$GITHUB_OUTPUT" + - name: Setup Zig uses: pantry-pm/pantry/packages/action@main with: - packages: zig@0.17.0-dev + packages: zig@${{ steps.zig-version.outputs.version }} - name: Generate docs run: zig build-lib -femit-docs src/lib.zig @@ -83,10 +97,14 @@ jobs: - name: Checkout code uses: actions/checkout@v6 + - name: Read supported Zig version + id: zig-version + run: echo "version=$(cat .zig-version)" >> "$GITHUB_OUTPUT" + - name: Setup Zig uses: pantry-pm/pantry/packages/action@main with: - packages: zig@0.17.0-dev + packages: zig@${{ steps.zig-version.outputs.version }} - name: Install kcov continue-on-error: true @@ -121,3 +139,30 @@ jobs: - name: Coverage skipped if: steps.install-kcov.outcome != 'success' run: echo "kcov not available on this platform, skipping coverage" + + latest-zig: + name: Compatibility with latest Zig 0.17.0-dev + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + continue-on-error: true + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup latest Zig development build + uses: pantry-pm/pantry/packages/action@main + with: + packages: zig@0.17.0-dev + + - name: Verify Zig installation + run: zig version + + - name: Build framework + run: zig build + + - name: Run tests + run: zig build test + + - name: Run examples + run: zig build examples diff --git a/.zig-version b/.zig-version new file mode 100644 index 0000000..021fc03 --- /dev/null +++ b/.zig-version @@ -0,0 +1 @@ +0.17.0-dev.2163+89ff10d56 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1207925..2060c91 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,7 @@ Thank you for your interest in contributing to the Zig Test Framework! This docu ### Prerequisites -- Zig 0.15.1 or later +- The exact Zig development build recorded in [`.zig-version`](.zig-version) - Git - Basic understanding of testing frameworks (Jest, Vitest, or similar) diff --git a/README.md b/README.md index f19c85c..80b0443 100644 --- a/README.md +++ b/README.md @@ -756,7 +756,10 @@ zig build examples ## Requirements -- Zig 0.15.1 or later +- The exact Zig development build recorded in [`.zig-version`](.zig-version) + +See [TOOLCHAIN.md](TOOLCHAIN.md) for the compatibility policy and upgrade +process. ## Documentation diff --git a/TOOLCHAIN.md b/TOOLCHAIN.md new file mode 100644 index 0000000..c0c1074 --- /dev/null +++ b/TOOLCHAIN.md @@ -0,0 +1,23 @@ +# Zig toolchain policy + +The Zig Test Framework supports the exact Zig development build recorded in +`.zig-version`. Required CI jobs use that version so pull requests are tested +against a reproducible toolchain. + +Because the project follows Zig development builds, CI also runs a scheduled +compatibility check against the latest `0.17.0-dev` build. That check is +informational: an upstream API change should produce an intentional toolchain +update rather than unexpectedly blocking unrelated pull requests. + +## Updating Zig + +1. Replace the version in `.zig-version` with the full output of `zig version`. +2. Run `zig fmt --check .`. +3. Run `zig build`, `zig build test`, and `zig build examples`. +4. Run `zig build-lib -femit-docs src/lib.zig` and remove the generated local + artifacts after verifying the command succeeds. +5. Summarize required compatibility changes in the pull request and, for a + release, in the changelog. + +The compatibility job can also be run manually from GitHub Actions before +updating the pinned version. diff --git a/build.zig.zon b/build.zig.zon index 3c895bb..4abdaae 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -5,9 +5,11 @@ .paths = .{ "build.zig", "build.zig.zon", + ".zig-version", "src", "tests", "examples", + "TOOLCHAIN.md", "README.md", "LICENSE", },