Proposal: add `zig pack` for creating release tarball of packages
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
ziptotar.gz - switched command from
zig releasetozig pack
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.
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.
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.
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.
Dupe of #14312. Your ideas are noted