Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add docs
Browse files Browse the repository at this point in the history
brianbruggeman committed May 25, 2024

Verified

This commit was signed with the committer’s verified signature.
joshcooper Josh Cooper
1 parent 2585d68 commit 2fc70f2
Showing 12 changed files with 486 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book
9 changes: 9 additions & 0 deletions docs/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[book]
authors = ["Brian Bruggeman"]
language = "en"
multilingual = false
src = "src"
title = "Semrel"

[output.html]
render-link = "render-link = \"{filename}.html\""
1 change: 1 addition & 0 deletions docs/src/.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Usage
9 changes: 9 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Summary

- [Motivation](./motivation.md)
- [Capabilities](./capabilities.md)
- [Basic rules](./basic-rules.md)
- [Algorithms](./algorithms.md)
- [Configuration](./configuration.md)
- [Usage](./usage.md)
- [Future work](./future-work.md)
105 changes: 105 additions & 0 deletions docs/src/algorithms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Algorithm

## Overview

The algorithm navigates through a repository's commit history, using Conventional Commits to determine the next version and generate release notes. It's designed for use in CI/CD pipelines, providing automated version determination and release notes creation.

Starting with the current version from the manifest file, the algorithm backtracks through the commits in the current branch, categorizing commit messages according to Conventional Commits. It identifies the highest level bump and the last updated manifest file at that level. If a commit type above the current level is found, the search continues at this new level until a manifest file with the correct version update is found, at which point the new version is returned.

A PEST parser is used to parse commit messages and extract the commit type, scope, subject, body, and footer. Non-compliant commit messages are recognized but do not trigger a version bump by default. Custom rules for version bumping can be provided, with the algorithm prioritizing rules from the command-line --rule flag, the configuration file, and finally, hard-coded default rules.

## Changelog

The tool will first look at the current manifest file and determine the current version. Then the tool will start walking backwards for all of the commits in the current branch. The tool looks for and categorizes the commit messages based on Conventional Commits. The following are recognized commit types:

- `build`: Changes that affect the build system or external dependencies (example scopes: cargo, npm)
- `cd`: Continuous Deployment
- `chore`: Other changes that don't modify src or test files
- `ci`: Changes to our CI configuration files and scripts (example scopes: github-actions)
- `docs`: Documentation only changes
- `feat`: A new feature
- `fix`: A bug fix
- `perf`: A code change that improves performance
- `refactor`: A code change that neither fixes a bug nor adds a feature
- `revert`: Reverts a previous commit
- `style`: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
- `test`: Adding missing tests or correcting existing tests

As the tool is walking, the tool is checking for the highest level bump and the last updated manifest file that has the same level. When the tool identifies a commit type above the current level, then the tool will continue searching for that new level. Once the tool identifies a manifest file with the correct version update for the new level, the tool will stop searching and return the new version.

## Base Commit bump rules

To extract that information, a PEST parser is used to parse the commit messages. The parser is defined in the `src/core/conventional_commits/commit_message.pest` file. The parser is then used to extract the commit type, scope, subject, body, and footer. The commit type is used to determine the next version. The scope and description are used to generate the release notes.

To be compliant, the type is required, but the scope, body, and footer are optional. The type is used to determine the next version. The scope is used to group the commits in the release notes. The body and footer are used to generate the release notes.

Additionally, non-compliant commit messages are recognized, but will not bump the version by default. It is possible to generally follow the conventional commit format and then provide custom rules for the bumping of the version.

Default rules are encoded in the `src/core/semantic_release/bump_rule_mapping.rs` file.

- Major: `BREAKING CHANGE` must be present somewhere in the commit message
- Minor: `feat` is the only commit type by default that bumps a minor version
- Patch: `chore`, `fix`, `perf`, `refactor`, `revert`, and `style` will all bump a patch version

> **NOTE:** The `BREAKING CHANGE` must be in the commit message body or footer. It is not required to be in the commit message subject.
> **NOTE:** the scope cannot be a standard commit type. If the scope is a standard commit type, then the tool will flag it as an error.
### Examples

