`TlsInitializationFailed`: cannot build on 0.16

CI fails, cannot reproduce locally:

 /__w/xtxf/xtxf/build.zig.zon:8:20: error: unable to discover remote git server capabilities: TlsInitializationFailed
            .url = "git+https://codeberg.org/ziglang/translate-c?ref=zig-0.16.x#6fe0ffc4549f15c5f2d9432c2b4460ba90ff85ac",
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/__w/xtxf/xtxf/build.zig.zon:12:20: error: unable to discover remote git server capabilities: TlsInitializationFailed
            .url = "git+https://github.com/AnErrupTion/termbox2?ref=master#c7f241e8888ce243e1748b05c26a42fcfaaad936",
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/__w/xtxf/xtxf/build.zig.zon:16:20: error: unable to connect to server: TlsInitializationFailed
            .url = "https://github.com/00JCIV00/cova/archive/62ead80ef63bfa255a31d5e121920576d25ba342.tar.gz",
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/__w/xtxf/xtxf/build.zig.zon:20:20: error: unable to connect to server: TlsInitializationFailed
            .url = "https://codeberg.org/charlesrocket/ghext/archive/0.7.7.tar.gz",
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.{
    .name = .xtxf,
    .version = "0.11.7",
    .fingerprint = 0x9f00a07015769a82,
    .minimum_zig_version = "0.16.0",
    .dependencies = .{
        .translate_c = .{
            .url = "git+https://codeberg.org/ziglang/translate-c?ref=zig-0.16.x#6fe0ffc4549f15c5f2d9432c2b4460ba90ff85ac",
            .hash = "translate_c-1.0.0-Q_BUWo_5BgD4flHdUhA31zOz0XvZk9k7lQv1ouzyNXj2",
        },
        .termbox2 = .{
            .url = "git+https://github.com/AnErrupTion/termbox2?ref=master#c7f241e8888ce243e1748b05c26a42fcfaaad936",
            .hash = "N-V-__8AAAUXBQD6Fwpi9m0MBqWXFFaqW5l1lVrJC2Ynj7a-",
        },
        .cova = .{
            .url = "https://github.com/00JCIV00/cova/archive/62ead80ef63bfa255a31d5e121920576d25ba342.tar.gz",
            .hash = "cova-0.10.1-_OE4RzPaBAD0JKOMIrEJ8uHfz1_OXM7jpBEBocS_81gw",
        },
        .ghext = .{
            .url = "https://codeberg.org/charlesrocket/ghext/archive/0.7.7.tar.gz",
            .hash = "ghext-0.7.7-dKaQN5ppAADIXDAgOvVXocflUFqS4w8cYmZXfj-qZTlf",
        },
    },

    .paths = .{
        "src",
        "test",
        "build.zig",
        "build.zig.zon",
    },
}

