KSPModdingLibs / KSPBuildTools

MIT License
2 stars 4 forks source link

GitVersioning as a versioning solution #13

Open Twinki14 opened 1 month ago

Twinki14 commented 1 month ago

I see the use of https://github.com/KSPModdingLibs/KSPBuildTools/blob/main/update-version.sh

https://github.com/dotnet/Nerdbank.GitVersioning or https://github.com/GitTools/GitVersion would provide a much more out-of-the-box solution that ties incredibly well together with GitHub actions and greatly simplifies the process you're already doing in https://github.com/KSPModdingLibs/KSPBuildTools/blob/main/update-version.sh

Basing release creation off of GitHub together with Git-based versioning would enable creators to write their own changelogs that could be automatically included in the release zip & automatically pack and version-stamp their mods

JonnyOThan commented 1 month ago

Thanks for the info, I wasn’t aware of these…probably would have used one if I was.

one of my goals here is to create a set of independent parts that can be customized and used individually, and not necessarily require using GitHub actions for building. And then also stitch those together in a common reusable system. I’d have to figure out of these packages support that (I think they do).

enable creators to write their own changelogs that could be automatically included in the release zip & automatically pack and version-stamp their mods

The current system supports this via yaclog. If you keep an unreleased section at the top of your changelog, then you can invoke create-release.yml with either a full version string or —major, —minor, etc. I don’t think I’ve fully documented all that yet…

drewcassidy commented 1 month ago

I put something together that does this. I propose that some or all of this be rolled into the KSPCommon.targets file, with an opt-out or opt-in.

https://github.com/KSPModdingLibs/Shabby/blob/3f1ed17419afa809d53bcabc728621e732df41a6/Source/Shabby.csproj#L25-L63

The idea is that assembly version would be entirely driven by git tags, not by yaclog. Yaclog can still be used to track changeling information and make it usable to GitHub releases or space dock, but would no longer be a dependency. If the current commit is on a tag, that tag is used as the version. otherwise it finds the most recent tag and increments the patch, and uses the number of commits since as a build number.

this whole system closely mirrors the Setuptools-SCM python package I've used to great effect for years, so there is real precedent for doing it this way.

The release action can still exist, as just a way to call yaclog release through the GitHub UI. then the main release workflow would pick up the new tag and turn it into a release. You can also run yaclog release locally and push the tag.

JonnyOThan commented 1 month ago

Note, yaclog is not at all a dependency right now. The only thing you need yaclog for is if you want automated release notes generation and support for incrementing a version number (the --minor, --patch options) instead of just typing the version number directly.


If the current commit is on a tag, that tag is used as the version

Forgive me, I'm not super well versed in usages of git tags. AFAIK It's just a name for a specific commit right?

As I understand it, the problem here is that I'd like the tagged version to reflect the state of the repo that the release was created from. But that means you need to commit updated changelog, .version files, etc and then tag that commit.

I can totally get on board with using the previous tag in order to do figure out what the version should be for the --major, --minor, --patch options though.


Oh, I think I understand. So the flow would be this:

  1. Some process runs that updates the changelog, .version files, etc. and commits that
  2. That commit gets tagged with the version number
  3. We compile the code which sees that, yes, the current commit is a tag and consumes that version number

That totally makes sense, because nothing has to be committed after the code is compiled.

drewcassidy commented 1 month ago

Close. Im imagining the .version file would just be a stub that only gets populated with the version information in the build script (already implemented here)

So workflow is: 1a) Developer manually dispatches the release workflow, which runs yaclog, then pushes the resulting commit and tag back to the repo. The only file it changes is the changelog to signal that the current version has changed, as well as creating a git tag. 1b) OR the developer does the same locally.

\2) the build action is triggered by a push to a tag. This compiles everything, packages it, and deploys it

JonnyOThan commented 1 month ago

Close. Im imagining the .version file would just be a stub that only gets populated with the version information in the build script (already implemented here)

how does this work for local iteration then? Won’t you constantly be sitting on a modified .version file? Or you have a malformed . Version file in the repo…(oh never mind I see it’s not modified in place)

actually, yeah, the .version file has to be committed for avc.

drewcassidy commented 1 month ago

You mean for comparison against? That's why I include it in the github release.

Which I understand is a slightly odd solution. you could certainly have it update at the same time as the changelog file, I just like having as few "stateful" components as possible

JonnyOThan commented 1 month ago

You mean for comparison against? That's why I include it in the github release.