#### Template
The basic format of a commit message is:

```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```

#### Breaking Change (Major)
A full example of a major breaking change. In this example, the type is `feat`, the scope is `core`, and the subject is `add new feature`.
```feat(core): add new feature
This is a new feature that we have added to the core library.
BREAKING CHANGE: The function signature has changed from `fn foo(a: i32, b: i32) -> i32` to `fn foo(a: i32, b: i32, c: i32) -> i32`. This was necessary to support building our new feature.
```

#### Feature update (Minor)
A smaller example of a minor feature. In this example, the type is `feat`, the scope is `core`, and the subject is `add new feature`.
```feat(core): add new feature```

#### Bug Fix (Patch)
A smaller example of a patch fix. In this example, the type is `fix`, the scope is `core`, and the subject is `fix bug`.
```fix(core): fix bug```

#### Semi-Compliant (NoBump)
A semi-compliant example. In this semi-compliant example, the type is `ENG-1234`, the scope is `none`, and the subject is `fix bug`. Because the type is not recognized, the tool will not bump the version.
```ENG-1234: fix bug```

#### Non-Compliant (NoBump)
A Non-compliant example. In this non compliant example, there is no type. The entire message is pulled into the subject.
```JohnDoe - add new feature```


## Customzing Rules

Custom rules currently can be added via a --rule flag. The algorithm for determining the bump rule to use is based on "which comes first". The order of precedence is:

- command-line --rule flag
- configuration file
- hard-coded default rules

So if a rule is present in the command-line --rule flag, then that rule will be used. If a rule is not present in the command-line --rule flag, then the configuration file will be checked. If a rule is not present in the configuration file, then the hard-coded default rules will be used.

The bump rules are a critical aspect because the version is determined by the highest level bump found in the commit history. If rules are changed between runs, then the version will be different.

An example for a custom rule might be:

```bash
$ semrel --rule ENG-1234=minor
```

And then with the following commit message, we would bump the minor version:
```ENG-1234: add new feature```
42 changes: 42 additions & 0 deletions docs/src/basic-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Basic rules

## Major

The goal of a major version is to indicate a breaking change. This can be done by including "BREAKING CHANGE" in the commit message body or footer. Alternatively, you can force a major version bump by using the `--bump=major` flag. This will increment the major version by one and reset the minor and patch versions to zero. For example, if the current version is `1.2.3`, the new version with a major bump will be `2.0.0`. Keeping with best practices of Semantic Versioning, the major version should be updated when incompatible changes are introduced.

Breaking changes can include:
- Changes to the public API
- Changes to the configuration file
- Changes to the command-line interface
- Changes to the environment variables
- Changes to the database schema

A Breaking Change should have a detailed description of the change and the reasoning behind it. This will help users understand the impact of the change and how to adapt to the new version.

## Minor

The goal of a minor version is to indicate a new feature. This can be done by including "feat" in the commit message type. Alternatively, you can force a minor version bump by using the `--bump=minor` flag. This will increment the minor version by one and reset the patch version to zero. For example, if the current version is `1.2.3`, the new version with a minor bump will be `1.3.0`. Keeping with best practices of Semantic Versioning, the minor version should be updated when new features are introduced.

New features can include:
- New functionality
- New endpoints
- New commands
- New configuration options
- New environment variables

A New Feature should have a detailed description of the feature and the reasoning behind it. This will help users understand the new functionality and how to use it. However, new features should not introduce breaking changes. If a new feature requires a breaking change, it should be considered a major version bump.

## Patch

The goal of a patch version is to indicate a bug fix. This can be done by including "fix" in the commit message type. Alternatively, you can force a patch version bump by using the `--bump=patch` flag. This will increment the patch version by one. For example, if the current version is `1.2.3`, the new version with a patch bump will be `1.2.4`. Keeping with best practices of Semantic Versioning, the patch version should be updated when bugs are fixed or minor improvements are made.

Patches can include:
- Refactoring
- Performance improvements
- Code cleanup
- Reverting changes
- Style changes
- Bug fixes

