Zig Official Website Source

repository·main·Indexed 19 days ago

https://github.com/ziglang/www.ziglang.org

Source code and content for the official Zig programming language website. Built with the Zine static site generator, the repository includes documentation on running the site locally, contributing translations, and technical requirements for hosting community mirrors, including tarball filename parsing and integrity verification.

Tokens
3.7K
Snippets
13
Records
18
Agent score
66%

What's inside ziglang.org

  1. Overview of the check-mirrors utility

    main

    The check-mirrors utility is a tool used to verify the integrity and functionality of community Zig mirrors. It ensures that mirrors are serving correct content by fetching a subset of available tarballs and signatures from each mirror and comparing them against the files served by the official ziglang.org.

    This check is automated via a daily workflow and is also triggered whenever a Pull Request modifies the mirror list.

  2. How to parse Zig tarball filenames to extract versions

    main

    Mirrors must parse filenames to determine if a request is for a 'normal' release or a 'pre-release' version.

    Supported Filename Patterns

    • zig-VERSION.EXT
    • zig-bootstrap-VERSION.EXT
    • zig-ARCH-OS-VERSION.EXT
    • zig-OS-ARCH-VERSION.EXT (Legacy/Older versions only)

    Where VERSION is a SemVer string (e.g., 0.14.1 or 0.15.0-dev.671+c907866d5), EXT is .tar.xz, .zip, .tar.xz.minisig, or .zip.minisig.

    Option 1: Regular Expression

    Use the following regex to validate the name and capture the version string in a single group:

    ^zig(?:|-bootstrap|-[a-zA-Z0-9_]+-[a-zA-Z0-9_]+)-(\d+\.\d+\.\d+(?:-dev\.\d+\+[0-9a-f]+)?)\.(?:tar\.xz|zip)(?:\.minisig)?$

    Option 2: Manual String Parsing

    1. Verify the filename starts with zig-.
    2. Verify the filename ends with a supported extension (.tar.xz, .zip, .tar.xz.minisig, .zip.minisig).
    3. Find the last occurrence of -. If that byte is followed by dev, find the previous occurrence of - instead.
    4. The substring after that - (and before the extension) is the version.
    ^zig(?:|-bootstrap|-[a-zA-Z0-9_]+-[a-zA-Z0-9_]+)-(\d+\.\d+\.\d+(?:-dev\.\d+\+[0-9a-f]+)?)\.(?:tar\.xz|zip)(?:\.minisig)?$
  3. How to write a translation

    main

    Adding a new language translation involves several steps. Refer to the Zine documentation for content and templating syntax, and the i18n section for localization specifics.

    A complete translation requires:

    1. Registering the translation in build.zig and creating its corresponding content directory.
    2. Creating a corresponding Ziggy file under i18n/ that contains the localized version of every phrase used on the site.
    3. Translating all content files (note: news and devlog files should not be translated).
  4. Add a new community mirror to the Zig list

    main

    Once your mirror meets all technical requirements, you can add it to the official list by:

    1. Modifying the list in assets/community-mirrors.ziggy.
    2. Adding a single entry to the end of the array with your .url, .username, and .email.
    3. Opening a pull request.

    Example entry format:

    +    {
    +        .url = "https://mymirror.net",
    +        .username = "my-github-username",
    +        .email = "my@email.com",
    +    },
    [
         {
             .url = "https://a.com",
             .username = "a",
             .email = "a@a.com",
         },
         {
             .url = "https://b.com/zig",
             .username = "b",
             .email = "b@b.com",
         },
    +    {
    +        .url = "https://mymirror.net",
    +        .username = "my-github-username",
    +        .email = "my@email.com",
    +    },
     ]
  5. Run the Zig website locally

    main

    The website uses Zine for static site generation. To run the site locally, ensure you have the correct version of Zig installed (Zine and the website code samples target the latest tagged release of Zig). You can use zigup to manage multiple Zig versions easily. Once Zig is configured, use the Zig build system to serve the site.

    zig build serve
  6. Requirements for hosting a Zig community mirror

    main

    If you wish to host a community mirror for Zig tarballs, your service must adhere to the following technical requirements:

    Connectivity and Security

    • HTTPS Only: The mirror base URL X must start with https:// and support valid signed certificates.
    • Dual Stack: Must support HTTPS requests on both IPv4 and IPv6.

    Caching and Sourcing

    • Local Caching: The mirror must cache tarballs locally; it cannot simply act as a transparent proxy/forwarder.
    • Sourcing: Tarballs must be downloaded from https://ziglang.org/ (or a valid mirror of it).
    • Integrity: Files provided must be bit-for-bit identical to those on https://ziglang.org/.
    • On-demand Fetching: If a requested tarball is not in the local cache, the mirror must immediately download it from the source and serve it.

    Request Handling and Versioning

    • Normal Versions: For Semantic Versioning (SemVer) releases (e.g., 0.14.1), serve files from https://ziglang.org/download/<version>/<filename>.
    • Pre-release Versions: For dev/pre-release versions (e.g., 0.15.0-dev.671...), serve files from https://ziglang.org/builds/<filename>.
    • Error Codes:
      • 404 Not Found: May be used if the filename doesn't match the expected schema or if a version is too old (e.g., $\le$ 0.5.0).
      • 504 Gateway Timeout: Should be used if the upstream https://ziglang.org/ fails or times out.
      • 429 Too Many Requests: Should be used for rate-limiting.
      • 503 Service Unavailable: Should be used during scheduled maintenance.

    Metadata

    • Source Tracking: Mirrors may observe the source query parameter (e.g., ?source=github-mlugg-setup-zig) to identify traffic origins.
  7. Example: Reading a file relative to the executable directory

    main

    This example demonstrates how to locate the directory where the current executable resides, open it, and read a file (e.g., word.txt) using an ArenaAllocator for memory management. This pattern is useful for accessing bundled assets or configuration files that are shipped alongside your binary.

    const std = @import("std");
    
    pub fn main() !void {
        // Initialize an ArenaAllocator for easy memory management
        var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);
        defer arena_state.deinit();
        const arena = arena_state.allocator();
    
        // Get the directory where the current executable is located
        const self_exe_dir_path = try std.fs.selfExeDirPathAlloc(arena);
        var self_exe_dir = try std.fs.cwd().openDir(self_exe_dir_path, .{});
        defer self_exe_dir.close();
    
        // Read a file named 'word.txt' from that directory
        const word = try self_exe_dir.readFileAlloc(arena, "word.txt", 1000);
    
        // Setup buffered stdout
        var stdout_buffer: [1000]u8 = undefined;
        var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
        const stdout = &stdout_writer.interface;
    
        try stdout.print("Hello {s}\n", .{word});
        try stdout.flush();
    }
  8. Use conditional compilation with build-time configuration

    main

    In Zig, you can use build-time configuration (often provided via an imported config module) to control code execution and compilation. This allows you to:

    1. Enforce version requirements: Use std.SemanticVersion.parse on a configuration string and check its properties (like major, minor, patch) within main or at compile-time using @compileError to prevent compilation if requirements aren't met.
    2. Conditionally include code: Use boolean flags from your configuration (e.g., config.have_libfoo) inside if blocks to conditionally call functions or include logic that depends on external dependencies or specific build settings.
    const std = @import("std");
    const config = @import("config");
    
    // Parse version from config for validation
    const semver = std.SemanticVersion.parse(config.version) catch unreachable;
    
    extern fn foo_bar() void;
    
    pub fn main() !void {
        // Enforce version constraints
        if (semver.major < 1) {
            @compileError("too old");
        }
        
        std.debug.print("version: {s}\n", .{config.version});
    
        // Conditionally execute code based on build config
        if (config.have_libfoo) {
            foo_bar();
        }
    }