瀏覽代碼

rework ci

Jonathan Marler 10 月之前
父節點
當前提交
49ae4a789e
共有 3 個文件被更改,包括 241 次插入146 次删除
  1. 12 21
      .github/workflows/artifact.yml
  2. 163 93
      build.zig
  3. 66 32
      test.zig

+ 12 - 21
.github/workflows/artifact.yml

@@ -9,28 +9,19 @@ jobs:
       fail-fast: false
     runs-on: ${{matrix.os}}
     steps:
-      - uses: actions/checkout@v2
-      - uses: goto-bus-stop/setup-zig@v1
+      - uses: actions/checkout@v4
+      - uses: goto-bus-stop/setup-zig@v2
         with:
           version: 0.12.0
       - run: |
-          zig build test -Dci_target=${{matrix.os}}-${{matrix.arch}}
-      - run: |
-          zig build -Dci_target=ubuntu-latest-x86_64 -p zig-out-ubuntu-latest-x86_64
-      - run: |
-          zig build -Dci_target=ubuntu-latest-aarch64 -p zig-out-ubuntu-latest-aarch64
-      - run: |
-          zig build -Dci_target=macos-latest-x86_64 -p zig-out-macos-latest-x86_64
-      - run: |
-          zig build -Dci_target=macos-latest-aarch64 -p zig-out-macos-latest-aarch64
-      - run: |
-          zig build -Dci_target=windows-latest-x86_64 -p zig-out-windows-latest-x86_64
-      - uses: actions/upload-artifact@v2
-        with:
-          name: zigup ${{ matrix.os }}-${{ matrix.arch }}
-          path: zig-out/bin/*
-      - if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' }}
-        uses: actions/upload-artifact@v2
+          zig build ci --summary all
+      - if: ${{ matrix.os == 'ubuntu-latest'  }}
+        uses: actions/upload-artifact@v4
         with:
-          name: zigup ${{ matrix.os }}-aarch64
-          path: zig-out-${{matrix.os}}-aarch64/bin/*
+          name: zigup-archives
+          path: |
+            zig-out/zigup-x86_64-linux.tar.gz
+            zig-out/zigup-x86_64-macos.tar.gz
+            zig-out/zigup-x86_64-windows.zip
+            zig-out/zigup-aarch64-linux.tar.gz
+            zig-out/zigup-aarch64-macos.tar.gz

+ 163 - 93
build.zig

@@ -1,63 +1,42 @@
 const std = @import("std");
 const builtin = @import("builtin");
-const Pkg = std.build.Pkg;
-
-fn unwrapOptionalBool(optionalBool: ?bool) bool {
-    if (optionalBool) |b| return b;
-    return false;
-}
 
 pub fn build(b: *std.Build) !void {
-    //var github_release_step = b.step("github-release", "Build the github-release binaries");
-    //try addGithubReleaseExe(b, github_release_step, ziget_repo, "x86_64-linux", .std);
-
-    const maybe_ci_target = b.option([]const u8, "ci_target", "the CI target being built");
-    const target = if (maybe_ci_target) |ci_target|
-        b.resolveTargetQuery(try std.zig.CrossTarget.parse(.{ .arch_os_abi = ci_target_map.get(ci_target) orelse {
-            std.log.err("unknown ci_target '{s}'", .{ci_target});
-            std.process.exit(1);
-        } }))
-    else
-        b.standardTargetOptions(.{});
-
-    // Compile in ReleaseSafe on Windows for faster extraction
-    const optimize: std.builtin.OptimizeMode = if (
-        (maybe_ci_target != null) and (target.result.os.tag == .windows)
-    ) .ReleaseSafe else b.standardOptimizeOption(.{});
 
-    const win32exelink_mod: ?*std.Build.Module = blk: {
-        if (target.result.os.tag == .windows) {
-            const exe = b.addExecutable(.{
-                .name = "win32exelink",
-                .root_source_file = .{ .path = "win32exelink.zig" },
-                .target = target,
-                .optimize = optimize,
-            });
-            break :blk b.createModule(.{
-                .root_source_file = exe.getEmittedBin(),
-            });
+    const target = b.standardTargetOptions(.{});
+    const optimize = b.standardOptimizeOption(.{});
+
+    const zigup_exe_native = blk: {
+        const exe = addZigupExe(b, target, optimize);
+        b.installArtifact(exe);
+        const run_cmd = b.addRunArtifact(exe);
+        run_cmd.step.dependOn(b.getInstallStep());
+        const run_step = b.step("run", "Run the app");
+        run_step.dependOn(&run_cmd.step);
+        if (b.args) |args| {
+            run_cmd.addArgs(args);
         }
-        break :blk null;
+        break :blk exe;
     };
 
-    const exe = try addZigupExe(
-        b,
-        target,
-        optimize,
-        win32exelink_mod,
-    );
-    b.installArtifact(exe);
-
-    const run_cmd = b.addRunArtifact(exe);
-    run_cmd.step.dependOn(b.getInstallStep());
-
-    const run_step = b.step("run", "Run the app");
-    run_step.dependOn(&run_cmd.step);
-    if (b.args) |args| {
-        run_cmd.addArgs(args);
+    const test_step = b.step("test", "test the executable");
+    {
+        const exe = b.addExecutable(.{
+            .name = "test",
+            .root_source_file = .{ .path = "test.zig" },
+            .target = target,
+            .optimize = optimize,
+        });
+        const run_cmd = b.addRunArtifact(exe);
+        run_cmd.addArtifactArg(zigup_exe_native);
+        run_cmd.addDirectoryArg(b.path("scratch/native"));
+        test_step.dependOn(&run_cmd.step);
     }
 
-    addTest(b, exe, target, optimize);
+    const unzip_step = b.step(
+        "unzip",
+        "Build/install the unzip cmdline tool",
+    );
 
     {
         const unzip = b.addExecutable(.{
@@ -67,8 +46,13 @@ pub fn build(b: *std.Build) !void {
             .optimize = optimize,
         });
         const install = b.addInstallArtifact(unzip, .{});
-        b.step("unzip", "Build/install the unzip cmdline tool").dependOn(&install.step);
+        unzip_step.dependOn(&install.step);
     }
+
+    const zip_step = b.step(
+        "zip",
+        "Build/install the zip cmdline tool",
+    );
     {
         const zip = b.addExecutable(.{
             .name = "zip",
@@ -77,39 +61,43 @@ pub fn build(b: *std.Build) !void {
             .optimize = optimize,
         });
         const install = b.addInstallArtifact(zip, .{});
-        b.step("zip", "Build/install the zip cmdline tool").dependOn(&install.step);
+        zip_step.dependOn(&install.step);
     }
-}
 
-fn addTest(
-    b: *std.Build,
-    exe: *std.Build.Step.Compile,
-    target: std.Build.ResolvedTarget,
-    optimize: std.builtin.Mode,
-) void {
-    const test_exe = b.addExecutable(.{
-        .name = "test",
-        .root_source_file = .{ .path = "test.zig" },
-        .target = target,
-        .optimize = optimize,
+    const host_zip_exe = b.addExecutable(.{
+        .name = "zip",
+        .root_source_file = b.path("zip.zig"),
+        .target = b.host,
     });
-    const run_cmd = b.addRunArtifact(test_exe);
 
-    // TODO: make this work, add exe install path as argument to test
-    //run_cmd.addArg(exe.getInstallPath());
-    _ = exe;
-    run_cmd.step.dependOn(b.getInstallStep());
-
-    const test_step = b.step("test", "test the executable");
-    test_step.dependOn(&run_cmd.step);
+    const ci_step = b.step("ci", "The build/test step to run on the CI");
+    ci_step.dependOn(b.getInstallStep());
+    ci_step.dependOn(test_step);
+    ci_step.dependOn(unzip_step);
+    ci_step.dependOn(zip_step);
+    try ci(b, ci_step, test_step, host_zip_exe);
 }
 
 fn addZigupExe(
     b: *std.Build,
     target: std.Build.ResolvedTarget,
     optimize: std.builtin.Mode,
-    win32exelink_mod: ?*std.Build.Module,
-) !*std.Build.Step.Compile {
+) *std.Build.Step.Compile {
+    const win32exelink_mod: ?*std.Build.Module = blk: {
+        if (target.result.os.tag == .windows) {
+            const exe = b.addExecutable(.{
+                .name = "win32exelink",
+                .root_source_file = .{ .path = "win32exelink.zig" },
+                .target = target,
+                .optimize = optimize,
+            });
+            break :blk b.createModule(.{
+                .root_source_file = exe.getEmittedBin(),
+            });
+        }
+        break :blk null;
+    };
+
     const exe = b.addExecutable(.{
         .name = "zigup",
         .root_source_file = .{ .path = "zigup.zig" },
@@ -120,31 +108,113 @@ fn addZigupExe(
     if (target.result.os.tag == .windows) {
         exe.root_module.addImport("win32exelink", win32exelink_mod.?);
     }
-
     return exe;
 }
 
-fn addGithubReleaseExe(
+fn ci(
     b: *std.Build,
-    github_release_step: *std.build.Step,
-    comptime target_triple: []const u8,
+    ci_step: *std.Build.Step,
+    test_step: *std.Build.Step,
+    host_zip_exe: *std.Build.Step.Compile,
 ) !void {
-    const small_release = true;
+    const ci_targets = [_][]const u8 {
+        "x86_64-linux",
+        "x86_64-macos",
+        "x86_64-windows",
+        "aarch64-linux",
+        "aarch64-macos",
+    };
+
+    const make_archive_step = b.step("archive", "Create CI archives");
+    ci_step.dependOn(make_archive_step);
+
+    var previous_test_step = test_step;
+
+    for (ci_targets) |ci_target_str| {
+        const target = b.resolveTargetQuery(try std.zig.CrossTarget.parse(
+            .{ .arch_os_abi = ci_target_str },
+        ));
+        const optimize: std.builtin.OptimizeMode =
+            // Compile in ReleaseSafe on Windows for faster extraction
+                if (target.result.os.tag == .windows) .ReleaseSafe
+            else .Debug;
+        const zigup_exe = addZigupExe(b, target, optimize);
+        const zigup_exe_install = b.addInstallArtifact(zigup_exe, .{
+            .dest_dir = .{ .override = .{ .custom = ci_target_str } },
+        });
+        ci_step.dependOn(&zigup_exe_install.step);
+
+        const test_exe = b.addExecutable(.{
+            .name = b.fmt("test-{s}", .{ci_target_str}),
+            .root_source_file = .{ .path = "test.zig" },
+            .target = target,
+            .optimize = optimize,
+        });
+        const run_cmd = b.addRunArtifact(test_exe);
+        run_cmd.addArtifactArg(zigup_exe);
+        run_cmd.addDirectoryArg(b.path(b.fmt("scratch/{s}", .{ci_target_str})));
+
+        // This doesn't seem to be working, so I've added a pre-check below
+        run_cmd.failing_to_execute_foreign_is_an_error = false;
+        const os_compatible = (builtin.os.tag == target.result.os.tag);
+        const arch_compatible = (builtin.cpu.arch == target.result.cpu.arch);
+        if (os_compatible and arch_compatible) {
+            ci_step.dependOn(&run_cmd.step);
+
+            // prevent tests from running at the same time so their output
+            // doesn't mangle each other.
+            run_cmd.step.dependOn(previous_test_step);
+            previous_test_step = &run_cmd.step;
+        }
 
-    const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = target_triple });
-    const mode = if (small_release) .ReleaseSafe else .Debug;
-    const exe = try addZigupExe(b, target, mode);
-    if (small_release) {
-        exe.strip = true;
+        if (builtin.os.tag == .linux) {
+            make_archive_step.dependOn(makeCiArchiveStep(
+                b, ci_target_str, target.result, zigup_exe_install, host_zip_exe
+            ));
+        }
     }
-    exe.setOutputDir("github-release" ++ std.fs.path.sep_str ++ target_triple);
-    github_release_step.dependOn(&exe.step);
 }
 
-const ci_target_map = std.ComptimeStringMap([]const u8, .{
-    .{ "ubuntu-latest-x86_64", "x86_64-linux" },
-    .{ "macos-latest-x86_64", "x86_64-macos" },
-    .{ "windows-latest-x86_64", "x86_64-windows" },
-    .{ "ubuntu-latest-aarch64", "aarch64-linux" },
-    .{ "macos-latest-aarch64", "aarch64-macos" },
-});
+fn makeCiArchiveStep(
+    b: *std.Build,
+    ci_target_str: []const u8,
+    target: std.Target,
+    exe_install: *std.Build.Step.InstallArtifact,
+    host_zip_exe: *std.Build.Step.Compile,
+) *std.Build.Step {
+    const install_path = b.getInstallPath(.prefix, ".");
+
+    if (target.os.tag == .windows) {
+        const out_zip_file = b.pathJoin(&.{
+            install_path,
+            b.fmt("zigup-{s}.zip", .{ci_target_str}),
+        });
+        const zip = b.addRunArtifact(host_zip_exe);
+        zip.addArg(out_zip_file);
+        zip.addArg("zigup.exe");
+        zip.addArg("zigup.pdb");
+        zip.cwd = .{ .path = b.getInstallPath(
+            exe_install.dest_dir.?,
+            ".",
+        )};
+        zip.step.dependOn(&exe_install.step);
+        return &zip.step;
+    }
+
+    const targz = b.pathJoin(&.{
+        install_path,
+        b.fmt("zigup-{s}.tar.gz", .{ci_target_str}),
+    });
+    const tar = b.addSystemCommand(&.{
+        "tar",
+        "-czf",
+        targz,
+        "zigup",
+    });
+    tar.cwd = .{ .path = b.getInstallPath(
+        exe_install.dest_dir.?,
+        ".",
+    )};
+    tar.step.dependOn(&exe_install.step);
+    return &tar.step;
+}

+ 66 - 32
test.zig

@@ -18,39 +18,67 @@ fn setPathEnv(new_path: []const u8) void {
 const expected_zig_version_0_7_0 = if (builtin.os.tag == .macos) "0.7.0+9af53f8e0" else "0.7.0";
 
 pub fn main() !u8 {
-    std.log.info("running test!", .{});
-    try fixdeletetree.deleteTree(std.fs.cwd(), "scratch");
-    try std.fs.cwd().makeDir("scratch");
-    const bin_dir = "scratch" ++ sep ++ "bin";
+    var allocator_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
+    //defer allocator_instance.deinit();
+    const allocator = allocator_instance.allocator();
+
+    const all_cmdline_args = try std.process.argsAlloc(allocator);
+    if (all_cmdline_args.len <= 1) {
+        try std.io.getStdErr().writer().print("Usage: test ZIGUP_EXE TEST_DIR\n", .{});
+        return 0xff;
+    }
+    const cmdline_args = all_cmdline_args[1..];
+    if (cmdline_args.len != 2) {
+        std.log.err("expected 1 cmdline arg but got {}", .{cmdline_args.len});
+        return 0xff;
+    }
+
+    const zigup_src_exe = cmdline_args[0];
+    const test_dir = cmdline_args[1];
+    std.log.info("run zigup tests", .{});
+    std.log.info("zigup exe '{s}'", .{zigup_src_exe});
+    std.log.info("test directory '{s}'", .{test_dir});
+
+    if (!std.fs.path.isAbsolute(test_dir)) {
+        std.log.err("currently the test requires an absolute test directory path", .{});
+        return 0xff;
+    }
+
+    try fixdeletetree.deleteTree(std.fs.cwd(), test_dir);
+    try std.fs.cwd().makePath(test_dir);
+    const bin_dir = try std.fs.path.join(allocator, &.{ test_dir, "bin" });
     try std.fs.cwd().makeDir(bin_dir);
-    const install_dir = if (builtin.os.tag == .windows) (bin_dir ++ "\\zig") else ("scratch/install");
+    const install_sub_path = if (builtin.os.tag == .windows) "bin\\zig" else "install";
+    const install_dir = try std.fs.path.join(allocator, &.{test_dir, install_sub_path });
     try std.fs.cwd().makeDir(install_dir);
 
-    // NOTE: for now we are incorrectly assuming the install dir is CWD/zig-out
-    const zigup = comptime "." ++ sep ++ bin_dir ++ sep ++ "zigup" ++ builtin.target.exeFileExt();
+    const zigup = try std.fs.path.join(allocator, &.{
+        test_dir,
+        "bin",
+        "zigup" ++ comptime builtin.target.exeFileExt()
+    });
     try std.fs.cwd().copyFile(
-        comptime "zig-out" ++ sep ++ "bin" ++ sep ++ "zigup" ++ builtin.target.exeFileExt(),
+        zigup_src_exe,
         std.fs.cwd(),
         zigup,
         .{},
     );
     if (builtin.os.tag == .windows) {
-        const zigup_pdb = comptime "." ++ sep ++ bin_dir ++ sep ++ "zigup.pdb";
-        try std.fs.cwd().copyFile(
-            comptime "zig-out" ++ sep ++ "bin" ++ sep ++ "zigup.pdb",
-            std.fs.cwd(),
-            zigup_pdb,
-            .{},
+        const zigup_src_pdb = try std.mem.concat(
+            allocator, u8, &.{ zigup_src_exe[0 .. zigup_src_exe.len-4], ".pdb" }
         );
+        defer allocator.free(zigup_src_pdb);
+        const zigup_pdb = try std.fs.path.join(allocator, &.{ test_dir, "bin\\zigup.pdb" });
+        defer allocator.free(zigup_pdb);
+        try std.fs.cwd().copyFile(zigup_src_pdb, std.fs.cwd(), zigup_pdb, .{});
     }
 
-    const install_args = if (builtin.os.tag == .windows) [_][]const u8{} else [_][]const u8{ "--install-dir", install_dir };
+    const install_args = if (builtin.os.tag == .windows) [_][]const u8{
+    } else [_][]const u8{
+        "--install-dir", install_dir,
+    };
     const zigup_args = &[_][]const u8{zigup} ++ install_args;
 
-    var allocator_store = std.heap.ArenaAllocator.init(std.heap.page_allocator);
-    defer allocator_store.deinit();
-    const allocator = allocator_store.allocator();
-
     const path_link = try std.fs.path.join(allocator, &.{ bin_dir, comptime "zig" ++ builtin.target.exeFileExt() });
     defer allocator.free(path_link);
 
@@ -60,14 +88,9 @@ pub fn main() !u8 {
         std.log.err("the PATH environment variable does not exist?", .{});
         return 1;
     };
-    const cwd = try std.process.getCwdAlloc(allocator);
 
     const original_path_env = path_env_ptr.*;
-    {
-        const scratch_bin_path = try std.fs.path.join(allocator, &.{ cwd, bin_dir });
-        defer allocator.free(scratch_bin_path);
-        setPathEnv(try std.mem.concat(allocator, u8, &.{ scratch_bin_path, path_env_sep, original_path_env }));
-    }
+    setPathEnv(try std.mem.concat(allocator, u8, &.{ bin_dir, path_env_sep, original_path_env }));
 
     {
         const result = try runCaptureOuts(allocator, zigup_args ++ &[_][]const u8{ "default", "master" });
@@ -139,7 +162,8 @@ pub fn main() !u8 {
     // verify we print a nice error message if we can't update the symlink
     // because it's a directory
     {
-        const zig_exe_link = comptime "scratch" ++ sep ++ "bin" ++ sep ++ "zig" ++ builtin.target.exeFileExt();
+        const zig_exe_link = try std.fs.path.join(allocator, &.{ bin_dir, "zig" ++ comptime builtin.target.exeFileExt() });
+        defer allocator.free(zig_exe_link);
 
         if (std.fs.cwd().access(zig_exe_link, .{})) {
             try std.fs.cwd().deleteFile(zig_exe_link);
@@ -237,7 +261,7 @@ pub fn main() !u8 {
     try testing.expectEqual(@as(u32, 3), try getCompilerCount(install_dir));
 
     // Just make a directory to trick zigup into thinking there is another compiler so we don't have to wait for it to download/install
-    try std.fs.cwd().makeDir(install_dir ++ sep ++ "0.9.0");
+    try makeDir(test_dir, install_sub_path ++ sep ++ "0.9.0");
     try testing.expectEqual(@as(u32, 4), try getCompilerCount(install_dir));
     try runNoCapture(zigup_args ++ &[_][]const u8{"clean"});
     try testing.expectEqual(@as(u32, 3), try getCompilerCount(install_dir));
@@ -281,20 +305,24 @@ pub fn main() !u8 {
 
     // verify that we get an error if there is another compiler in the path
     {
-        const bin2_dir = "scratch" ++ sep ++ "bin2";
+        const bin2_dir = try std.fs.path.join(allocator, &.{ test_dir, "bin2" });
+        defer allocator.free(bin2_dir);
         try std.fs.cwd().makeDir(bin2_dir);
 
         const previous_path = path_env_ptr.*;
-        const scratch_bin2_path = try std.fs.path.join(allocator, &.{ cwd, bin2_dir });
-        defer allocator.free(scratch_bin2_path);
 
         {
-            var file = try std.fs.cwd().createFile(comptime bin2_dir ++ sep ++ "zig" ++ builtin.target.exeFileExt(), .{});
+            const fake_zig = try std.fs.path.join(allocator, &.{
+                bin2_dir,
+                "zig" ++ comptime builtin.target.exeFileExt()
+            });
+            defer allocator.free(fake_zig);
+            var file = try std.fs.cwd().createFile(fake_zig, .{});
             defer file.close();
             try file.writer().writeAll("a fake executable");
         }
 
-        setPathEnv(try std.mem.concat(allocator, u8, &.{ scratch_bin2_path, path_env_sep, previous_path }));
+        setPathEnv(try std.mem.concat(allocator, u8, &.{ bin2_dir, path_env_sep, previous_path }));
         defer setPathEnv(previous_path);
 
         // verify zig isn't currently on 0.7.0 before we set it as the default
@@ -326,6 +354,12 @@ pub fn main() !u8 {
     return 0;
 }
 
+fn makeDir(dir_path: []const u8, sub_path: []const u8) !void {
+    var dir = try std.fs.cwd().openDir(dir_path, .{});
+    defer dir.close();
+    try dir.makeDir(sub_path);
+}
+
 fn checkZigVersion(allocator: std.mem.Allocator, zig: []const u8, compare: []const u8, want_equal: enum { not_equal, equal }) !void {
     const result = try runCaptureOuts(allocator, &[_][]const u8{ zig, "version" });
     defer {