The Bug Fix should have a detailed description of the bug and the reasoning behind the fix. This will help users understand the impact of the bug and how to adapt to the new version. However, bug fixes should not introduce breaking changes. If a bug fix requires a breaking change, it should be considered a major version bump.

10 changes: 10 additions & 0 deletions docs/src/capabilities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Capabilities

The following capabilities are supported by the current version of the tool:

- **Conventional Commits**: The tool uses Conventional Commits to determine the next version. This is inspired by semantic-release.
- **Version determination**: The tool determines the next version based on the commit history from a git repository.
- **Logging**: The tool logs the versioning decisions made during the process. This can be accessed by setting `RUST_LOG`
- **Standalone**: The tool is a standalone binary that requires no additional plugins or packages.
- **Compatibility**: The tool is compatible with various languages and ecosystems.
- **Customizable**: The tool allows for custom rules to be defined for commit types.
31 changes: 31 additions & 0 deletions docs/src/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Configuration

## Bump Rules

The configuration file uses the Toml format. The following is an example of a configuration file and is the default configuration used by the tool.

```toml
[semrel.rules]
feat = "minor"
chore = "patch"
fix = "patch"
perf = "patch"
refactor = "patch"
revert = "patch"
style = "patch"
build = "none"
ci = "none"
cd = "none"
docs = "none"
test = "none"
```

## Location

The configuration file maybe located in the following locations (in order of precedence):

- next to the manifest file (e.g. Cargo.toml or package.json or pyproject.toml)
- at the root of the project (e.g. .semrel.toml)
- in an XDG compliant configuration directory (e.g. $XDG_CONFIG_HOME/semrel/config.toml)
- under $HOME/.config/semrel/config.toml (if $XDG_CONFIG_HOME is not set)
- in the system configuration directory (e.g. /etc/semrel/config.toml)
98 changes: 98 additions & 0 deletions docs/src/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Examples

This section contains a few examples of how to use the library from the command line.

## Basic usage

The following command will determine the next version based on the commit history of the current repository:

```bash
$ semrel
0.3.0
```

## Show the current version
```bash
$ semrel show current
0.2.3
```

## Custom rules

Custom rules can be defined via the `--rule` flag. The following command will bump the version to a minor version if the commit message contains `ENG-1234`:

```bash
$ git log -1 --pretty=%B
ENG-1234: add new feature

$ semrel show next --rule ENG-1234=minor
0.3.0
```

## Show the log used to calculate the version

The following command will show the commit log used to calculate the version:

```bash
$ semrel --log
f7e8fc4fc26f83f8053bd78c9475ba67b643f182 ci: add ci
ec79645b01ee77c6a7fa9b522534fbcf159c22ea chore(git): fix ignored
191ba409562f345d290014fa2a1c30fb784c61b7 feat(docker): Add example dockerfile
d47b19bbd040725d37d30f155e0ed78088cc1895 docs: simplify readme
c78f934b20845c0f1dfdd95043eb904d94fbb29a fix(commit-type): update release notes
06b31c48954e0b48599cf78d179586f69277c398 fix(deps): reduce git footprint
078e0ec70e6a0699e0654d09320a5808c2acfaad test(invalid_json): fix broken test
97f72245da66f1eef77ff949c1935f4e08fbaa98 fix(changelog): manages edge cases around bumps
3f2e48af7ddc2fe38de15b710d07b8747c0971a3 tested release
```

## Show the release notes

The following command will show the release notes:

```bash
$ semrel --notes
# Release notes: 0.3.0 (2024-05-24)


## Features

### docker
- Add example dockerfile


## Fixes

### changelog
- manages edge cases around bumps

### commit-type
- update release notes

### deps
- reduce git footprint


## Test

### invalid_json
- fix broken test


## Chore

### git
- fix ignored


## Continuous Integration
- add ci


## Documentation
- simplify readme


## Non Compliant
- tested release
```
11 changes: 11 additions & 0 deletions docs/src/future-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Future work

Rather than having a roadmap, these are a list of ideas that should be explored.

