BigWigsMods/packager

Packaging can receive the right tag but use the wrong tag

AlexFolland opened this issue · 15 comments

In this action, you can see that the tag pushed was 2023-07-10-release and yet the packager used tag 2023-07-08-alpha for packaging, leading CurseForge to receive the exact same package as last time instead of a new package with 2023-07-10-release in the file name.

Look at this. Even though it could see the correct tag which I pushed, as made evident here with the refs/tags/2023-07-10-release part:

Run if [[ -n "$WOWI_API_TOKEN" && "refs/tags/2023-07-10-release" == "refs/tags/"* && "true" == "true" ]] && ! hash pandoc &>/dev/null; then
  if [[ -n "$WOWI_API_TOKEN" && "refs/tags/2023-07-10-release" == "refs/tags/"* && "true" == "true" ]] && ! hash pandoc &>/dev/null; then
fi

It made packages with file names with 2023-07-08-alpha, which is not the tag I pushed:

Uploading AutoGear-2023-07-08-alpha.zip (1.14.3,2.5.4,3.4.1,10.0.0 alpha) to https://wow.curseforge.com/projects/39179
Success!

Uploading AutoGear-2023-07-08-alpha.zip (10.0.0,3.4.1,1.14.3,2.5.4) to https://www.wowinterface.com/downloads/info26415
Success!

Updating GitHub release: https://github.com/AlexFolland/AutoGear/releases/tag/2023-07-08-alpha
Uploading AutoGear-2023-07-08-alpha.zip... Success!
Uploading release.json... Success!

You've got two lightweight tags pointing to the exact same commit.

Lightweight tags don't have any metadata whatsoever - they simply act as named pointers to other objects in the repository. When the packager asks Git to describe what the current tag actually is then it cannot disambiguate which of them is newer, so it'll name potentially any valid tag for the commit.

You should be able to avoid this in the future by using annotated tags which include metadata on when the tag was actually created. When describing a commit Git will prefer annotated tags are preferred over lightweight tags and uses the metadata to select the newest tag.

Annotated tags will always be preferred over lightweight tags, and tags with newer dates will always be preferred over tags with older dates. If an exact match is found, its name will be output and searching will stop.

Even annotated tags will cause the same issue. Tagging the same commit, with either type of tag, will often cause the older tag name to be re-packaged.

OK, sounds like you understand the issue. Now how should it be solved, considering that there's evidence that the script knows which exact tag was pushed?

I'll try to fix it myself and make a pull request.

It looks like we can use ${GITHUB_REF#refs/*/} to get the correct tag, instead of $( git -C "$si_repo_dir" describe --tags --always --abbrev=0 2>/dev/null ). Does that sound right to you?

GitHub Actions knows what ref was modified and communicates it to the packager via the GITHUB_REF environment variable, however fundamentally what you're seeing isn't going to be consistently solvable for a few reasons;

  1. While the packager can be told to use the environment variable, said variable naturally only exists if the packager is being run by GHA to begin with. The issue of having multiple tags pointing to a commit is still going to cause issues for any other CI system (Gitlab) or for manual runs of the packager on local systems.
  2. The packager also wants the previous tag name which isn't going to be communicated by an environment variable. This mostly just impacts automated changelog generation I believe - it may end up throwing the "wrong" tag into the comparison URL and look a bit weird as a result.

Issue 1 there can be solved by checking GITHUB_REF and if it's empty, falling back to the current method.

Issue 2 may be solvable a different way. Since I can clearly see what the tags are in my repository, and my IDE even shows me only the commit messages since the last tag, there must be a scriptable way to do that in the packager script.

Neither of those issues is as bad as the packager packaging the wrong tag, by the way. We do have the reference from github, so it should be used.

My use case doesn't seem wrong to me. I packaged the alpha, let people test it and tell me if it fixed the issues, and if so, package the release. It seems like a good idea, and only the packager has an issue with it. It doesn't seem right to say that doing that should be avoided because the packager might package the wrong tag.

Maybe I'm being pedantic here but I don't think it's really the "wrong" tag when you've given a single commit two names - you've more or less told Git that either tag name is completely acceptable when referring to the commit without giving it any recourse whatsoever to differentiate the two with additional metadata.

The packager could certainly use environment variables to hint which tag name should be preferred in an ambiguous case such as this, but I'm cautious about support for this being a bit confusing if someone were to later migrate away from GHA with this type of setup, or if they have a need to debug packaging locally and end up running into the same issue seen here. Fundamentally supporting such a hint would be wholly specific to GHA, whereas the alternative of just applying "newer" tags to an empty commit would be consistent everywhere.

Incidentally for alpha releases there is an alternative option available; simply have the packager process all commits to your master branch even if untagged. It'll automatically treat those as alpha builds and publishes them to CF/Wago, allowing you to use tags for anything that's not an alpha.

Look at the last two tags in that output - they've got the exact same date.

I've tried a few ways to get timestamps and they've been inaccurate. There's a taggerdate field, but it doesn't seem to always be populated.

For that second listing those are actually annotated tags - so they have the necessary metadata saying when it was created. Lightweight tags effectively just being named pointers rather than real objects in Git don't have that.

Were I to hazard a guess, that the first command you executed listed the "alpha" tag first for the most recent commit feels reasonably likely to be the reason why git describe as run by the packager used that tag; it was probably the first one in the list of refs that it came across that was valid for your to-be-packaged commit.

The git documentation actually states that, at least when using annotated tags, the newer one is supposed to be preferred - but I have observed the issue often enough to say this doesn't seem to work. I have one particular addon that has a tendency to get re-tagged to pickup locale updates, where this happens.

Of course if you use lightweight tags to begin with, there isn't even any date information to sort by.

OK, so lightweight tags are basically useless for this since they don't contain timestamps. Good to know. I'll always use annotated tags from now on. Apparently I have done so in the past with different tools which automatically created annotated tags. However recently, I've been using VS Code and that creates lightweight tags by default. I didn't realize I was destroying the possibility of sorting tags.

However, that leads me back to the GITHUB_REF. At least the situation could be improved if the GITHUB_REF variable was used when it is possible to use, and the latest annotated tag with field taggerdate could be used when that's possible to use. Those seem like 2 improvements that are worthwhile, even if the core issue can't be solved with lightweight tags and a non-github usage of the packager.

took a stab at this with a8acbfa