/go-semver-release

Go program designed to automate semantic versioning of Git repository by analyzing their formatted commit history and tagging them with the right semver.

Primary LanguageGoMIT LicenseMIT

go version badge github actions badge go report card license badge

Go SemVer Release

Go program designed to automate versioning of Git repository by analyzing their formatted commit history and tagging them with the right semver number. This program can be used directly via its CLI or its corresponding GitHub Action.

Motivation

Handling a Git repository versions can be done using well-thought convention such as SemVer so that your API consumers know when a non-retro-compatible change is introduced in your API. Building on that, versioning automation can be achieved by using formated commits following the Conventional Commit convention.

This project was built to create a lightweight and simple tool to seamlessly automate versioning on your Git repository. Following the UNIX philosophy of "make each program do one thing well", it only handles publishing semver tags to your Git repository, no package publishing or any other features.

The Docker image merely weight 7Mb and the Go program inside will compute your semver tag in seconds, no matter the size of your commit history.

This tool aims to integrate semantic versioning automation in such a way that, all you have to do is:

  • Choose a release branch (e.g., main, release)

  • Take care to format commits on that branch by following the Conventional Commit convention, which many IDEs plugins offers to do seamlessly (e.g., VSCode, IntelliJ)

Note: go-semver-release can only read annotated Git tags, so if you plan on only using it in dry-run mode to then use its output to tag your repository with an other action, make sure the tag you are pushing is annotated, otherwise the program will not be able to detect it.

Install

If Go is installed on your machine, you can install from source using go install:

$ go install github.com/s0ders/go-semver-release/cmd/go-semver-release@v1.5.2
$ go-semver-release --help

For cross-platform compatibility, you can use the generated Docker image:

$ docker pull soders/go-semver-release@
$ docker run --rm soders/go-semver-release --help

Verify that the downloaded image has not be tampered using Cosign:

$ PUB_KEY=https://raw.githubusercontent.com/s0ders/go-semver-release/main/cosign.pub
$ cosign verify --key $PUB_KEY soders/go-semver-release@

Each Docker image comes with a corresponding SBOM (SPDX format) also signed using the same key-pair.

Prerequisites

There are only a few prerequisites for using this tool and getting the benefits it brings :

  • The Git repository commits must follow the Conventional Commit convention, as it is what is used to compute the semantic version.
  • The repository passed to the program (or action) must already be initialized (i.e. Git HEAD does not point to nothing)

Usage

You must pass the Git URL of the repository to target using the --url flag:

$ go-semver-release --url <GIT URL>

Because the program needs to push tag to the remote, it must authenticate itself using a personal access token passed with --token:

$ go-semver-release [...] --token <ACCESS TOKEN>

The release branch on which the commits are fetched is specified using --branch:

$ go-semver-release [...] --branch <BRANCH NAME>

Custom release rules are passed to the program using the --rules:

$ go-semver-release [...] --rules <PATH TO RULES>

The program supports a dry-run mode that will only compute the next semantic version, if any, and will stop here without pushing any tag to the remote, dry-run is false by default:

$ go-semver-release [...] --dry-run true

Verbose output can be enabled as bellow which will show each commit (hash and short message) that triggers a release during the process and the associated release type, verbose output is false by default:

$ go-semver-release [...] --verbose true

A custom prefix can be added to the tag name pushed to the remote, by default the tag name correspond to the SemVer (e.g. 1.2.3) but you might want to use some prefix like v using --tag-prefix:

$ go-semver-release [...] --tag-prefix <PREFIX>

Note: You can change your tag prefix during the lifetime of your repository (e.g., going from none to v) and this will not affect your semver tags history, meaning that the program will still be able to recognize semver tags made with your old-prefixes, if any. There are no limitation to how many time you can change your tag prefix during the lifetime of your repository.

GitHub Actions

Inputs

The action takes the same parameters as those defined in the usage section. Note that the boolean flags (e.g., --dry-run, --verbose) need to be passed as a string inside your YAML work-flow due to how Github Actions works.

Outputs

The action generate a two outputs

  • SEMVER, the computed semver or the current one if no new were computed, prefixed with the given tag-prefix if any;
  • NEW_RELEASE, whether a new semver was computed or not.

Example Workflow

Bellow is an example of this action inside a GitHub Actions pipeline.

jobs:
  go-semver-release:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Semver Release
      uses: s0ders/go-semver-release@v1.5.2
      with:
        repository-url: 'https://github.com/path/to/your/repo.git'
        tag-prefix: 'v'
        branch: 'release'
        dry-run: 'true'
        verbose: 'true'
        token: ${{ secrets.ACCESS_TOKEN }}

Release Rules

Release rules define which commit type will trigger a release, and what type of release (i.e. major, minor, patch). By default, the program applies the following release rules:

{
    "releaseRules": [
        {"type": "feat", "release": "minor"},
        {"type": "perf", "release": "minor"},
        {"type": "fix", "release": "patch"}
    ]
}

You can define custom release rules to suit your needs using a JSON file and by passing it to the program as bellow. Be careful with release rules though, especially major ones, as their misuse might easily make you loose the benefits of using a semantic version number.

{
    "releaseRules": [
        {"type": "feat", "release": "minor"},
        {"type": "perf", "release": "patch"},
        {"type": "refactor", "release": "patch"},
        {"type": "fix", "release": "patch"}
    ]
}

The following type are supported for release rules: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test.

The following release types are supported for release rules: major, minor, patch.

WIP

  • Use Cobra for better CLI
  • Support a local mode (repo already on local host, no need to push tags to a remote, no token)