- [ ] Generating commits, tags, etc. to simplify workflows
- [ ] Adding a github action to automatically update the manifest file
- [ ] Adding support for Rust workspaces and monorepos
- [ ] Pattern matching for commit messages
- [ ] Release notes templates
- [ ] More care and consideration for using semrel as a library
- [ ] Consider scope as a configurable control mechanism for bumping versions
17 changes: 17 additions & 0 deletions docs/src/motivation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Motivation

## Problem

The current deployment process in many projects is only partially automated, with versions being managed manually within pull requests. This often leads to versions being forgotten to be updated, causing confusion about the deployed version and slowing down the deployment process. The team needs a lightweight, customizable tool that integrates well with git and command-line interfaces, and can determine the next version based on commit history. The frequency of forgotten version updates, the process for backtracking when a version is forgotten, the checks in place for version updates, and the process for tracking the version in production are all areas of concern. The impact of the current process on productivity and the specific issues arising from forgotten version updates also need to be addressed.

## Existing Solutions

We looked at semantic-release, which is a popular tool for automating versioning and releases. Cargo-release is another tool, but in both cases, they seem to be primarily focused on a specific domain (e.g. npm packages or Rust projects). The expansive ecosystem of semantic-release is compelling. But the tooling itself was difficult to debug and failed to just work in Rust and Python projects. Because we want to support Rust, Python, Typescript and Javascript, we needed something that was lightweight, more flexible and plugged into existing github actions without obfuscating the process used to develop the next version.

## Goals

- Implement Conventional Commits for version determination, inspired by semantic-release.
- Establish a clear and intuitive process for versioning.
- Enhance user understanding through comprehensive logging of versioning decisions.
- Develop a standalone tool that requires no additional plugins or packages.
- Ensure the tool's compatibility across various languages and ecosystems.
152 changes: 152 additions & 0 deletions docs/src/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Usage

This section contains a few examples of how to use the library from the command line.

