also looking at this
build: single-source the package and CLI version
#20
7 files
+40
-11
| @@ -328,7 +328,8 @@ We follow [Semantic Versioning](https://semver.org/): | ||
| 328 | 328 | |
| 329 | 329 | ### Release Steps |
| 330 | 330 | |
| 331 | 1. Update version in `build.zig.zon` | |
| 331 | 1. Update version in `build.zig.zon`. This is the authoritative package | |
| 332 | version; the build injects it into `zig-test --version` automatically. | |
| 332 | 333 | 2. Update CHANGELOG.md |
| 333 | 334 | 3. Create git tag: `git tag -a v1.2.3 -m "Release 1.2.3"` |
| 334 | 335 | 4. Push tag: `git push origin v1.2.3` |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | # Zig Test Framework - Features Summary |
| 2 | 2 | |
| 3 | **Framework Version:** 2.3.0 | |
| 3 | **Framework Version:** See `build.zig.zon` (the authoritative version source) | |
| 4 | 4 | **Last Updated:** 2025-10-26 |
| 5 | 5 | **Status:** Production Ready |
| 6 | 6 | |
| @@ -537,5 +537,5 @@ The framework is ready for production use and provides a comprehensive testing s | ||
| 537 | 537 | --- |
| 538 | 538 | |
| 539 | 539 | **Last Updated:** 2025-10-26 |
| 540 | **Framework Version:** 2.3.0 | |
| 540 | **Framework Version:** See `build.zig.zon` (the authoritative version source) | |
| 541 | 541 | **Status:** Production Ready ✅ |
| @@ -35,11 +35,11 @@ Add to your `build.zig.zon`: | ||
| 35 | 35 | ```zig |
| 36 | 36 | .{ |
| 37 | 37 | .name = "my-project", |
| 38 | .version = "0.1.0", | |
| 38 | .version = "0.1.0", // Your project's version | |
| 39 | 39 | .dependencies = .{ |
| 40 | 40 | .@"zig-test-framework" = .{ |
| 41 | .url = "https://github.com/zig-utils/zig-test-framework/archive/refs/tags/v0.1.0.tar.gz", | |
| 42 | // Replace with actual hash after publishing | |
| 41 | .url = "https://github.com/zig-utils/zig-test-framework/archive/refs/tags/vX.Y.Z.tar.gz", | |
| 42 | // Replace X.Y.Z and the hash with the release you use | |
| 43 | 43 | }, |
| 44 | 44 | }, |
| 45 | 45 | } |
| @@ -1,19 +1,37 @@ | ||
| 1 | 1 | const std = ; |
| 2 | const manifest_source = @embedFile("build.zig.zon"); | |
| 3 | const package_version = manifestVersion(manifest_source); | |
| 4 | ||
| 5 | fn manifestVersion(source: []const u8) []const u8 { | |
| 6 | const marker = ".version = \""; | |
| 7 | const marker_start = std.mem.indexOf(u8, source, marker) orelse | |
| 8 | @compileError("build.zig.zon must declare .version"); | |
| 9 | const start = marker_start + marker.len; | |
| 10 | const end_offset = std.mem.indexOfScalar(u8, source[start..], '"') orelse | |
| 11 | @compileError("build.zig.zon contains an unterminated .version"); | |
| 12 | return source[start .. start + end_offset]; | |
| 13 | } | |
| 2 | 14 | |
| 3 | 15 | pub fn build(b: *std.Build) void { |
| 4 | 16 | const target = b.standardTargetOptions(.{}); |
| 5 | 17 | const optimize = b.standardOptimizeOption(.{}); |
| 6 | 18 | |
| 19 | const build_options = b.addOptions(); | |
| 20 | build_options.addOption([]const u8, "version", package_version); | |
| 21 | ||
| 7 | 22 | // Create the main library module |
| 8 | 23 | const lib_module = b.addModule("zig_test_framework", .{ |
| 9 | 24 | .root_source_file = b.path("src/lib.zig"), |
| 10 | 25 | .target = target, |
| 11 | 26 | .link_libc = true, |
| 12 | 27 | }); |
| 28 | lib_module.addOptions("build_options", build_options); | |
| 13 | 29 | |
| 14 | 30 | // Create the test runner executable |
| 15 | 31 | const exe = b.addExecutable(.{ |
| 16 | 32 | .name = "zig-test", |
| 33 | .version = std.SemanticVersion.parse(package_version) catch | |
| 34 | @panic("build.zig.zon contains an invalid semantic version"), | |
| 17 | 35 | .root_module = b.createModule(.{ |
| 18 | 36 | .root_source_file = b.path("src/main.zig"), |
| 19 | 37 | .target = target, |
| @@ -258,6 +276,11 @@ pub fn build(b: *std.Build) void { | ||
| 258 | 276 | run_invalid_config.expectExitCode(2); |
| 259 | 277 | test_step.dependOn(&run_invalid_config.step); |
| 260 | 278 | |
| 279 | const run_version = b.addRunArtifact(exe); | |
| 280 | run_version.addArg("--version"); | |
| 281 | run_version.expectStdErrEqual(b.fmt("Zig Test Framework v{s}\n", .{package_version})); | |
| 282 | test_step.dependOn(&run_version.step); | |
| 283 | ||
| 261 | 284 | // Examples |
| 262 | 285 | const basic_example = b.addExecutable(.{ |
| 263 | 286 | .name = "basic_example", |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | const std = ; |
| 2 | const build_options = ; | |
| 2 | 3 | const config_mod = ; |
| 3 | 4 | const test_runner = ; |
| 4 | 5 | |
| @@ -44,6 +45,8 @@ pub const CLIOptions = struct { | ||
| 44 | 45 | timeout: ?u64 = null, // Global timeout in milliseconds |
| 45 | 46 | }; |
| 46 | 47 | |
| 48 | pub const version = build_options.version; | |
| 49 | ||
| 47 | 50 | pub const CLIError = error{ |
| 48 | 51 | InvalidArgument, |
| 49 | 52 | MissingValue, |
| @@ -383,8 +386,7 @@ pub const CLI = struct { | ||
| 383 | 386 | /// Print version information |
| 384 | 387 | pub fn printVersion(self: Self) void { |
| 385 | 388 | _ = self; |
| 386 | std.debug.print("Zig Test Framework v2.5.0\n", .{}); | |
| 387 | std.debug.print("Features: Parallel, Coverage, UI, Snapshots, Watch, Memory Profiling, TAP/JUnit, Progress Indicators, Timeout\n", .{}); | |
| 389 | std.debug.print("Zig Test Framework v{s}\n", .{version}); | |
| 388 | 390 | } |
| 389 | 391 | |
| 390 | 392 | /// Convert CLI options to RunnerOptions |
| @@ -423,6 +425,10 @@ test "CLI parse version" { | ||
| 423 | 425 | try std.testing.expect(cli.options.version); |
| 424 | 426 | } |
| 425 | 427 | |
| 428 | test "CLI build version is valid semantic version metadata" { | |
| 429 | _ = try std.SemanticVersion.parse(version); | |
| 430 | } | |
| 431 | ||
| 426 | 432 | test "CLI parse bail" { |
| 427 | 433 | var cli = CLI.init(std.testing.allocator); |
| 428 | 434 | const args = [_][]const u8{ "zig-test", "--bail" }; |