AviSynth / AviSynthPlus

AviSynth with improvements
http://avs-plus.net
963 stars 73 forks source link

[RFC] Version: add development build info to Version() #362

Closed qyot27 closed 1 year ago

qyot27 commented 1 year ago

In another issue or discussion topic or somewhere on Doom9, the topic of how to handle release version bumping and in-between test builds was briefly brought up. I finally decided to try to mock up and test one such solution, which needed to be A) intelligent enough that we would not have to manually intervene except on our normal release bumps, and B) would maintain a clear distinction between releases and development test builds.

This is what I have so far: avs_devversion

Two lines, the first of which clearly states 'Next Version Development Build' and provides its test build designation, which is just git's CommitDate of the most recent commit in big endian date format (CommitDate, because the version is supposed to be deterministic rather than subject to whenever the build actually happened; I may need to adjust the exact date format so that it takes the date from UTC instead of being affected by time zone).

The second line gives the actual git tag information provided by running git describe --tags, so you get the number of commits after the most recent tag as well as the git hash. There is an alternative in that one that would only print the git hash while the commit difference was appended to the main version report (e.g. AviSynth+ 3.7.2+340), but when I was thinking about it more, displaying the main version number as it was at release and then showing the full git info for the particular in between commit seems more clear-cut.

So in this case, we release 3.7.3. After a few months, there's been 30 commits to master and a test build goes out. It would show up as:

AviSynth+ 3.7.3 (rXXXX, master, aarch64)
Next Version Development Build: 2023-10-14
Git: v3.7.3-30-gXXXXXXXX

The next build is another couple months later, with 26 more commits. The new build now reports:

AviSynth+ 3.7.3 (rXXXX, master, aarch64)
Next Version Development Build: 2023-12-23
Git: v3.7.3-56-gXXXXXXXX

This would remove the need to modify version.h.in to report the unreleased 'next' version number (as it now exists with the clear 'Next Version Development Build' marker, and the build itself is identified by an ever-advancing date instead of needing to do 'test1', 'test2', etc.), and remove the confusion that having pre-release builds with the next version's version number in them can cause. With the inclusion of the git info, it can also be shown how distant from the official release it is, or how distant it is from the previous dev build. That's technically the same reason we show the sequential revision number, but now that we have 4000 commits in master, that's getting more than a bit unwieldy. Being able to see 'oh, 56 commits since the release of 3.7.3' is easier to handle.

The actual way this interacts with the tags is as follows (and here I'm going to lay out in writing how I typically do the release tagging, so it is a good idea to have it to reference for posterity's sake).

Release builds will not show the two lines added by this pull request, and neither will builds of commits older than the latest tag, even if those commits would (or even did) have that info on them before the release was made. But how does it know that the build is a release build? Or that it's between tags from before the release? It does this by looking at the commit count since the latest tag, and if that difference is greater than 0, it knows that it's a dev build. The release commit itself has the tag attached to it, and thus will always be zero, and older commits - due to the way the comparison in Version.cmake is handled - will also show zero. And because the release branches are only committed to when they're fast-forwarded at release time, there shouldn't be anything getting committed to them between tags: it all comes in at once, and a new tag is created at the HEAD of the release branch.

In this setup, any non-release branch (master, or any topic branches you may have locally) will display the dev build info so long as they contain everything from the most recent release, plus additional commits that pertain to either the topic branch or have been upstreamed to master. But in the event that you're looking at the exact same commit that corresponds to the most recent tag, it will know you're on the release and omit the dev info, even if the branch is not the release branch (I originally didn't want to do this, and tried to have it restricted to just master, but it didn't really work correctly and topic branches are just as much development for the next version as master is).

[Possible] to-dos:

Thoughts?

pinterf commented 1 year ago

Thank you for the detailed explanation. I don't have much knowledge about the real purpose of tags and the system and rules behind them; I always learn and will have to read about it, I think. I Have to read it again, though. Preparing a release is not an easy and straightforward procedure, I woudn't dare make a release with my present knowledge.

