Skip to content

Commit

Permalink
chore(check): add customizable allowed prefixes
Browse files Browse the repository at this point in the history
The allowed prefixes, which bypass the regex check,
can now be configured.
  • Loading branch information
Lotram committed Feb 18, 2023
1 parent 1ff575d commit 6e874d4
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 27 deletions.
8 changes: 8 additions & 0 deletions commitizen/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,14 @@
"default": False,
"help": "allow empty commit messages, which typically abort a commit",
},
{
"name": ["--allowed-prefixes"],
"action": "extend",
"nargs": "*",
"help": "allowed commit message prefixes. "
"If the message starts by one of these prefixes, "
"the message won't be checked against the regex",
},
],
},
{
Expand Down
18 changes: 10 additions & 8 deletions commitizen/commands/check.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import re
import sys
from typing import Any, Dict, Optional
from typing import Any, Dict, List, Optional

from commitizen import factory, git, out
from commitizen.config import BaseConfig
Expand Down Expand Up @@ -30,6 +30,13 @@ def __init__(self, config: BaseConfig, arguments: Dict[str, Any], cwd=os.getcwd(
arguments.get("allow_abort", config.settings["allow_abort"])
)

# we need to distinguish between None and [], which is a valid value
self.allowed_prefixes: List[str] = (
arguments.get("allowed_prefixes")
if arguments.get("allowed_prefixes") is not None
else config.settings["allowed_prefixes"]
)

self._valid_command_argument()

self.config: BaseConfig = config
Expand Down Expand Up @@ -132,12 +139,7 @@ def _filter_comments(msg: str) -> str:
def validate_commit_message(self, commit_msg: str, pattern: str) -> bool:
if not commit_msg:
return self.allow_abort
if (
commit_msg.startswith("Merge")
or commit_msg.startswith("Revert")
or commit_msg.startswith("Pull request")
or commit_msg.startswith("fixup!")
or commit_msg.startswith("squash!")
):

if any(map(commit_msg.startswith, self.allowed_prefixes)):
return True
return bool(re.match(pattern, commit_msg))
8 changes: 8 additions & 0 deletions commitizen/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class Settings(TypedDict, total=False):
tag_format: Optional[str]
bump_message: Optional[str]
allow_abort: bool
allowed_prefixes: List[str]
changelog_file: str
changelog_incremental: bool
changelog_start_rev: Optional[str]
Expand Down Expand Up @@ -62,6 +63,13 @@ class Settings(TypedDict, total=False):
"tag_format": None, # example v$version
"bump_message": None, # bumped v$current_version to $new_version
"allow_abort": False,
"allowed_prefixes": [
"Merge",
"Revert",
"Pull request",
"fixup!",
"squash!",
],
"changelog_file": "CHANGELOG.md",
"changelog_incremental": False,
"changelog_start_rev": None,
Expand Down
14 changes: 14 additions & 0 deletions docs/check.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
# Check

## About

This feature checks whether the commit message follows the given committing rules. And comment in git message will be ignored.

If you want to setup an automatic check before every git commit, please refer to
[Automatically check message before commit](auto_check.md).

## Usage

There are three mutually exclusive ways to use `cz check`:

- with `--rev-range` to check a range of pre-existing commits
- with `--message` or by piping the message to it to check a given string
- or with `--commit-msg-file` to read the commit message from a file

### Git Rev Range

If you'd like to check a commit's message after it has already been created, then you can specify the range of commits to check with `--rev-range REV_RANGE`.

```bash
Expand All @@ -25,7 +28,9 @@ For example, if you'd like to check all commits on a branch, you can use `--rev-
For more info on how git commit ranges work, you can check the [git documentation](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#_commit_ranges).

### Commit Message

There are two ways you can provide your plain message and check it.

#### Method 1: use -m or --message

```bash
Expand Down Expand Up @@ -59,3 +64,12 @@ cz check --message MESSAGE --allow-abort

Empty commit messages typically instruct Git to abort a commit, so you can pass `--allow-abort` to
permit them. Since `git commit` accepts an `--allow-empty-message` flag (primarily for wrapper scripts), you may wish to disallow such commits in CI. `--allow-abort` may be used in conjunction with any of the other options.

### Allowed Prefixes

If the commit message starts by some specific prefixes, `cz check` returns `True` without checkign the regex.
By default, the the following prefixes are allowed: `Merge`, `Revert`, `Pull Request`, `fixup!` and `squash!`.

```bash
cz check --message MESSAGE --allowed-prefixes 'Merge' 'Revert' 'Custom Prefix'
```
40 changes: 21 additions & 19 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,26 @@

## Settings

| Variable | Type | Default | Description |
| -------------------------- | ------ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | `str` | `"cz_conventional_commits"` | Name of the committing rules to use |
| `version` | `str` | `None` | Current version. Example: "0.1.2" |
| `version_files` | `list` | `[ ]` | Files were the version will be updated. A pattern to match a line, can also be specified, separated by `:` [See more][version_files] |
| `tag_format` | `str` | `None` | Format for the git tag, useful for old projects, that use a convention like `"v1.2.1"`. [See more][tag_format] |
| `update_changelog_on_bump` | `bool` | `false` | Create changelog when running `cz bump` |
| `gpg_sign` | `bool` | `false` | Use gpg signed tags instead of lightweight tags. |
| `annotated_tag` | `bool` | `false` | Use annotated tags instead of lightweight tags. [See difference][annotated-tags-vs-lightweight] |
| `bump_message` | `str` | `None` | Create custom commit message, useful to skip ci. [See more][bump_message] |
| `allow_abort` | `bool` | `false` | Disallow empty commit messages, useful in ci. [See more][allow_abort] |
| `changelog_file` | `str` | `CHANGELOG.md` | filename of exported changelog |
| `changelog_incremental` | `bool` | `false` | Update changelog with the missing versions. This is good if you don't want to replace previous versions in the file. Note: when doing `cz bump --changelog` this is automatically set to `true` |
| `changelog_start_rev` | `str` | `None` | Start from a given git rev to generate the changelog |
| `style` | `list` | see above | Style for the prompts (It will merge this value with default style.) [See More (Styling your prompts with your favorite colors)][additional-features] |
| `customize` | `dict` | `None` | **This is only supported when config through `toml`.** Custom rules for committing and bumping. [See more][customization] |
| `use_shortcuts` | `bool` | `false` | If enabled, commitizen will show keyboard shortcuts when selecting from a list. Define a `key` for each of your choices to set the key. [See more][shortcuts] |
| `major_version_zero` | `bool` | `false` | When true, breaking changes on a `0.x` will remain as a `0.x` version. On `false`, a breaking change will bump a `0.x` version to `1.0`. [major-version-zero] |
| `prerelease_offset` | `int` | `0` | In special cases it may be necessary that a prerelease cannot start with a 0, e.g. in an embedded project the individual characters are encoded in bytes. This can be done by specifying an offset from which to start counting. [prerelease-offset] |
| Variable | Type | Default | Description |
| -------------------------- | ------ | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | `str` | `"cz_conventional_commits"` | Name of the committing rules to use |
| `version` | `str` | `None` | Current version. Example: "0.1.2" |
| `version_files` | `list` | `[ ]` | Files were the version will be updated. A pattern to match a line, can also be specified, separated by `:` [See more][version_files] |
| `tag_format` | `str` | `None` | Format for the git tag, useful for old projects, that use a convention like `"v1.2.1"`. [See more][tag_format] |
| `update_changelog_on_bump` | `bool` | `false` | Create changelog when running `cz bump` |
| `gpg_sign` | `bool` | `false` | Use gpg signed tags instead of lightweight tags. |
| `annotated_tag` | `bool` | `false` | Use annotated tags instead of lightweight tags. [See difference][annotated-tags-vs-lightweight] |
| `bump_message` | `str` | `None` | Create custom commit message, useful to skip ci. [See more][bump_message] |
| `allow_abort` | `bool` | `false` | Disallow empty commit messages, useful in ci. [See more][allow_abort] |
| `allowed_prefixes` | `list` | `[ "Merge", "Revert", "Pull request", "fixup!", "squash!"]` | Allow some prefixes and do not try to match the regex when checking the message [See more][allowed_prefixes] |
| `changelog_file` | `str` | `CHANGELOG.md` | filename of exported changelog |
| `changelog_incremental` | `bool` | `false` | Update changelog with the missing versions. This is good if you don't want to replace previous versions in the file. Note: when doing `cz bump --changelog` this is automatically set to `true` |
| `changelog_start_rev` | `str` | `None` | Start from a given git rev to generate the changelog |
| `style` | `list` | see above | Style for the prompts (It will merge this value with default style.) [See More (Styling your prompts with your favorite colors)][additional-features] |
| `customize` | `dict` | `None` | **This is only supported when config through `toml`.** Custom rules for committing and bumping. [See more][customization] |
| `use_shortcuts` | `bool` | `false` | If enabled, commitizen will show keyboard shortcuts when selecting from a list. Define a `key` for each of your choices to set the key. [See more][shortcuts] |
| `major_version_zero` | `bool` | `false` | When true, breaking changes on a `0.x` will remain as a `0.x` version. On `false`, a breaking change will bump a `0.x` version to `1.0`. [major-version-zero] |
| `prerelease_offset` | `int` | `0` | In special cases it may be necessary that a prerelease cannot start with a 0, e.g. in an embedded project the individual characters are encoded in bytes. This can be done by specifying an offset from which to start counting. [prerelease-offset] |

## pyproject.toml or .cz.toml

Expand Down Expand Up @@ -118,6 +119,7 @@ commitizen:
[major-version-zero]: bump.md#-major-version-zero
[prerelease-offset]: bump.md#-prerelease_offset
[allow_abort]: check.md#allow-abort
[allowed_prefixes]: check.md#allowed-prefixes
[additional-features]: https://github.com/tmbo/questionary#additional-features
[customization]: customization.md
[shortcuts]: customization.md#shortcut-keys
Expand Down
33 changes: 33 additions & 0 deletions tests/commands/test_check_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,39 @@ def test_check_command_override_allow_abort_config(config, mocker: MockFixture):
error_mock.assert_called_once()


def test_check_command_with_allowed_prefixes_arg(config, mocker: MockFixture):
success_mock = mocker.patch("commitizen.out.success")
check_cmd = commands.Check(
config=config,
arguments={"message": "custom! test", "allowed_prefixes": ["custom!"]},
)

check_cmd()
success_mock.assert_called_once()


def test_check_command_with_allowed_prefixes_config(config, mocker: MockFixture):
success_mock = mocker.patch("commitizen.out.success")
config.settings["allowed_prefixes"] = ["custom!"]
check_cmd = commands.Check(config=config, arguments={"message": "custom! test"})

check_cmd()
success_mock.assert_called_once()


def test_check_command_override_allowed_prefixes_config(config, mocker: MockFixture):
error_mock = mocker.patch("commitizen.out.error")
config.settings["allow_abort"] = ["fixup!"]
check_cmd = commands.Check(
config=config,
arguments={"message": "fixup! test", "allowed_prefixes": ["custom!"]},
)

with pytest.raises(InvalidCommitMessageError):
check_cmd()
error_mock.assert_called_once()


def test_check_command_with_pipe_message(mocker: MockFixture, capsys):
testargs = ["cz", "check"]
mocker.patch.object(sys, "argv", testargs)
Expand Down
2 changes: 2 additions & 0 deletions tests/test_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"tag_format": None,
"bump_message": None,
"allow_abort": False,
"allowed_prefixes": ["Merge", "Revert", "Pull request", "fixup!", "squash!"],
"version_files": ["commitizen/__version__.py", "pyproject.toml"],
"style": [["pointer", "reverse"], ["question", "underline"]],
"changelog_file": "CHANGELOG.md",
Expand All @@ -66,6 +67,7 @@
"tag_format": None,
"bump_message": None,
"allow_abort": False,
"allowed_prefixes": ["Merge", "Revert", "Pull request", "fixup!", "squash!"],
"version_files": ["commitizen/__version__.py", "pyproject.toml"],
"style": [["pointer", "reverse"], ["question", "underline"]],
"changelog_file": "CHANGELOG.md",
Expand Down

0 comments on commit 6e874d4

Please sign in to comment.