The goal of this tool is to have a simple versioning system that we can use to track the different releases. The tool prints the current version (e.g. to be used for tagging) depending on the git history and commit messages.
The versioning scheme is a combination of the Semantic Versioning and the Calendar Versioning called
Semantic Calendar Versioning and is meant to be primarily used to version a user-centric software rather than libraries
(which allows for some opinionated behaviour decisions).
Basically the core versioning is based on the calendar versioning scheme followed by the semantic versioning.
This means that the actual version number has 3 parts: YEAR.MINOR.PATCH
. The YEAR
is the current year, and the MINOR
and PATCH
are calculated from the git history since the beginning of the current year.
Note that the MINOR
starts from 1
unlike in the traditional semantic versioning where it starts from 0
. This is
to start the new year with version 1
no matter if the severity of the commit. The primary reason is that it looks better
in the final software than 0
.
# .github/workflows/version.yml
name: Semantic Calendar Version
on:
push:
branches:
- master
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }} # checkout the correct branch name
fetch-depth: 0 # fetch the whole repo history
- name: Semantic Calendar Version
id: version
uses: lukashornych/[email protected]
- name: Use the version
run: |
echo ${{ steps.version.outputs.version }}
- name: Use the previous version
run: |
echo ${{ steps.version.outputs.previous-version }}
You can use semantic-calendar-version to version different modules in a mono-repo structure.
This can be achieved by using different prefixes
and log-path
filters for
different modules.
Assuming the following directory structure, we can use semantic-calendar-version to generate
version with prefix module1-x.x.x
for changes in the module1/
directory
and module2-x.x.x
for changes in the module2/
directory.
.
├── Dockerfile
├── Makefile
├── README.md
├── module1
│ ├── Dockerfile
│ └── src/
└── module2
├── Dockerfile
└── src/
With github actions you can create different workflows that are triggered when changes happen on different directories.
# .github/workflows/module1.yml
name: Version Module 1
on:
pull_request:
paths:
- .github/workflows/module1.yml
- module1/**
push:
paths:
- .github/workflows/module1.yml
- module1/**
branches:
- master
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }} # checkout the correct branch name
fetch-depth: 0 # fetch the whole repo history
- name: Semantic Calendar Version
uses: lukashornych/[email protected]
with:
prefix: module1-
log-path: module1/
# .github/workflows/module2.yml
name: Version Module 2
on:
pull_request:
paths:
- .github/workflows/module2.yml
- module2/**
push:
paths:
- .github/workflows/module2.yml
- module2/**
branches:
- master
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }} # checkout the correct branch name
fetch-depth: 0 # fetch the whole repo history
- name: Semantic Calendar Version
uses: lukashornych/[email protected]
with:
prefix: module2-
log-path: module2/
Creates a version with the format YEAR.MINOR.PATCH
To use this you need to be in the working dir of a git project:
$ ./semantic-calendar-version
2024.1.0
Versions are incremented since the last tag or if new year comes. The patch version is incremented by default,
unless a new year came since last tag or there is at least one commit since the last tag, containing a minor identifier
(defaults to /feat(\([^\)]+\))?:/
) in the message.
On branches other than the master/main and development branch (default to master
and dev
) the version is a variation
of the latest common tag with the master/main branch, and has the following format:
{YEAR}.{MINOR}.{PATCH}-{sanitized-branch-name}.{commits-distance}.{hash}
On the development branch the format is the following:
{YEAR}.{MINOR}.{PATCH}-SNAPSHOT.{hash}
Example:
---A---B---C <= Master (tag: 2024.1.1) L <= Master (semantic-calendar-version: 2024.1.2)
\ /
D---E---F---G---H---I---J---K <= Foo (semantic-calendar-version: 2024.1.2-foo.8.5e30d83)
Example2 (with dev branch):
---A---B---C <= Master (tag: 2024.1.1) L <= Master (semantic-calendar-version: 2024.1.2)
\ / <= Fast-forward merges to master (same commit id)
C L <= Dev (semantic-calendar-version: 2024.1.2-SNAPSHOT.5e30d83)
\ /
E---F---G---H---I---J---K <= Foo (new_version: 2024.1.2-foo.7.5e30d83)
Example3 (with feature message):
---A---B---C <= Master (tag: 2024.1.1) L <= Master (semantic-calendar-version: 2024.2.0)
\ /
D---E---F---G---H---I---J---K <= Foo (semantic-calendar-version: 2024.2.0-foo.8.5e30d83)
\\
message: "feat: add magic button"
You can configure the action with various inputs, a list of which has been provided below:
Name | Description | Default Value |
---|---|---|
tool-version | The version of the tool to run | latest |
release-branch | The name of the master/main branch | master |
dev-branch | The name of the development branch | dev |
year_switch_mode | Specifies when to switch to a new year. Possible values: - Always - switches to a new year for all changes - OnMinor - switches to a new year only for minor changes, not for patch changes |
Always |
minor-identifier | The string used to identify a minor release (wrap with '/' to match using a regular expression) | feature: |
prefix | The prefix used for the version name | |
log-paths | The paths used to calculate changes (comma-separated) |
To use this tool you will need to install a few dependencies:
Ubuntu:
sudo apt-get install \
libevent-dev \
git
Fedora:
sudo dnf -y install \
libevent-devel \
git
Alpine:
apk add --update --no-cache --force-overwrite \
gc-dev pcre-dev libevent-dev \
git
OsX:
brew install \
libevent \
git
To compile locally you need to install crystal and possibly all required libraries. Then you can run everything locally using the makefile.
To get the list of available commands:
$ make help
This tool is heavily based on the git-version where all the versioning logic comes from.
semantic-calendar-version is available under the Apache 2 license. See the LICENSE file for more info.