libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.71k stars 1.8k forks source link

Change version numbering to accomodate betas, release candidates, point-releases etc.? #5217

Closed smcv closed 2 years ago

smcv commented 2 years ago

Some of the recent SDL releases have had regressions that needed to be fixed shortly after release: 2.0.16 had #4630 and a HIDAPI regression, and 2.0.18 had various regressions that led to 2.0.20 being effectively just a bugfix release for 2.0.18.

However, because there's only one branch in git, each new release also picks up new feature work and technical-debt cleanup, which needs some testing before it's ready to go in a release. It also has a risk of causing new regressions, and the cycle continues.

Downstream distributions like the Steam Runtime, Linux distributions, and games that bundle a copy of SDL can work around this by cherry-picking bugfix patches into their copy (and I regularly do this in Debian and the Steam Runtime), but then mechanisms that compare more than one version and try to use the newest are unable to tell which version is newer/better/more-bug-fixed than the other.

The unofficial prereleases that happen before a stable release, such as https://discourse.libsdl.org/t/sdl-2-0-20-prerelease/34342/7, also identify themselves as being the same version as the actual stable release, which seems likely to lead to confusion; and it isn't immediately obvious which git commit they were built from, because there's no tag like prerelease-2.0.20pre1 that corresponds to them.

I think it could be useful to consider changing the version-numbering model for SDL and adjacent libraries (SDL_image, etc.) to avoid those problems:

GTK, Qt, Flatpak and dbus are some examples of projects with approximately this versioning model.

For betas and release candidates, there are a few conventions in common use:

It would also be nice if there was a representation for intermediate versions in git. At the moment, SDL seems to have the same convention used in dbus, where an odd micro version indicates a git snapshot, and all formal prereleases or releases have an even micro version. This works by releasing 2.0.20, immediately bumping the version number to 2.0.21, and then bumping the version number again to 2.0.22 before the next release, so that if you see a SDL binary that claims to be version 2.0.21, you know that it's a snapshot from somewhere between 2.0.20 and 2.0.22. Keeping that convention, and documenting it, seems like a good idea.

One potential problem with these suggestions is that SDL_VERSIONNUM assumes that the minor version is <= 9 and the micro version is <= 99. That could perhaps be avoided by redefining SDL_VERSIONNUM to use a larger "width" for those fields: because SDL_VERSIONNUM is a compile-time thing rather than a runtime thing, hopefully that won't break anyone?

smcv commented 2 years ago

An alternative way to get many of the properties I described above, without potentially breaking assumptions around SDL_VERSIONNUM, would be to introduce a fourth version component (nano version), so that for example regressions in 2.0.22.0 could be fixed in 2.0.22.1:

smcv commented 2 years ago

If it was up to me, I'd personally go for the major/minor/micro, odd/even setup as used in Flatpak and dbus, which I think is fairly straightforward to document and understand.