qyot27 commented 1 year ago

I really only went into detail on that because the dev info added to Version with this change compares against the most recent tag to generate its output. It was mainly that I had never actually described how I went about making the releases, and if anything, I realized I needed to have that documented somehow. It wasn't because I was planning to stop doing the releases myself; it's just good to have the information public in the event that I can't when a new release needs to be made.

The real question is whether the proposed info is the direction we want to go in. Instead of doing something like 3.7.4 test 2, it would still be shown as 3.7.3 with 'test X' replaced with the date, and perhaps more importantly, the git info shown so that we can refer back to the exact commit if users spot a bug that crops up between one test build and the next.

Essentially, rather than this (with the version being manually changed outside of the git history with every test):

3.7.3
3.7.4 test 1
3.7.4 test 2
3.7.4

it would become (with the date/git info automatically generated):

3.7.3
3.7.3-devnext 2023-10-14
3.7.3-devnext 2023-12-23
3.7.4

(the -devnext could be added to the main version line, but it seems a little redundant if we have the line right underneath it that says 'Next Version Development Build'; for the filename of the installer or zipfile, it would make more sense, especially since the date is already there for the releases: AviSynthPlus_3.7.3-devnext_20231014.exe, AviSynthPlus_3.7.3-devnext_20231223.exe, and so on...)

But users would also see the git info when running Version(), so we could just have the filenames of the test builds directly reference that:

AviSynthPlus_3.7.3_2023XXXX.exe (release)
AviSynthPlus_3.7.3-30-gXXXXXXXX_20231014.exe (test)
AviSynthPlus_3.7.3-56-gXXXXXXXX_20231223.exe (test)
AviSynthPlus_3.7.4_20XXXXXX.exe (release)
pinterf commented 1 year ago

I like that syntax for the intermediate builds (commit count since last tagged version) Question: how would it appear in 3rd party unofficial builds; do they need to take any measures before compiling and publishing the actual set of DLLs to appear as a non-final one?

qyot27 commented 1 year ago

Nope. That it would be handled automatically was the main concern I had.

The only caveat is that the repo needs to have the tag information present. If someone is trying to keep their publicly-available fork synced to upstream, this requires fetching the tags separately (with git fetch --all --tags). So the typical case of '3rd party user does a fresh clone from our repo and builds it' - totally fine.

My fork (qyot27/AviSynthPlus) has no tags present on it because it's ancient (pretty sure I forked it shortly after pylorak first posted the initial set of changes in one of the 2.6 alpha threads, before the name 'AviSynth+' was adopted, since I had to rename the repo some time later) and I never bothered pushing tags up there. So a fresh clone of my repo errored out. On the other hand, if you built it from a fresh clone of your fork, it'd latch onto the most recent tag that was pushed there - r2772-MT. But I figure that's kind of an edge case because either A) users are going to do a fresh clone from this repo (and therefore always have the latest tags present) or B) 3rd party repos that care enough about syncing to upstream will fetch and push the tags once this becomes pertinent.

qyot27 commented 1 year ago

Fixed the issue that RELEASE_TARBALL would encounter (Github doesn't package git directories or metadata in its tarballs, so RELEASE_TARBALL exists to circumvent that for users that prefer grabbing the tarball instead of cloning; having the new dev info stuff not in that ifdef in version.h.in would have made it fail), and made sure that the date reported for the latest commit to HEAD is in UTC for determinism purposes.

If there's no objections or tweaks raised, I'll merge this in a couple days.

pinterf commented 1 year ago

That --unix then means UTC.

qyot27 commented 1 year ago

Unix time is always in UTC, yes. But it's not immediately recognizable by anyone as a date (Date: 1686690823), so to display as YYYY-MM-DD it has to be converted back out of that with CMake's TIMESTAMP function, where you have to explicitly request UTC.

All because git doesn't just offer non-local-time that as an option (it does as an environment variable, but I can't imagine trying to massage that into working on Windows through CMake invoking git...).