Making It Useful (MfGames Conventional Commit)
We wrote mfgames-conventional-commits
to solve a small itch of wanting to be able to calculate version numbers based on Conventional Commits but only for commits that touch specific directories. That way, a change to MfGames.IO
would bump that version up but not touch the versioning for MfGames.Nitride
in the same monorepo. For the most part, it was to allow the CIL projects to have different versions as they all had different lineages before they were combined.
As things go, we always intended to polish and expand on the tool but other things got in the way. But then D. Moonfire was working on Git For Authors and realized they didn't have a good solution for calculating version numbers of novels. Since we already had this tool, we spent a few days making it more useful and capable for single package projects and require less overhead to configure it.
Simplified Setup
The configuration file goes into //.config/mfgames-conventional-commit.json
as usual, but setup has gotten significant easier. we added a defaults
section that applies to every project along with substitutions for packages with {package}
that allow each pack to have their own directories.
{
"$schema": "https://mfgames.com/mfgames-conventional-commit-rs/schemas/v0.json",
"defaults": {
"tag_prefix": "{package}-",
"directories": { "include": ["src/{package}"] },
"files": { "include": ["src/{package}/**/*"] }
},
"packages": {
"MfGames.Cryptography": {},
"MfGames.DI.AutofacExtensions": {},
"MfGames.Gallium": {},
"MfGames.IO": {},
// There is more here
"MfGames.ToolBuilder.Tables": {}
}
}
It used to be we had to have the tag_prefix
and files
elements in each one with a customization per project to include the path. Now, {package}
can be used to substitute the package name and defaults to apply to any package that doesn't have settings underneath itself. In the future, we'll have some configuration that will scan the //src
directory for the package names, but not this round.
Version Numbers
We also have two variants of version numbers based on usage. The first is the “flatten” version which calculates the most relevant major, minor, or patch version and applies it to the latest found tag. So if you have a “feat”, “fix”, “fix” on 1.0.0, it would be “1.1.0”. In contrast is the “detail” version which applies the version one at a time. So if you had the same “feat”, “fix”, “fix” on 1.0.0, the result would be “1.1.2”.
Most software projects seem to make a conscious decision to bump up the version. With semantic releases, the versioning is done on the pipeline. For a long time, we used “flattened” as the basic approach since that is what Semantic Release did. However, with novels and the like, sometimes they go out without the pipeline running and it is useful to make sure new versions show up; hence the use of “detail”.
This also resulted in a slightly different output for the mfgames-conventional-commit version
command:
$ cd src/MfGames.IO
$ mfgames-conventional-commit version
package_name last_version flatten_version flatten_changed detail_version detail_changed
MfGames.IO 2.7.0 2.7.0 false 2.7.0 false
$ mfgames-conventional-commit version --all | head -n 5
package_name last_version flatten_version flatten_changed detail_version detail_changed
MfGames.Cryptography 14.7.0 14.7.0 false 14.7.0 false
MfGames.DI.AutofacExtensions 0.0.1 true 0.0.1 true
MfGames.Gallium 3.6.0 3.6.0 false 3.6.0 false
MfGames.IO 2.7.0 2.7.0 false 2.7.0 false
Because we're fond of changing format as needed, so it can also dump a JSON or Markdown version. And all logging is sent to stderr, so piping can work properly.
$ mfgames-conventional-commit version --json | jq
[
{
"package_name": "MfGames.IO",
"last_version": "2.7.0",
"flatten_version": "2.7.0",
"flatten_changed": false,
"detail_version": "2.7.0",
"detail_changed": false
}
]
$ mfgames-conventional-commit version --all --format markdown | head -n 5
package_name | last_version | flatten_version | flatten_changed | detail_version | detail_changed |
---|---|---|---|---|---|
MfGames.Cryptography | 14.7.0 | 14.7.0 | false | 14.7.0 | false |
MfGames.DI.AutofacExtensions | 0.0.1 | true | 0.0.1 | true | |
MfGames.Gallium | 3.6.0 | 3.6.0 | false | 3.6.0 | false |
MfGames.IO | 2.7.0 | 2.7.0 | false | 2.7.0 | false |
MfGames.Locking | 2.5.1 | 2.5.1 | false | 2.5.1 | false |
Updates
Another useful feature is the ability to perform updates if the version number changed. This is used to define an updates
element in the configuration file:
{
"$schema": "https://mfgames.com/mfgames-conventional-commit-rs/schemas/v0.json",
"defaults": {
"updates": [
{ "script": "npm version {detail_version} --no-git-tag-version" },
{ "script": "git tag v{detail_version}" }
]
}
}
As you can see from above, the command will change the NPM version and create a Git tag. If always_run
is set to true, then it will run every time it is called, otherwise it will only run if the Git tag doesn't match the calculated tag.
The main reason for this is because then we don't have to write a hundred plugins for different systems. You can just write the script to do it, call another program, or just write some output. Anything a shell can do, this can do.
Inferred Package
One of the more annoying things is that we couldn't figure out the package name from the current context. For the most part, that didn't mean much since we could always provide --package package-name
, but we found it useful enough that we made the tool figure out the patch from the directories
attribute above. This also handles {package}
substitutions, so it is generally useful.
Both the version
and update
commands also take an --all
which means all packages in the project instead of --package package-name
for an arbitrary package, or either of these to guess it from the directory.
Sane Defaults
Finally, we added a sane default if the //.config/mfgames-conventional-commit.json
file is missing, or it doesn't have many settings. This assumes the entire directory is a single package called “default” and it uses a “vX.X.X” tag to represent versions.
Future Steps
This is a secondary project for us. Obvious, if we have an itch and it doesn't do something we want, we'll add it. If there are any issues that would be really useful or if you come up with something useful for the project (that is in scope), report or comment on it and we'll see about implementing it.
Metadata
Project
- Project Home
- Documentation
- Repository
- Issues
- Project ID: 019530c5-8880-77e3-9e41-83db8b5a49ba