(Obviously it's not up to me - I am not a SDL maintainer, only a downstream packager and occasional upstream contributor.)

slouken commented 2 years ago

For SDL2 we are limited by the ABI of SDL_VERSIONNUM, where minor can only up to 10. We can definitely move to this scheme in SDL3 however.

In the meantime, we can potentially implement your alternative suggestion with a nano version. We haven't done that because from a manpower perspective we have our hands full simply doing our current full releases and don't have the bandwidth to cherry pick additional interim stable releases.

If someone were willing to do that, we can certainly add release-2.0.N.x branches and I could periodically build releases from that, and SDL_GetRevision() could reflect that in the string returned.

We'll continue to use the odd/even convention for unreleased/released versions. We'll also add rcN tags for release candidates in the future.

@icculus, thoughts?

cgutman commented 2 years ago

@slouken are you still planning to bump the version to 2.0.21 for this development cycle?

slouken commented 2 years ago

@slouken are you still planning to bump the version to 2.0.21 for this development cycle?

Yep!

icculus commented 2 years ago

Bumping this out of the 2.0.22 milestone and into our SDL3 planning list, since it would make sense to make significant versioning changes then.

Since we're planning to start SDL3 soon and SDL2 has been using this versioning for almost a decade, we probably shouldn't change this here.

smcv commented 2 years ago

2.0.22 release candidate 1 still thinks it's version 2.0.22 internally, but @slouken tagged it as 2.0.22-RC1 in git, which is a really useful step towards this - thanks for doing that! Doing the same for future RCs would be useful.

slouken commented 2 years ago

You're welcome - will do! :)

smcv commented 2 years ago

SDL 2.0.22 release candidates had quite a lot of regressions, so we had a two steps forward/one step back situation that took a while to sort out. There's still one known regression, #5572, which is not going to be solved until 2.0.24 now.

It's not great that we can't fix regressions without doing a whole new "feature" release, so @slouken asked me to think about this some more.

For SDL2 we are limited by the ABI of SDL_VERSIONNUM, where minor can only up to 10

Since SDL 3 will be incompatible with SDL 2 anyway, we don't actually need SDL_VERSIONNUM to be a lossless encoding of all possible version numbers, only those that start with a 2; so perhaps we could let the minor version overflow into the thousands digit? That would mean that SDL 2.24.0 would be encoded as 4400, and the highest possible SDL 2 version number 2.255.99 would be 27599. It's a bit nasty, but doesn't seem awful.

The micro version can't go higher than 99 because if it did, that would stop SDL_VERSIONNUM from being monotonically increasing; and the minor version can't go higher than 255 because SDL_version uses 1 byte per component.

SDL_VERSION_ATLEAST could easily be made future-proof by turning it into a more complex expression.

smcv commented 2 years ago

I still think it would be useful to have the versioning structure that GLib and libdbus use, something like this:

Or if making this use of the minor version is off the table as a result of the SDL_VERSIONNUMBER encoding, then they could perhaps be development prereleases like 2.0.23.1 (read as "2.0.24 beta 1"), followed by stable version 2.0.24.0 and optionally point releases like 2.0.24.1, with the nano version just not appearing in the SDL_VERSIONNUMBER or SDL_version?

Either way, to make stable point-releases possible, we'd have to make sure the ABI versioning (LT_CURRENT, etc.) treats 2.(0.)24.1 as newer than 2.(0.)24.0, but older than 2.(0.)25.0. An easy way to do that would be to always set SDL_INTERFACE_AGE to 0 for new "feature" versions, even if no new functions have actually been added.

slouken commented 2 years ago

I think both of these comments are good changes. Let's create a PR that implements them and bumps the current development 2.0.23 to 2.23.0?

One question is when do we bump the patch number for development versions? Maybe we never do, and those are always .0, and should never be released in distributions? Or maybe we just do it when/if a development version needs to go into the Steam Linux Runtime, so version comparison works as expected?

smcv commented 2 years ago

Let's create a PR that implements them and bumps the current development 2.0.23 to 2.23.0?

I'll try to do that next week.

One question is when do we bump the patch number for development versions? Maybe we never do, and those are always .0, and should never be released in distributions? Or maybe we just do it when/if a development version needs to go into the Steam Linux Runtime, so version comparison works as expected?

If you want to mark a point in time as "this is a beta/prerelease/whatever, and if you want to look for regressions then this is a good version to synchronize on", then I think it makes sense to give it a unique version number, whether it's going into downstream distributions or not (and even if you don't actually make dist until you are approaching final release status). When I was chasing regressions in 2.0.22, I found it really useful to be able to say "broken with rc2, fixed in rc3" or similar.

In dbus, we extended the odd/even convention to micro versions: an even micro version like 1.13.18 is a tagged release, and an odd micro version like 1.13.19 indicates some random point in git between 1.13.18 and 1.13.20.

Or if you don't like dbus' approach, then you could bump the micro version (patch number) whenever you do a prerelease, so the progression of versions might go:

and so on.

smcv commented 2 years ago

and should never be released in distributions

The rule I always tell people in projects like dbus and Flatpak is: if you get on the prerelease train, then you have to be prepared to stay on it all the way to the next station. Downstreams can package 1.odd.z versions, but if they do, then it's at their own risk, and they must keep up with the latest releases until they get to the next 1.even.z version (at which point they can decide whether to stay there for a while, or go back to prereleases). Downstreams that do short-term stable releases, like Ubuntu and Fedora, should make sure to avoid shipping a prerelease in those, and downstreams that do long-term stable releases, like Ubuntu LTS and Debian, should definitely be avoiding prereleases.

