-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add documentation and help text
- Replaces Click with Typer
- Loading branch information
Showing
20 changed files
with
507 additions
and
240 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
template: | ||
config: | ||
commit-link-pattern: https://github.com/multimac/conventional/commit/{commit} | ||
issue-link-pattern: https://github.com/multimac/conventional/issues/{issue} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) [year] [fullname] | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# Conventional | ||
|
||
## About | ||
|
||
Conventional is an extensible command-line tool for parsing and processing structured commits. It comes with support for the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard, but can be extended to support any other commit formats. | ||
|
||
## Requirements | ||
|
||
* Python 3.8+ | ||
* Git 2.27.0 | ||
|
||
## Installation | ||
|
||
Install and update using [pip](https://pip.pypa.io/en/stable/quickstart/): | ||
|
||
```bash | ||
$ pip install -U conventional | ||
``` | ||
|
||
## Usage | ||
|
||
### Listing Commits | ||
|
||
```bash | ||
$ conventional list-commits | ||
``` | ||
|
||
The `list-commits` command will retrieve git commits from a repository and output them in json, one object per commit per line, which can then be piped to, eg., `jq`. By default the command will output the raw fields retrieved from the commit, including the commit's subject, body, author, and date. | ||
|
||
This command can automatically parse commits by providing the `--parse` flag. If the flag is specified, commits will be instead output in the format described in [Parsing Commits](#parsing-commits). The `--include-unparsed` flag is supported in this command as will, and if provided commits which failed to be parsed will be output missing the `data` field. | ||
|
||
### Parsing Commits | ||
|
||
```bash | ||
$ conventional [--config .conventional.yaml] parse-commit | ||
``` | ||
|
||
The `parse-commit` command will read commits from a file or stdin and attempt to parse them using the configured parser. This command will output commits in json, one object per line, in the format `{"source": {}, "data": {}}`, where `source` contains the raw commit fields and `data` contains the fields parsed from the commit. | ||
|
||
If a commit cannot be parsed, by default it will not be included in the output. This behaviour can be disabled with the `--include-unparsed` flag, in which case commits that fail to be parsed will be output missing the `data` field (as no fields could be parsed). | ||
|
||
See [Parsers](#parsers) below for a list of parsers included with `conventional`. | ||
|
||
### Rendering commits into a template | ||
|
||
```bash | ||
$ conventional [--config .conventional.yaml] template | ||
``` | ||
|
||
The `template` command will read a stream of commits, determine different "versions" by looking at the tags on commits, and render them using the configured template. Templates are rendered using Jinja2, and are provided the list of versions along with any custom configuration specified in the configuration file. | ||
|
||
See [Templates](#templates) below for a list of templates included with `conventional`. | ||
|
||
### Notes | ||
|
||
Internally, some commands will use other commands to provide additional functionality and simplify common use-cases. | ||
|
||
For example... | ||
```bash | ||
$ conventional list-commits --parse # is equivalent to | ||
$ conventional list-commits | conventional parse-commit | ||
``` | ||
And... | ||
```bash | ||
$ conventional template # is equivalent to | ||
$ conventional list-commits | conventional parse-commit | conventional template --input - | ||
``` | ||
|
||
This means that if, for example, you wish to use `conventional template` but only use commits created since the last tag you can use the command `conventional list-commits --from-last-tag | conventional template --input -`. | ||
|
||
## Configuration | ||
|
||
Along with the command-line parameters, a configuration file can be provided via the `--config-file` parameter when calling `conventional`. By default `conventional` is configured to parse commits aligning to the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard and render them into a changelog, but this can be changed by configuring the `parser` and `template` sections in the config file, along with other things. | ||
|
||
See [config_default.yaml](conventional/config_default.yaml) to see what can be included in the configuration file. | ||
|
||
Below is a list of the parsers and templates provided by default with `conventional`. | ||
|
||
### Parsers | ||
|
||
#### [module: conventional.parser, name: ConventionalCommitParser](conventional/parser/conventional_commits.py) | ||
*Parses commits aligning to the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard.* | ||
|
||
##### Supported configuration: | ||
* `types` - The values which are allowed to be used as a `type` in commit messages. Any commits using a type not specified in this list will fail to parse correctly. | ||
|
||
### Templates | ||
|
||
#### [package: conventional, name: changelog.md](conventional/templates/changelog.md) | ||
*Renders commits in a format appropriate for a storing in a CHANGELOG.md file.* | ||
|
||
##### Supported configuration: | ||
* `commit-link-pattern` - This pattern will be used to generate a link to the commit, with `{rev}` being replaced with the hash of the commit and `{short_rev}` being replace with the short hash of the commit. For example, if you are using Github this may be `https://github.com/[owner]/[repo]/commit/{rev}`. | ||
* `issue-link-pattern` - This pattern will be used to generate a link to any issues references in the commit, with `{issue}` being expanded to the ID of the issue. For example, if you are using Jira this format may be `https://[company].atlassian.net/browse/{issue}`. | ||
* `type-headings` - A mapping of commit "type" to the text that should be used in the header for a specific type of change. Defaults to `{"feat": "Feature", "fix": "Fixes"}`. | ||
|
||
#### [package: conventional, name: slack.md](conventional/templates/slack.md) | ||
*Renders commits in a format appropriate for posting to Slack.* | ||
|
||
##### Supported configuration: | ||
* `commit-link-pattern` - This pattern will be used to generate a link to the commit, with `{rev}` being replaced with the hash of the commit and `{short_rev}` being replace with the short hash of the commit. For example, if you are using Github this may be `https://github.com/[owner]/[repo]/commit/{rev}`. | ||
* `issue-link-pattern` - This pattern will be used to generate a link to any issues references in the commit, with `{issue}` being expanded to the ID of the issue. For example, if you are using Jira this format may be `https://[company].atlassian.net/browse/{issue}`. | ||
* `type-headings` - A mapping of commit "type" to the text that should be used in the header for a specific type of change. Defaults to `{"feat": "Feature", "fix": "Fixes"}`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .cli import main | ||
from .parser import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
from conventional.main import main | ||
from conventional.cli import main | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import enum | ||
import logging | ||
import pathlib | ||
|
||
import confuse | ||
import typer | ||
|
||
from . import util | ||
from .commands import group as main | ||
|
||
handler = util.TyperHandler() | ||
handler.formatter = util.ColorFormatter() | ||
|
||
logger = logging.getLogger() | ||
logging.basicConfig(handlers=[handler], force=True) | ||
|
||
logging.getLogger("aiocache").setLevel(logging.ERROR) | ||
|
||
|
||
class Verbosity(str, enum.Enum): | ||
critical = "CRITICAL" | ||
debug = "DEBUG" | ||
error = "ERROR" | ||
fatal = "FATAL" | ||
info = "INFO" | ||
warning = "WARNING" | ||
|
||
|
||
@main.callback() | ||
def init( | ||
ctx: typer.Context, | ||
config_file: pathlib.Path = typer.Option( | ||
None, exists=True, dir_okay=False, help="A file to read configuration values from.", | ||
), | ||
verbosity: Verbosity = typer.Option( | ||
Verbosity.info, case_sensitive=False, help="Set the verbosity of the logging." | ||
), | ||
) -> None: | ||
""" | ||
Conventional - An extensible command-line tool for parsing and processing structured commits. | ||
""" | ||
|
||
logging.getLogger().setLevel(getattr(logging, verbosity)) | ||
|
||
config = confuse.Configuration("Conventional", "conventional") | ||
if config_file is not None: | ||
config.set_file(config_file) | ||
|
||
ctx.obj = config | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
from asyncio import run | ||
from pathlib import Path | ||
from typing import Optional | ||
|
||
from confuse import Configuration | ||
from typer import Argument, Context, FileText, Option, Typer | ||
|
||
group = Typer() | ||
|
||
|
||
@group.command("list-commits") | ||
def _list_commits( | ||
ctx: Context, | ||
*, | ||
output: FileText = Option( | ||
"-", | ||
help="A file to write commits to. If `-`, commits will be written to stdout.", | ||
mode="w", | ||
), | ||
from_rev: Optional[str] = Option( | ||
None, "--from", help="The commit or tag to start from when listing commits from." | ||
), | ||
from_last_tag: bool = Option( | ||
False, | ||
"--from-last-tag", | ||
help="If given, the commit list will start from the most-recent tag.", | ||
), | ||
to_rev: str = Option("HEAD", "--to", help="The commit or tag to stop at listing commits."), | ||
reverse: bool = Option( | ||
False, | ||
"--reverse", | ||
help="If given, the list of commits will be reversed (ie. oldest commit first).", | ||
), | ||
parse: bool = Option( | ||
False, "--parse", help="If set, commits will be parsed with `parse-commit`." | ||
), | ||
include_unparsed: bool = Option( | ||
False, | ||
help="If set, commits which fail to be parsed will be included in the output. See `parse-commit`.", | ||
), | ||
path: Optional[Path] = Argument(None), | ||
) -> None: | ||
""" | ||
Retrieves commits from the git repository at PATH, or the current directory if PATH is not provided. | ||
""" | ||
|
||
from .list_commits import main | ||
|
||
run( | ||
main( | ||
ctx.find_object(Configuration), | ||
output=output, | ||
from_rev=from_rev, | ||
from_last_tag=from_last_tag, | ||
to_rev=to_rev, | ||
reverse=reverse, | ||
parse=parse, | ||
include_unparsed=include_unparsed, | ||
path=path, | ||
) | ||
) | ||
|
||
|
||
@group.command("parse-commit") | ||
def _parse_commit( | ||
ctx: Context, | ||
*, | ||
input: FileText = Option( | ||
"-", help="A file to read commits from. If `-`, commits will be read from stdin." | ||
), | ||
output: FileText = Option( | ||
"-", | ||
help="A file to write parsed commits to. If `-`, parsed commits will be written to stdout.", | ||
mode="w", | ||
), | ||
include_unparsed: bool = Option( | ||
False, help="If set, commits which fail to be parsed will be returned." | ||
), | ||
) -> None: | ||
""" | ||
Parses a stream of commits in the given file or from stdin. | ||
""" | ||
|
||
from .parse_commit import main | ||
|
||
run( | ||
main( | ||
ctx.find_object(Configuration), | ||
input=input, | ||
output=output, | ||
include_unparsed=include_unparsed, | ||
) | ||
) | ||
|
||
|
||
@group.command("template") | ||
def _template( | ||
ctx: Context, | ||
*, | ||
input: Optional[FileText] = Option( | ||
None, | ||
help="A file to read commits from. If `-`, commits will be read from stdin. Defaults to reading commits from a git repository in the current directory.", | ||
), | ||
output: FileText = Option( | ||
"-", | ||
help="A file to write parsed commits to. If `-`, parsed commits will be written to stdout.", | ||
mode="w", | ||
), | ||
include_unparsed: bool = Option( | ||
False, | ||
help="If set, commits which fail to be parsed will be returned. See `parse-commit`.", | ||
), | ||
path: Optional[Path] = Argument(None), | ||
) -> None: | ||
""" | ||
Reads a stream of commits from the given file or stdin and uses them to render a template. | ||
""" | ||
|
||
from .template import main | ||
|
||
run( | ||
main( | ||
ctx.find_object(Configuration), | ||
input=input, | ||
output=output, | ||
include_unparsed=include_unparsed, | ||
path=path, | ||
) | ||
) |
Oops, something went wrong.