build:

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const build_options = b.addOptions();
    const translate_c_dep = b.dependency("translate_c", .{});
    const termbox_dep = b.dependency("termbox2", .{
        .target = target,
        .optimize = optimize,
    });

    const termbox: Translator = .init(translate_c_dep, .{
        .c_source_file = termbox_dep.path("termbox2.h"),
        .target = target,
        .optimize = optimize,
        .default_init = true,
    });

    termbox.defineCMacro("TB_IMPL", null);
    termbox.defineCMacro("_XOPEN_SOURCE", "0");

    if (target.result.os.tag == .freebsd) {
        termbox.defineCMacro("__BSD_VISIBLE", "1");
    }

    const exe_mod = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
        .link_libc = true,
        .imports = &.{
            .{ .name = "termbox", .module = termbox.mod },
        },
    });

    const exe = b.addExecutable(.{
        .name = "xtxf",
        .root_module = exe_mod,
    });

    const cova_dep = b.dependency("cova", .{
        .target = target,
        .optimize = optimize,
    });

    const cova_mod = cova_dep.module("cova");

    if (target.query.cpu_arch == null) {
        const cova_gen = @import("cova").addCovaDocGenStep(b, cova_dep, exe, .{
            .kinds = &.{.all},
            .version = version(b),
            .help_docs_config = .{
                .section = '6',
            },
            .tab_complete_config = .{
                .include_opts = true,
                .add_cova_lib_msg = false,
                .add_install_instructions = false,
            },
        });

        const meta_doc_gen = b.step("gen-doc", "Generate Meta Docs");
        meta_doc_gen.dependOn(&cova_gen.step);
    }

    exe.root_module.addImport("cova", cova_mod);
    exe.root_module.addOptions("build_options", build_options);

    build_options.addOption([]const u8, "version", version(b));
    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);

    run_cmd.step.dependOn(b.getInstallStep());

    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);

    const unit_tests_mod = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
        .link_libc = true,
        .imports = &.{
            .{ .name = "termbox", .module = termbox.mod },
        },
    });

    const unit_tests = b.addTest(.{
        .root_module = unit_tests_mod,
    });

    const test_step = b.step("test", "Run all tests");
    test_step.dependOn(&b.addRunArtifact(unit_tests).step);

    const test_options = b.addOptions();
    const test_live = b.option(bool, "test_live", "Live integration tests") orelse false;
    test_options.addOption(bool, "test_live", test_live);
    test_options.addOptionPath("exe_path", exe.getEmittedBin());

    const integration_tests_mod = b.createModule(.{
        .root_source_file = b.path("test/cli.zig"),
        .target = target,
        .optimize = optimize,
    });

    const integration_tests = b.addTest(.{
        .root_module = integration_tests_mod,
        .use_llvm = true, //temp
    });

    integration_tests.root_module.addOptions("build_options", test_options);

    test_step.dependOn(&b.addRunArtifact(integration_tests).step);

    const merge_step = b.addSystemCommand(&.{ "kcov", "--merge" });
    merge_step.addDirectoryArg(b.path("coverage"));
    merge_step.addDirectoryArg(b.path("kcov-unit"));
    merge_step.addDirectoryArg(b.path("kcov-int"));

    const kcov_unit = b.addSystemCommand(&.{ "kcov", "--include-path=src" });
    kcov_unit.addDirectoryArg(b.path("kcov-unit"));
    kcov_unit.addArtifactArg(unit_tests);
    merge_step.step.dependOn(&kcov_unit.step);

    const kcov_int = b.addSystemCommand(&.{ "kcov", "--include-path=src,test" });
    kcov_int.addDirectoryArg(b.path("kcov-int"));
    kcov_int.addArtifactArg(integration_tests);
    merge_step.step.dependOn(&kcov_int.step);

    const coverage_step = b.step("coverage", "Generate test coverage (kcov)");
    coverage_step.dependOn(&merge_step.step);
}

fn version(b: *std.Build) []const u8 {
    const semver = manifest.version;
    const os = @tagName(builtin.target.os.tag);
    var gxt = Ghext.init(std.heap.page_allocator) catch return semver;
    const hash = gxt.hash(Ghext.HashLen.Short, Ghext.Worktree.Checked);
    return b.fmt("{s} ({s}) {s}", .{ semver, os, hash });
}

const manifest: struct {
    const Dependency = struct {
        url: []const u8,
        hash: []const u8,
        lazy: bool = false,
    };

    name: enum { xtxf },
    version: []const u8,
    fingerprint: u64,
    paths: []const []const u8,
    minimum_zig_version: []const u8,
    dependencies: struct {
        translate_c: Dependency,
        termbox2: Dependency,
        cova: Dependency,
        ghext: Dependency,
    },
} = @import("build.zig.zon");

const std = @import("std");
const builtin = @import("builtin");

const Ghext = @import("ghext").Ghext;
const Translator = @import("translate_c").Translator;

What am I doing wrong? chore(release): prepare for 0.11.7 · charlesrocket/xtxf@642e048 · GitHub

bump bump bump

This looks like an error during the fetch phase. The build system is trying to download them. My guess is that there is a network issue or possibly bad certs or something. The fact that it fails for all the dependencies seems to indicate that it is a system issue, probably with the runner setup or something.

The kcov/kcov container image doesn’t have /etc/ssl/certs (because on its own Kcov doesn’t need any), so I think it fails on that. My guess is you’ll need to do the build in a different container (perhaps a generic distro one, like debian), then move to the kcov/kcov one for coverage.

1 Like

It is not the network since other steps pass, and kcov container works well for another project dfs/.github/workflows/coverage.yml at trunk · charlesrocket/dfs · GitHub

IMO the big problem here is that error.TlsInitializationFailed can indicate too many wildly different types of issues:

  • Failure to load the system CA bundle (what @spiffyk mentioned)
  • Cert provided by the server is invalid in some way
  • Cert is valid but can’t be trusted based on the CAs we’re using
  • Cert is trusted but expired or not yet valid (system time may be incorrect?)
  • Anything else related to TLS (unlikely)

The thing is, the TLS implementation in std does already have separate errors for most if not all of these, but std.http.Client wraps them all into TlsInitializationFailed

3 Likes