# GitLab Flavored Semantic Versioning ## Goal This project tries to achieve automatic semantic versioning not basing the version bump on the conventional commits standars, but rather on a `Changelog` value on the trailer of commit messages. This works well if a project follows a similar workflow to the one used at GitLab, where each change must not be made on a development branch, never on the release branch and needs to get merged through a merge request. The beauty of this project is that you don't need to use the conventional commits specification, so you can have commits more similar to ```plaintext Added new feature A to address this requirement ``` instead of ```plaintext feat(): added new feature A to address this requirement ``` This translates to: - _**no "wasted" characters for that message prefix**_ - more readable commit messages - a nicer `Changelog` ```plaintext New features: - Added new feature A to address this requirement - Added feature B ``` vs ```plaintext New features: - feat(): added new feature A to address this requirement - feat: added feature B ``` ## Setup The only tool you need to setup this project on your local environment is Ruby, which can be downloaded using `asdf`. The Ruby version required is `3.2.4`. Once Ruby is present on your system you can install the dependencies by running ```shell bundle install ``` ## Testing At the moment there's no built-in testing platform, but I'm planning to use `rspec` to add unit tests. ## Usage ### Installation This project is available as a Ruby gem, so to be able to use it is enough to run ```shell gem install gfsm ``` Once that command completes, the gem will be available and you can invoke it from the command line with ```shell gfsm help ``` **Important**: `git` must be avaiable on the system for the gem to work. The main way this project can be used though, is inside a CI pipeline where you can invoke it to bump the version and/or update the changelog. To facilitate this, a docker image is published with every release of this tool. [Here](https://gitlab.com/zille_marco/gitlab-flavored-semantic-versioning/container_registry/3294324) is a list of all the available images. ### Available commands The main commands available are: - `gfsm version`: this command takes care of the project's verioning. - `gfsm changelog`: this command takes care of the project's changelog. - `gfsm help`: this command will display the available commands and their usage. To use these commands, you can invoke the `gfsm` executable from the command line. For example: ```shell gfsm version gfsm changelog ``` #### gfsm version The `version` command has its own subcommands: - `bump`: used to bump the version to the next one - `current`: used to extract the current version - `help`: used to print the usage of the `vesion` command itself All subcommands are configurable through either CLI flags or environment variables, that have precedence over the CLI flags. | CLI flag | Environment variable | Accepted values | Default | Description | | ------------------- | -------------------- | ------------------------------ | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | `--force` | `FORCE_BUMP` | | | If there are no commits with a changelog trailer, the version will still be bumped. | | `--force-version` | `FORCE_BUMP_VERSION` | `major`, `minor`, `patch` | `patch` | If the version needs to be force-bumped, this flag instructs the tool which section of the version to bump. | | `--prerelease` | `PRERELEASE` | | | Turns on prerelease generation, which by default appends `-pre` to the generated version. | | `--prerelease-name` | `PRERELEASE_NAME` | Any string without whitespaces | `pre` | When prerelease generation is enabled, this overrides the default `pre` value appended as suffix to the generated version. | | `--configuration` | `CONFIGURATION_FILE` | A file path | `./gfsmrc.yml` | The path to the YAML configuration file. | | `--path` | `REPOSITORY_PATH` | A folder path | `.` | The path to the folder containing the Git repository. | | `--from` | `FROM_COMMIT` | A commit SHA or a tag name | The latest **reachable** tag | The commit SHA or the tag name from where to start scraping for commit messages. | | `--to` | `TO_COMMIT` | A commit SHA or a tag name | `HEAD` | The commit SHA or the tag name where to stop scraping for commit messages. | | `--initial-version` | `INITIAL_VERSION` | A semantic version value | `0.0.0` | The version used when the project doesn't have one yet, useful for the first initialization of the project. | #### gfsm changelog The `changelog` command has its own subcommands: - `generate`: used to generate a changelog for the latest version - `extract`: used to extract a section from the changelog associated with a specific version - `help`: used to print the usage of the `changelog` command itself All subcommands are configurable through either CLI flags or environment variables, that have precedence over the CLI flags. The `changelog` command supports all the flags and environment variables of the `version` command, with the following additions. | CLI flag | Environment variable | Accepted values | Default | Description | | -------------------- | -------------------- | --------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--output-file` | `OUTPUT_FILE` | A file path | | The path to the CHANGELOG.md file, which will be created if not existing. If not specified the changelog will be written to stdout. **Only usable with `generate`**. | | `--input-file` | `INPUT_FILE` | A file path | `./CHANGELOG.md` | The path to the CHANGELOG.md file. **Only usable with `extract`**. | | `--no-incremental` | `NO_INCREMENTAL` | | | When provided, the output file will always be overridden and will contain only the changelog entries for the latest version. | | `--only-new-entries` | `ONLY_NEW_ENTRIES` | | | When provided, the output will always be written to stdout and will only contain the changelog for the latest changes without the version header. | | `--extract-version` | `EXTRACT_VERSION` | A version name | | When provided, this specifies the version that `extract` will extract the release notes from. If not provided, or set to `latest`, it will extract the release notes from the latest version. | ### Configuration GFSM can be cofigured by providing a YAML configuration file which will contain informations about the supported changelog trailers, the section they belong to and their priority. The schema is the following: ```plaintext change_types: : title: string matcher: string bump: major|minor|patch priority: number ``` Where: - `` is used only to separate the different sections - `title` is the title used when generating the changelog - `matcher` is the string that the commit changelog trailer has to contain in order to match the section - `bump` tells the tool which section of the version to bump when a commit changelog trailer matches the section - `priority` is used to order the sections when generating the changelog, the higher the priority the higher up the section will be in the changelog Here is an example: ```yaml change_types: new_features: title: "New features" matcher: added bump: minor priority: 6 feature_removals: title: "Feature removals" matcher: removed bump: major priority: 5 deprecations: title: "Deprecations" matcher: deprecated bump: minor priority: 4 feature_changes: title: "Feature changes" matcher: changed bump: minor priority: 3 fixes: title: "Fixes" matcher: fixed bump: patch priority: 2 security_fixes: title: "Security fixes" matcher: security bump: patch priority: 1 other: title: "Other" matcher: other bump: patch priority: 0 ```