## How we might use this
```bash
# What's the change log for this new version?
$ semrel show log
f7e8fc4fc26f83f8053bd78c9475ba67b643f182 ci: add ci
ec79645b01ee77c6a7fa9b522534fbcf159c22ea chore(git): fix ignored
191ba409562f345d290014fa2a1c30fb784c61b7 feat(docker): Add example dockerfile
d47b19bbd040725d37d30f155e0ed78088cc1895 docs: simplify readme
c78f934b20845c0f1dfdd95043eb904d94fbb29a fix(commit-type): update release notes
06b31c48954e0b48599cf78d179586f69277c398 fix(deps): reduce git footprint
078e0ec70e6a0699e0654d09320a5808c2acfaad test(invalid_json): fix broken test
97f72245da66f1eef77ff949c1935f4e08fbaa98 fix(changelog): manages edge cases around bumps
3f2e48af7ddc2fe38de15b710d07b8747c0971a3 tested release

# What's the current version?
$ semrel show current
0.2.0

# What's the next version based on the changelog?
$ semrel show next
0.3.0

# How did we get to this version?
$ RUST_LOG=semrel=debug semrel show next
2024-05-24T12:39:42.266931Z DEBUG semrel::core::git::repo: Searching for repository under: .
2024-05-24T12:39:42.267995Z DEBUG semrel::core::git::repo: Found repository at: /Users/brianbruggeman/repos/mine/semrel
2024-05-24T12:39:42.268012Z DEBUG semrel::core::git::log: Starting get_changelog for path: /Users/brianbruggeman/repos/mine/semrel
2024-05-24T12:39:42.268054Z DEBUG semrel::manifests::supported_manifests: Parsing manifest: "/Users/brianbruggeman/repos/mine/semrel/Cargo.toml"
2024-05-24T12:39:42.268062Z DEBUG semrel::manifests::cargo_toml: Parsing Cargo.toml
2024-05-24T12:39:42.268293Z DEBUG semrel::manifests::cargo_toml: Parsed manifest.
2024-05-24T12:39:42.268308Z DEBUG semrel::manifests::supported_manifests: Getting version from manifest
2024-05-24T12:39:42.268312Z DEBUG semrel::manifests::supported_manifests: Version: Ok(SimpleVersion { major: 0, minor: 2, patch: 0 })
2024-05-24T12:39:42.268316Z DEBUG semrel::manifests::supported_manifests: Parsed manifest version: SimpleVersion { major: 0, minor: 2, patch: 0 }
2024-05-24T12:39:42.268320Z DEBUG semrel::manifests::supported_manifests: Getting filename from manifest
2024-05-24T12:39:42.268322Z DEBUG semrel::manifests::supported_manifests: Filename: Ok("Cargo.toml")
...
2024-05-24T12:39:42.284358Z DEBUG semrel::core::git::log: Finished get_changelog
2024-05-24T12:39:42.284368Z DEBUG semrel::core::semantic_release::bump_rule_mapping: Finding rule for Ci
2024-05-24T12:39:42.284371Z DEBUG semrel::core::semantic_release::bump_rule_mapping: Finding rule for Chore
2024-05-24T12:39:42.284373Z DEBUG semrel::core::semantic_release::bump_rule_mapping: Finding rule for Feat
2024-05-24T12:39:42.284375Z DEBUG semrel::core::semantic_release::bump_rule_mapping: Finding rule for Docs
2024-05-24T12:39:42.284378Z DEBUG semrel::core::semantic_release::bump_rule_mapping: Finding rule for Fix
2024-05-24T12:39:42.284382Z DEBUG semrel::core::semantic_release::bump_rule_mapping: Finding rule for Fix
2024-05-24T12:39:42.284384Z DEBUG semrel::core::semantic_release::bump_rule_mapping: Finding rule for Test
2024-05-24T12:39:42.284386Z DEBUG semrel::core::semantic_release::bump_rule_mapping: Finding rule for Fix
2024-05-24T12:39:42.284388Z DEBUG semrel::core::semantic_release::bump_rule_mapping: Finding rule for NonCompliant
0.3.0
```
## Basic usage
The following command will determine the next version based on the commit history of the current repository:
```bash
$ semrel
0.3.0
```
## Show the current version
```bash
$ semrel show current
0.2.3
```
## Custom rules
Custom rules can be defined via the `--rule` flag. The following command will bump the version to a minor version if the commit message contains `ENG-1234`:
```bash
$ git log -1 --pretty=%B
ENG-1234: add new feature
$ semrel show next --rule ENG-1234=minor
0.3.0
```
# Update the manifest
```bash
$ semrel update
```
## Show the log used to calculate the version
The following command will show the commit log used to calculate the version:
```bash
$ semrel show log
f7e8fc4fc26f83f8053bd78c9475ba67b643f182 ci: add ci
ec79645b01ee77c6a7fa9b522534fbcf159c22ea chore(git): fix ignored
191ba409562f345d290014fa2a1c30fb784c61b7 feat(docker): Add example dockerfile
d47b19bbd040725d37d30f155e0ed78088cc1895 docs: simplify readme
c78f934b20845c0f1dfdd95043eb904d94fbb29a fix(commit-type): update release notes
06b31c48954e0b48599cf78d179586f69277c398 fix(deps): reduce git footprint
078e0ec70e6a0699e0654d09320a5808c2acfaad test(invalid_json): fix broken test
97f72245da66f1eef77ff949c1935f4e08fbaa98 fix(changelog): manages edge cases around bumps
3f2e48af7ddc2fe38de15b710d07b8747c0971a3 tested release
```
## Show the release notes
The following command will show the release notes:
```bash
$ semrel show notes
# Release notes: 0.3.0 (2024-05-24)
## Features
### docker
- Add example dockerfile
## Fixes
### changelog
- manages edge cases around bumps
### commit-type
- update release notes
### deps
- reduce git footprint
## Test
### invalid_json
- fix broken test
## Chore
### git
- fix ignored
## Continuous Integration
- add ci
## Documentation
- simplify readme
## Non Compliant
- tested release
```

0 comments on commit 2fc70f2

Please sign in to comment.