zig icon indicating copy to clipboard operation
zig copied to clipboard

Proposal: add `zig pack` for creating release tarball of packages

Open scottredig opened this issue 1 year ago • 4 comments

tl;dr:

With a build.zig.zon of:

.{
    .name = "ziginit",
    .version = "0.0.0-dev",

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

and these files in the directory:

  • .git/...
  • build.zig
  • build.zig.zon
  • src/main.zig
  • someotherfile.mp4

Running this command: zig pack 0.1.0 Creates the file zig-out/ziginit-0.1.0-BWdcABvF_jM1.tar.gz Containing these files:

  • build.zig
  • build.zig.zon
  • src/main.zig

Except the contents of build.zig.zon have been modified to:

.{
    .name = "ziginit",
    .version = "0.1.0",

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

Detailed reasoning

Semantic Versioning

As noted in https://github.com/ziglang/zig/issues/19765, committing a semantic version into a repository is problematic. Semantic versions are supposed to reference points in time, not ranges of possible contents. Additionally, pre-release tags are the mechanism for possible unstable or for temporarily breaking the API contract. https://semver.org/ is reasonably ~~grumpy~~ precise about these points.

With the user experience as is, I don't expect this to be done correctly most of the time. Indeed looking at a few notable projects, I don't see any pre-release tags. When tools start referencing this version field, some dependencies referencing a non-release commit having the same version as another dep referencing a release commit, things are going to break.

Semi-related: In addition for proposal https://github.com/ziglang/zig/issues/8284#issuecomment-1000565560, pre-release tags should be considered unstable for post 1.0 releases. This was proposed in the thread: https://github.com/ziglang/zig/issues/8284#issuecomment-816810590 The other version checks approved in this thread should also performed by zig pack, so that people don't make broken releases where the commit seems fine before marking the version, but marking the version as not a pre-release version suddenly breaks things.

Also in response Loris mentioned something about "zig make-release", which sounds like this proposal, but I can't find any more references to that anywhere. So um... sorry if this is a duplicate of something I can't find.

Admittedly, I think a careful reading of semver says that even pre-release tags should be unique, but I think the above proposal is a pragmatic middle ground. An alternative would be to make the version field entirely optional, never included in commits, and only ever set by zig pack.

Archive Contents

Already the cache will only keep files referenced by .paths. So there is little point in ever including such files in a release tar.gz in the first place. Asking someone to manually do it is silly. An automatic process is additionally a boon for reproducible releases, eg for verification purposes in security consensus contexts.

Archive Naming

I yoinked the format from https://github.com/ziglang/zig/issues/20178. It'd be convenient for package archive names to fit a standard format, and while this wouldn't force it, it'd make it the happy path. Potentially makes the hash proposal irrelevant, as the hash being in the filename makes locating the hash by itself much easier.

Subjective Experience

The first time I did a package release, the process wasn't clear; So I just tagged a commit as 0.1.0, and let the automatic Github archive link be the release url. This has all of the problems listed above, so not great. I think that having a top level command which just does things correctly would be a boon to the usability of Zig, reducing variability and guiding users towards good behavior. After this proposal, the only addition to the naive approach would be running the command and dropping the tar.gz file into the Github release.

Other notes

The version field in the zig init zon file should be changed to be 0.0.0-dev, or similar. I also think add comment such as

// Do not commit a version that doesn't have a pre-release tag, eg "-dev".
// Using "zig pack" will set this for package releases.

Edit log

  • switched type from zip to tar.gz
  • switched command from zig release to zig pack

scottredig avatar Jul 31 '24 09:07 scottredig

Immediately after submitting I realized that .zip might not be the desired archive format. Eg could just as easily be .tar.gz. A more consistent archive format would be another bonus of zig release. The rest of the proposal is orthogonal to the archive format.

scottredig avatar Jul 31 '24 09:07 scottredig

As an additional idea, zig release x.y.z could edit the build.zig.zon file in the project root to hold .version = x.y.z-dev afterwards. And while at it, zig release could also check that the new release version is > the current version (meaning if build.zig.zon holds a development/pre-release tag, >= the corresponding release version) to further avoid errors. That way you can start with 0.0.0-dev from the template, every zig release automatically updates it to the next development version - basically no room for error left.

rohlem avatar Jul 31 '24 16:07 rohlem

Possible duplicate of #14312. Also related is #19603 which is motivated by tooling for creating package tarballs.

I don't have any especially strong opinions on the specific features of a potential zig release or zig pack command other than that it should archive all files matched by the build.zig.zon manifest. Currently, if you want to package a project that includes private files (internal documentation, integration tests, examples, maintenance scripts, etc.) that you don't want to ship (because you want to keep the package size down), you have to manually invoke tar with the files/directories you need, which is prone to copy/paste user error.

castholm avatar Jul 31 '24 18:07 castholm

As an additional idea, zig release x.y.z could edit the build.zig.zon file in the project root to hold .version = x.y.z-dev afterwards.

Note that, eg, zig pack 0.1.0-rc.1 or zig pack 0.1.0-dev+daily240731 would also be valid uses of the command. It's not just for full releases.

pre-release semver is before the associated semver with the same major.minor.patch but with no semver. So: 0.0.0 < 0.1.0-dev < 0.1.0 As there are three different choices for what number to increment for the next version, this choice can't be made without user input.

Also, I'm leaning more towards thinking that version just shouldn't be submitted to the repo. However there's more interactions with other tools I'm less familiar with to put forward a strong proposal for that. If anything, what is version right now should be renamed release-cycle, and then version is additionally added for releases, requiring that the release-cycle be only major.minor.patch, and the version have the same major.minor.patch plus optional pre-release and build identifier values.

Possible duplicate of #14312.

Ah, yeah. It's pretty close but there's enough unique specifics about this proposal that I'll leave it up to a core team member to dedup or not.

zig pack

Way better name, changed the proposal to match.

scottredig avatar Jul 31 '24 21:07 scottredig

Dupe of #14312. Your ideas are noted

andrewrk avatar Aug 12 '24 07:08 andrewrk