Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version string in release archives changes, which makes packaging harder #151

Closed
grembo opened this issue Jan 2, 2022 · 4 comments · Fixed by #152
Closed

Version string in release archives changes, which makes packaging harder #151

grembo opened this issue Jan 2, 2022 · 4 comments · Fixed by #152

Comments

@grembo
Copy link
Contributor

grembo commented Jan 2, 2022

(tagging @0mp, who is maintaining the FreeBSD port)

VERSION contains a version string that changes based on the state of the archive.

scli/VERSION

Line 1 in d9b38cf

$Format:%h %d$

This means, right after v0.6.5 was released, the file contained:

d2f437a (HEAD -> master, tag: v0.6.5, develop)

later this changed to

d2f437a (tag: v0.6.5).

This results in hashes of artifacts changing, which means package builders relying on those being correct end up not being able to fetch the package - one would think that official artifacts stay the same, but it appears that this might actually not be the case (comparing contents of v0.6.6 and v0.6.5 sources on the release page lead to this assumption).

There a discussion about this here: python-versioneer/python-versioneer#217

freebsd-git pushed a commit to freebsd/freebsd-ports that referenced this issue Jan 2, 2022
freebsd-git pushed a commit to freebsd/freebsd-ports that referenced this issue Jan 2, 2022
Hashes changed, see isamert/scli#151

(cherry picked from commit a22bf33)
@exquo exquo added the packaging label Jan 3, 2022
@exquo
Copy link
Collaborator

exquo commented Jan 3, 2022

Thanks for reporting, and for pointing to the same problem in the python-versioneer repo! I can see how this is an issue for the packagers. We definitely want to make life easier for you guys!

Here is what's happening:

We want scli --version to print a meaningful output whether scli has been obtained with git clone or downloaded from GitHub as a zip / tar.gz archive. But I don't want to have to update the version string somewhere in the source code, and then make a 'bump version' commit before every release.
Instead, getting the version number is taken care of by get_version() coupled with the VERSION file. If scli finds a .git dir, then scli --version runs git describe. If, on the other hand, scli has been downloaded as an archive from GitHub, then GitHub runs git archive to create that file; thanks to a hook in .gitattributes, during this process the contents of VERSION file are replaced with the actual version info, similar to that printed by git describe (see comments in the VERSION file).
Unfortunately, it's not exactly the same as git describe: we are limited to what git log's --pretty=format:'...' provides. The closest thing to what we want - the latest tag name - is the %d placeholder, which comes burdened with this extranous information about git branches pointing to the current commit. And those can change, of course, e.g. when a new commit is added to a branch that initally pointed to the tag.
python-versioneer apparently uses the same technique. Our version is a minimal implementation of the same idea.

Now, the problem arises because the archive files that GitHub provides for downloading, like the 'source code' files on the releases page, are generated dynamically at download time. This implies that there is no guarantee that the hashes of zip / tar.gz files downloaded at different times will stay the same. It's the same thing that causes #143.

Potential solutions

  • Upload archive files ourselves when creating releases. Those will be static.
    • Can be automated with GitHub actions.
    • Somewhat wasteful - basically duplicating the "source code" files (AFAIK, there is no option to disable those).
    • Adding confusion for users downloading from the release page - which file does one need and what's the difference between them?
    • Will not solve this problem if a downstream package is made from a 'non-release' commit (like this one targeting the latest master at the time)
  • Ensure that the tag commit does not have any other branches / tips pointing to it at the time of the release.
  • Write the version string manually somewhere in the source code and make a 'bump version' commit before a release.
    • Well, it's the kind of menial labor we're trying to avoid here..
      • Could potentially be automated: there is no pre-tag git hook, as far as I can see, but a custom script could be written as a replacement.
      • Still, adds unnecessary commits to the history.
  • (On the packagers' side): make the packaging scripts run a git clone && git checkout instead of downloading a tarball.

I am leaning towards the first option as the "least worst". It will also solve #143 and the potential future issues arising from relying on dynamically generated archive files. But none of the above seem ideal. Suggestions welcome!

@0mp has this come up in the past? Is this commit relevant? (The message "Fix scli --version")

@alexeyre can this be a problem for nixpkgs too?

@grembo
Copy link
Contributor Author

grembo commented Jan 4, 2022

@exquo What about using the %(describe) placeholder instead? It's available since git 2.32.

Example:

$Format:%h %(describe:match=v*)$

The above matches all annotated tags which start with a "v". So the one caveat is that tagging has to happen using git tag -a <tagname> (which seems like good practice for releases anyway).

The results look like this:

0bb2874 v0.0.1
aa12f3e v0.0.1-1-gaa12f3e
c41b211 v0.0.3

Which relate to:

  1. Build/export of version v0.0.1
  2. Build/export of first commit after version v0.0.1 (with hash)
  3. Build/export of version v0.0.3

I created a test repo to verify that this is actually supported by github: grembo/gitformattest

Testing shows that version strings stay stable this way.

@grembo
Copy link
Contributor Author

grembo commented Jan 4, 2022

The next release of git should contain this change, which will allow to do:

$Format:%h %(describe:match=v*:tags=true)$

to get rid of the annotation requirement on tags (even though, I kind of like using them anyway).

@exquo
Copy link
Collaborator

exquo commented Jan 4, 2022

What about using the %(describe) placeholder instead? It's available since git 2.32.

That's exactly what we need here, thanks so much!

I'm on an older git version, so was not aware of this addition. Ironically, it's right there next to %d in the git formatter documentation linked to above 🤦.

one caveat is that tagging has to happen using git tag -a <tagname>

Yes, we're using git's annotated tags. I agree it's a good practice regardless.

If you want to make a PR with this change to the VERSION file, I'd be happy to merge.

That should take care of this particular problem, but other issues caused by changing hashes of dynamically generated files might come up in the future. So, (note-to-self), we might still want to start uploading our own archive files to the releases.

grembo added a commit to grembo/scli that referenced this issue Jan 4, 2022
This should make auto-generated tarballs more stable, which helps
packagers.

Addresses isamert#151
grembo added a commit to grembo/scli that referenced this issue Jan 4, 2022
This should make auto-generated tarballs more stable, which helps
packagers.

Addresses isamert#151
@exquo exquo closed this as completed in #152 Jan 5, 2022
c-pec pushed a commit to c-pec/scli that referenced this issue Apr 20, 2022
This should make auto-generated tarballs more stable, which helps
packagers.

Addresses isamert#151
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants