Closed zsliu98 closed 8 months ago
When I want to release a new version
Yes, I find this process very awkward as well. I'd like to improve it, thanks for engaging!
If I create the VERSION file from git tags
Ok, so this keeps the VERSION file (which keeps it visible and coupled to the code, which is great). When you want to increment, you specify the new tag (with the desired version) and push (still has to have a commit attached to it).
Er, wait, does the new VERSION file get committed anywhere?
Maybe instead of github-action-get-previous-tag
, we could just have another build job that runs before everything, catches the tag changing via if: contains(github.ref, 'tags/v')
and writes + commits the VERSION?
Actually, maybe that's still "backwards" as it doesn't fix a few other pain points for me.
The friction I'd really love to remove is the whole "have to create a tag AND a commit AND push to trigger a release".
I often end up getting the repo ready for release, but then I have to add a fake / dumb commit to go with the tag. Or I forget to bump VERSION and it's going to release with the old VERSION.
So I'd love to bump VERSION locally. For example, I get to work on a bumped VERSION 2.1
locally — and when I finally merge into main
and push, it releases.
So maybe the best solution (for me at least) would be a release
action that doesn't trigger on a pushed tag, but triggers when it notices the VERSION file change, and then auto-tags that for me.
That way I don't have to care about juggling git tags — all I have to do is bump VERSION to release.
Er, wait, does the new VERSION file get committed anywhere?
No. The content of the VERSION file will be replaced by the latest tag when you execute the action. But the change will not get committed (of course you can commit it if you like).
I have three actions here:
Bump tag
: bump and push a new tag, on dispatchTest
: build the plugin and test it several times, on push, pull request and dispatchRelease
: build the plugin, test it, and release it if triggered with tag, on dispatchA drawback is that the VERSION file will not be consistent with the latest tag. Since I do not care about the version when building locally, it is not an issue for me.
In such a way, I am able to create a new release without doing anything locally. For example, I use Renovate to update submodules for me. A pull request (e.g. an update on JUCE master) from Renovate will first be verified by Test
. After that, I merge it, Bump tag
, and Release
a new version.
Thanks for the details!
It sounds like you have a good flow. For Pamplejuce, I think it be too confusing for others to have the local VERSION not updated / irrelevant / out of sync. Especially if they are including the major version as a part of their product names (which lets people cut breaking changes as new versions without impacting older projects). In that case, we need to be able to work with different versions locally.
You’ve motivated me to look into resolving the friction though — thanks! Right now I think “pushing an updated VERSION” is probably most compatible with people’s expectations. Sounds like I should try out a few methods, including yours, to see what feels best.
"pushing an updated VERSION creates tags and triggers release" also has a couple drawbacks, I think:
1.1.0
and the build fails, you'd need to again push the fix with a changed VERSION file, effectively needing to bump to 1.1.1
to get the release out.I guess the "cut releases based on pushing git tags" also has the same issue as #2, I guess. The benefit in both cases is that you only have to do 1 thing to cut a release, and it's "hygienic."
local git tags out of sync (not sure if relevant)
Yes, that's correct. If I rely on the VERSION file, the git tags will be out of sync. If I rely on the git tags, the VERSION file will be out of sync. Although git will notify me when I push anything to remote, this inconsistency might raise problems.
People can't cut a version of the same release twice, meaning if you push VERSION 1.1.0 and the build fails, you'd need to again push the fix with a changed VERSION file, effectively needing to bump to 1.1.1 to get the release out.
In such a case, I would delete the tag 1.1.0 remote & local, fix, commit, and tag it again with 1.1.0. Assume that sufficient tests will be carried out before updating VERSION / tagging a repo, such cases should be rare.
The bump tag action you are using looks interesting. I like that it enforces a PR flow and increments with semver — definitely up my alley!
Assume that sufficient tests will be carried out before updating VERSION / tagging a repo, such cases should be rare.
My experience is usually that CI catches and does a lot of extra things that the local environment doesn't, so I often end up with one platform having some issues even after running tests locally. However, I'm also developing Pamplejuce and constantly doing things like updating parts of it, so I probably run into more random failures at different parts of the build/release chain that most people would.
So I guess the ideal is "only tag once it's green in CI and passed QA." I'm definitely guilty of just pushing tags to my private repos hoping it'll work out. In a way I wish there was a way to manually "release" on a normal green CI commit...
Thanks (again!) for providing your perspective.
I'm going to summarize the options with pros/cons for Pamplejuce proper. I'll get a few more people using it to weigh in before making a decision I think.
Create a git tag and push to trigger a release:
git commit -m "Releasing v0.0.2"
git tag v0.0.2
git push --tags
VERSION
fileOn GitHub Actions dispatch
, use github-tag-action
to auto bump the version and push a new tag on merge. This requires using PRs to manage the workflow (which a lot of solo devs may not want bother with).
VERSION
file and stick the new version in there. GitHub Actions runs the release workflow when a change is detected.@sudara The last con for tags is the worst one
The first con for VERSION
is not really a con at all; perhaps noisy, but it's relevant noise
The second con for VERSION
also seems not hugely significant, either - you just add --tags
when you are pulling new code?
Sounds like this VERSION
file idea is a great one. Having GA automate tag naming seems like a pro, too.
find_package(Git)
if(GIT_EXECUTABLE)
# Generate a git-describe version string from Git repository tags
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=0
OUTPUT_VARIABLE GIT_DESCRIBE_VERSION
RESULT_VARIABLE GIT_DESCRIBE_ERROR_CODE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT GIT_DESCRIBE_ERROR_CODE)
set(FOOBAR_VERSION ${GIT_DESCRIBE_VERSION})
endif()
endif()
if(NOT DEFINED FOOBAR_VERSION)
set(FOOBAR_VERSION 0.0.0)
message(WARNING "Failed to determine VERSION from Git tags. Using default version \"${FOOBAR_VERSION}\".")
endif()
string(REPLACE "v" "" FOOBAR_VERSION_WITHOUT_V "${FOOBAR_VERSION}")
file(WRITE VERSION "${FOOBAR_VERSION_WITHOUT_V}")
After some search on Google, here is the best solution I can think of currently (ref: here). Perhaps you can add it as an optional Cmake module so that people can choose whether to use it!
It is compatible with (a previous version? of) Pamplejuce except for the sequence of the GA steps. I have to adjust it so that CMake is able to generate the VERSION file earlier. It syncs the VERSION file with the latest git tag (hopefully without any character other than "v").
@kriskeillor Thanks for weighing in. I agree with you, it seems most direct and clear to have VERSION
be the authoritative source.
@zsliu98 Thanks again! Appreciate the effort here. Another route would be to handle the tagging behind the scenes and just control the version from commits ala https://github.com/marketplace/actions/tag-version
After speaking with a few others, I'm leaning towards the VERSION
file route, as its easiest and has the most flexible mental model (esp. for those new to git, those don't care about tagging, or people like me, who like to bump the version locally so they can get the new version into shape).
When I want to release a new version, I have to:
If I create the VERSION file from git tags, I can save myself from the first step:
However in this case I have to make sure that the tags are in the format "-.-.-" What do you think about this?
See this workflow as an example.