No, the .version file contains a URL which AVC fetches from within the game to see if a mod has been updated. Typically that’s in the GitHub repo somewhere. So it needs to be committed on each release.


Oh, I see, the latest part of the URL works to handle that. That's a neat method!

https://github.com/drewcassidy/KSP-Conformal-Decals/releases/latest/download/ConformalDecals.version


OK, so what's the best way to integrate this into KSPCommon? I could add the targets to KSPCommon.targets and then leave it up to the developer to hook them up in beforebuild/afterbuild? And/or add inputs to the build action for extra msbuild targets to invoke before and after builds.

drewcassidy commented 1 week ago

Unfortunately GitVersion doesnt work with net48 projects at the moment bug report

I have my own hacked together version using git describe I can try to harden a bit. I don't know if the GitVersion project is likely to support our weird use case...

Twinki14 commented 1 week ago

Unfortunately GitVersion doesnt work with net48 projects at the moment bug report

I have my own hacked together version using git describe I can try to harden a bit. I don't know if the GitVersion project is likely to support our weird use case...

You can always go back to a version before 5.x, fairly easy to do in GitHub Actions.

https://github.com/dotnet/Nerdbank.GitVersioning Is another solution that's specific to .NET, and very likely has nice net48 support.

I'd spend some time coming up with some proper Git-based versioning and create a PR, but my solution would solely live in GitHub and rely on the use of GitHub Releases & GitHub Actions. Which goes against what @JonnyOThan had mentioned early on in the thread from my understanding.

I personally don't see any to having any packaging or publishing local, having it all in GitHub removes the need to have ultra-specific local configurations for cutting releases, and makes it incredibly easy for any interested KSP modders who want to fork your mod to try some stuff out and maybe cut their own releases. KSP Mods already for the most part exist on the GitHub platform. It's good practice to have your Continuous Delivery right next to your source-of-truth / source-code and honestly makes things so much easier.

GitHub is generally almost always available, accessible on any device, and you can always download the release to publish elsewhere if needed. Anytime anyone forks your repository all your GitHub workflows are included.

They don't have to download any dependencies and they don't have to run anything other than their IDE locally.

What @JonnyOThan had originally mentioned desiring is.. quite literally GitHub Actions, but you're wanting it available locally or something local you can have GitHub Actions use, which is overkill. You'd be taking a spoon and a knife to solve something you only need a fork for.

drewcassidy commented 1 week ago

I still need to be able to build the mod locally to develop it. Not having that is a non-starter

Nerdbank.GitVersioning still pulls from a json version file which is weird... I don't understand why it cant just use git describe

Twinki14 commented 1 week ago

I still need to be able to build the mod locally to develop it. Not having that is a non-starter

Nerdbank.GitVersioning still pulls from a json version file which is weird... I don't understand why it cant just use git describe

Yeah, the actual mod build process would still work locally. Devs need to be able to build their 💩 lol. I'm only strongly suggesting the CI/CD only live in GitHub.

I've built custom versioning for GHA that uses git directly in the past, it sorta works.

GitVersion works independently from the dotnet source, the only benefit to using it alongside dotnet is that it would stamp the assembly. So you could still use it and find something else that can stamp the mods assembly in CI with the semantic version GitVersion gives you.

Twinki14 commented 1 week ago

https://github.com/adamralph/minver Did just stumble upon this, much more minimal than GitVersion or Nerdbank and uses Git Tags directly

<Target Name="MyTarget" AfterTargets="MinVer">
  <PropertyGroup>
    <APPVEYOR_BUILD_NUMBER Condition="'$(APPVEYOR_BUILD_NUMBER)' == ''">0</APPVEYOR_BUILD_NUMBER>
    <AssemblyVersion>$(MinVerMajor).$(MinVerMinor).$(APPVEYOR_BUILD_NUMBER).$(MinVerPatch)</AssemblyVersion>
  </PropertyGroup>
</Target>
drewcassidy commented 1 week ago

Miniver doesn't increment the patch number

Twinki14 commented 1 week ago

Miniver doesn't increment the patch number

Goes off git tag, so the idea would be that you generate a semantic v2 version in CI (GitHub Actions) using GitVersion, then git tag using the output the GitVersion CLI gives you, and MinVer will stamp the assembly.

drewcassidy commented 1 week ago

I don't understand, msbuild already stamps the assembly with the version.

regardless, I already wrote #27

drewcassidy commented 1 week ago

Looking at it again, MinVer is actually perfect

however I don't think it has any place as part of KSPBuildTools. its easy enough to just add it to your csproj alongside KSPBuildTools