release: nix flake with tag-pinned hashes, reproducible tarballs (milestone 40)
flake.nix fetches the release tarballs and carries their SRI hashes in a generated block. The cut tool builds the release locally with the toolchain gates.yml pins, in a normalized nine-variable environment, writes the hashes into flake.nix, and commits it with build.zig.zon as the single bump commit. The package job verifies the pins on the bump commit and the publish job verifies them again on the tag, before anything is uploaded. The tarballs are written by dist_stage (std.tar.Writer, flate gzip) instead of the runner's tar and gzip, and -ffile-prefix-map keeps checkout paths out of the C objects; two checkouts at different absolute paths produce byte-identical archives. nxdns version, /api/version and the admin footer report the version only: the bump commit cannot know its own sha.
This commit is contained in:
+1
-2
@@ -453,9 +453,8 @@ pub fn runHelp(r: Runner) u8 {
|
||||
}
|
||||
|
||||
pub fn runVersion(r: Runner) u8 {
|
||||
r.out.print("nxdns {s} ({s})\nzig {s}\n", .{
|
||||
r.out.print("nxdns {s}\nzig {s}\n", .{
|
||||
version.string,
|
||||
version.git_commit,
|
||||
version.zig_version_string,
|
||||
}) catch return finish(r, exit_runtime);
|
||||
return finish(r, exit_ok);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const build_options = @import("build_options");
|
||||
|
||||
pub const string: []const u8 = build_options.version_string;
|
||||
pub const git_commit: []const u8 = build_options.git_commit;
|
||||
pub const zig_version_string: []const u8 = build_options.zig_version_string;
|
||||
|
||||
@@ -11,7 +11,6 @@ const version = @import("../../version.zig");
|
||||
|
||||
pub const Body = struct {
|
||||
version: []const u8,
|
||||
git_commit: []const u8,
|
||||
zig_version: []const u8,
|
||||
/// Seconds since the process started. Zero until `started_unix` is wired,
|
||||
/// and never negative: a clock stepped backwards must not report a
|
||||
@@ -31,7 +30,6 @@ pub fn handle(
|
||||
pub fn body(version_string: []const u8, started_unix: i64, now_unix: i64) Body {
|
||||
return .{
|
||||
.version = if (version_string.len == 0) version.string else version_string,
|
||||
.git_commit = version.git_commit,
|
||||
.zig_version = version.zig_version_string,
|
||||
.uptime_seconds = uptime(started_unix, now_unix),
|
||||
};
|
||||
@@ -47,7 +45,6 @@ const testing = std.testing;
|
||||
test "the body carries the build strings and the elapsed time" {
|
||||
const out = body("", 1_000, 1_060);
|
||||
try testing.expectEqualStrings(version.string, out.version);
|
||||
try testing.expectEqualStrings(version.git_commit, out.git_commit);
|
||||
try testing.expectEqualStrings(version.zig_version_string, out.zig_version);
|
||||
try testing.expectEqual(@as(u64, 60), out.uptime_seconds);
|
||||
}
|
||||
@@ -66,7 +63,6 @@ test "the body serializes with snake_case field names" {
|
||||
var writer: std.Io.Writer = .fixed(&buffer);
|
||||
try std.json.Stringify.value(body("1.2.3", 10, 20), .{}, &writer);
|
||||
const text = writer.buffered();
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "\"git_commit\":"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "\"zig_version\":"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "\"uptime_seconds\":10"));
|
||||
}
|
||||
|
||||
@@ -1913,10 +1913,9 @@ components:
|
||||
|
||||
Version:
|
||||
type: object
|
||||
required: [version, git_commit, zig_version, uptime_seconds]
|
||||
required: [version, zig_version, uptime_seconds]
|
||||
properties:
|
||||
version: { type: string }
|
||||
git_commit: { type: string }
|
||||
zig_version: { type: string }
|
||||
uptime_seconds: { type: integer }
|
||||
|
||||
|
||||
@@ -4223,11 +4223,10 @@ const rate_limited_sample: ContractSample = .{
|
||||
const ts_print_width = 120;
|
||||
const ts_tab_width = 4;
|
||||
|
||||
/// Build identity, not contract data: `git_commit` comes from `-Dgit-commit`
|
||||
/// and `zig_version` from the compiler that built the test, so keeping either
|
||||
/// verbatim would pin the golden to one machine. Neither name occurs anywhere
|
||||
/// else in the contract.
|
||||
const volatile_string_keys = [_][]const u8{ "git_commit", "zig_version" };
|
||||
/// Build identity, not contract data: `zig_version` comes from the compiler
|
||||
/// that built the test, so keeping it verbatim would pin the golden to one
|
||||
/// machine. The name occurs nowhere else in the contract.
|
||||
const volatile_string_keys = [_][]const u8{"zig_version"};
|
||||
|
||||
fn writeTabs(w: *std.Io.Writer, depth: usize) !void {
|
||||
for (0..depth) |_| try w.writeByte('\t');
|
||||
|
||||
Reference in New Issue
Block a user