In Debian, I put 1.odd.z releases (and SDL prereleases, and occasionally git snapshots) in the experimental branch, which is what experimental is for: it's not expected to work smoothly (it's intended to be higher-regression-risk than a rolling release distribution like Arch, for example). Rolling release variants like Debian testing/unstable, and rolling-release-only distributions like Arch, should usually stick to "stable" upstream releases, and maybe some release candidates if the downstream maintainer is being careful enough.

slouken commented 2 years ago

Or if you don't like dbus' approach, then you could bump the micro version (patch number) whenever you do a prerelease, so the progression of versions might go:

  • 2.0.22
  • (git main becomes 2.23.0)
  • 2.23.1 (prerelease)
  • 2.23.2 (prerelease)
  • 2.24.0

Yes, I think this approach will work best with our workflow.

slouken commented 2 years ago

When you do the PR, can you also submit them for the SDL_* libraries? I'd like to incorporate this change into the next SDL_image and SDL_mixer releases (which I'm working on now)

smcv commented 2 years ago

I think both of these comments are good changes. Let's create a PR that implements them and bumps the current development 2.0.23 to 2.23.0?

5602

When you do the PR, can you also submit them for the SDL_* libraries?

I'll look at that next.

icculus commented 2 years ago

I think this is a bad idea to change this now. If I didn't say that clearly enough, I'm repeating it again.

If we're doing this, let's change this for SDL3 and not change this for SDL2, which is hopefully going into fixes-only mode soon.

smcv commented 2 years ago

I think this is a bad idea to change this now. If I didn't say that clearly enough, I'm repeating it again.

Do I understand correctly from #5602 that after discussion with @slouken, this objection no longer applies?

icculus commented 2 years ago

Do I understand correctly from #5602 that after discussion with @slouken, this objection no longer applies?

Sam made some good points to me; I withdraw my objection.

smcv commented 2 years ago

git main is now versioned 2.23.0, which will lead to 2.23.x prereleases, and eventually 2.24.0 as the next stable release after 2.0.22.

When you do the PR, can you also submit them for the SDL_* libraries? I'd like to incorporate this change into the next SDL_image and SDL_mixer releases (which I'm working on now)

https://github.com/libsdl-org/SDL_image/pull/222 converts SDL_image to be version 2.5.x, so that 2.6.0 will be the next stable release after 2.0.5. Does that numbering make sense to you?

If the SDL_image pull request looks reasonable, I can look at doing similar for SDL_mixer (2.5.x, leading to a 2.6.0 stable release superseding 2.0.4), SDL_ttf (2.19.x, leading to a 2.20.0 stable release superseding 2.0.18), and optionally SDL_net.

slouken commented 2 years ago

If the SDL_image pull request looks reasonable, I can look at doing similar for SDL_mixer (2.5.x, leading to a 2.6.0 stable release superseding 2.0.4), SDL_ttf (2.19.x, leading to a 2.20.0 stable release superseding 2.0.18), and optionally SDL_net.

Yep, that looks good, thanks!

smcv commented 2 years ago

If the SDL_image pull request looks reasonable, I can look at doing similar for SDL_mixer (2.5.x, leading to a 2.6.0 stable release superseding 2.0.4), SDL_ttf (2.19.x, leading to a 2.20.0 stable release superseding 2.0.18), and optionally SDL_net.

These were merged. The next stable "feature" releases will be:

slouken commented 2 years ago

Are there any work items left before we close this?

smcv commented 2 years ago

Are there any work items left before we close this?

I don't think so, unless you want to use this issue to keep track of any regressions that it triggers elsewhere.

FFmpeg has an overly tight version constraint on its dependency: https://trac.ffmpeg.org/ticket/9768.

py-sdl2 was failing CI in Debian. I reported https://github.com/py-sdl/py-sdl2/issues/228 and sent a PR, which was merged.