knope 0.7.0

A command line tool for automating common development tasks
Documentation
# PrepareRelease step

This will look through all commits since the version tag and parse any [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) it finds. It will then bump the package version (depending on the [Semantic Versioning] rule determined from the commits) and add a new changelog entry using the [Keep A Changelog](https://keepachangelog.com/en/1.0.0/) format. Any files altered (`versioned_files` and `changelog`) will be staged for commit with `git add` **but not committed**.

The version bumping follows the same rules and logic as the [BumpVersion] step, with the rule selected for you automatically. Which files are edited (both for versioning and changelog) is determined by the [packages] section.

When multiple [packages] are configured—`PrepareRelease` runs for each package independently. The version tag _for that package_ will be the starting point.

```admonish note
The last "version tag" is used as the starting point to read commits—that's the most recent tag that was created by the [`Release`] step. See that step for details on the tagging formats.
```

## Limitations

The CHANGELOG format is pretty strict. Only three sections will be added to the new version, `### Breaking Changes` for anything that conventional commits have marked as breaking, `### Fixes` for anything called `fix:`, and `### Features` for anything with `feat: `. Any other commits (conventional or not) will be left out.

## Commit Scopes

The `PrepareRelease` step can be fine-tuned when working with multiple packages to only apply a commit to a specific package's version & changelog. This is done by adding a `scopes` array to the [packages] config and adding a [conventional commit scope] to the commits that should not apply to all packages. The following rules apply, in order, with respect to conventional commit scopes:

1. If no packages define `scopes` in their config, all commits apply to all packages. Scopes are not considered by `knope`.
2. If a commit does not have a scope, it applies to all packages.
3. If a commit has a scope, and _any_ package has defined a `scopes` array, the commit will only apply to those packages which have that scope defined in their `scopes` array.

## Examples

### Creating a Pre-release Version

If you include the `prerelease_label` option, the version created will be a pre-release version (treated like `Pre` rule in [BumpVersion]). This allows you to collect the commits _so far_ to an impending future version to get them out earlier.

```toml
[package]
versioned_files = ["Cargo.toml"]
changelog = "CHANGELOG.md"

[[workflows]]
name = "prerelease"

[[workflows.steps]]
type = "PrepareRelease"
prerelease_label = "rc"
```

If your prerelease workflow is exactly like your release workflow, you can instead temporarily add a prerelease label by passing the `--prerelease-label` option to `knope` or by setting the `KNOPE_PRERELEASE_LABEL` environment variable. This option overrides any set `prerelease_label` for any workflow run.

### Going from Pre-release to Full Release

Let's say that in addition to the configuration from the above example, you also have a section like this:

```toml
[[workflows]]
name = "release"

[[workflows.steps]]
type = "PrepareRelease"
```

And your changelog looks like this (describing some pre-releases you already have):

```md
## 2.0.0-rc.1

### Bug Fixes

- A bug in the first `rc` that we fixed.

## 2.0.0-rc.0

### Breaking Changes

- Cool new API

## 1.14.0

The last 1.x release.
```

Now you're ready to release 2.0.0—the version that's going to come after 2.0.0-rc.1. If you run the defined `release` rule, it will go all the way back to the tag `v1.14.0` and use the commits from that point to create the new version. In the end, you'll get version 2.0.0 with a new changelog entry like this:

```md
## 2.0.0

### Breaking Changes

- Cool new API

### Bug Fixes

- A bug in the first `rc` that we fixed.
```

### Multiple Packages with Scopes

Here's a `knope` config with two packages: `cli` and `lib`.

```toml
[package.cli]
versioned_files = ["cli/Cargo.toml"]
changelog = "cli/CHANGELOG.md"
scopes = ["cli"]

[package.lib]
versioned_files = ["lib/Cargo.toml"]
changelog = "lib/CHANGELOG.md"
scopes = ["lib"]

[[workflows]]
name = "release"

[[workflows.steps]]
type = "PrepareRelease"
```

The `cli` package depends on the `lib` package, so they will likely change together. Let's say the version of `cli` is 1.0.0 and the version of `lib` is 0.8.9. We add the following commits:

1. `feat(cli): Add a new --help option to display usage and exit`
2. `feat(lib)!: Change the error type of the parse function`
3. `fix: Prevent a crash when parsing invalid input`

The first two commits are scoped—they will only apply to the packages which have those scopes defined in their `scopes` array. The third commit is not scoped, so it will apply to both packages.

```admonish note
Here, the configured scopes are the same a the name of the package. This is common, but not required.
```

When the `release` workflow is run, the `cli` package will be bumped to 1.1.0 and the `lib` package will be bumped to 0.9.0. The changelog for `cli` will look like this:

```md
## 1.1.0

### Features

- Add a new --help option to display usage and exit

### Fixes

- Prevent a crash when parsing invalid input
```

And the changelog for `lib` will look like this:

```md
## 0.9.0

### Breaking Changes

- Change the error type of the parse function

### Fixes

- Prevent a crash when parsing invalid input
```

## Errors

The reasons this can fail:

1. The version could not be bumped for some reason.
2. The [packages] section is not configured correctly.
3. There was nothing to release. In this case it exits immediately so that there aren't problems with later steps.

[semantic versioning]: https://semver.org
[bumpversion]: ./BumpVersion.md
[packages]: ../packages.md
[`release`]: ./Release.md
[conventional commit scope]: https://www.conventionalcommits.org/en/v1.0.0/#commit-message-with-scope