Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6429d4e
feat(changelog): changelog tree generation from markdown
woile Jul 20, 2019
546828e
feat(cz/base): add default process_commit for processing commit message
Lee-W Jan 15, 2020
705dc2f
feat(cz/conventinal_commits): add changelog_map, changelog_pattern an…
Lee-W Jan 15, 2020
d104367
feat(commands/changelog): generate changelog_tree from all past commits
Lee-W Jan 15, 2020
10a0f3d
feat(changelog): generate changelog based on git log
Lee-W Jan 17, 2020
9ea446c
style(all): blackify
Lee-W Jan 15, 2020
4e58392
refactor(commands/changelog): use jinja2 template instead of string c…
Lee-W Jan 23, 2020
741e66d
fix(cli): add changelog arguments
Lee-W Jan 23, 2020
e831c33
feat(commands/changlog): add --start-rev argument to `cz changelog`
Lee-W Jan 23, 2020
351a674
style(cli): fix flake8 issue
Lee-W Jan 23, 2020
90f93fa
refactor(commands/changelog): remove redundant if statement
Lee-W Jan 23, 2020
ca74222
refactor(tests/utils): move create_file_and_commit to tests/utils
Lee-W Jan 23, 2020
bb647f9
feat(commands/changelog): exit when there is no commit exists
Lee-W Jan 23, 2020
f95ad39
fix(commands/changelog): remove --skip-merge argument
Lee-W Jan 23, 2020
a882736
fix(commitizen/cz): set changelog_map, changelog_pattern to none as d…
Lee-W Jan 23, 2020
e5b50fe
fix(changelog_template): fix list format
Lee-W Jan 23, 2020
4232aba
test(commands/changelog): add test case for changelog command
Lee-W Jan 23, 2020
9b91fad
refactor(templates): move changelog_template from cz to templates
Lee-W Jan 23, 2020
07ff25c
refactor(cli): reorder commands
Lee-W Jan 24, 2020
c417750
docs(README): add changelog command
Lee-W Jan 24, 2020
dbe926d
refactor(templates): remove unneeded __init__ file
Lee-W Jan 24, 2020
4f3a34b
style(tests/commands/changelog): blackify
Lee-W Jan 24, 2020
947d765
refactor(templates): rename as "keep_a_changelog_template.j2"
Lee-W Jan 24, 2020
6f72b6a
feat(commands/changelog): make changelog_file an option in config
Lee-W Jan 24, 2020
3bdd9b2
docs(config): add changlog_file a config option
Lee-W Jan 24, 2020
202121f
fix(conventional_commits): fix checking regular expression
Lee-W Mar 1, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 191 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
=============
Commitizen
=============

Python 3 command-line utility to standardize commit messages and bump version


.. image:: https://github.com/Woile/commitizen/workflows/Python%20package/badge.svg
:alt: Github Actions
:target: https://github.com/Woile/commitizen/actions

.. image:: https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=flat-square
:alt: Conventional Commits
:target: https://conventionalcommits.org

.. image:: https://img.shields.io/pypi/v/commitizen.svg?style=flat-square
:alt: PyPI Package latest release
:target: https://pypi.org/project/commitizen/

.. image:: https://img.shields.io/pypi/pyversions/commitizen.svg?style=flat-square
:alt: Supported versions
:target: https://pypi.org/project/commitizen/

.. image:: https://img.shields.io/codecov/c/github/Woile/commitizen.svg?style=flat-square
:alt: Codecov
:target: https://codecov.io/gh/Woile/commitizen

.. image:: docs/images/demo.gif
:alt: Example running commitizen

--------------

**Documentation**: https://Woile.github.io/commitizen/

--------------

.. contents::
:depth: 2


About
==========

Commitizen is a tool designed for teams.

Its main purpose is to define a standard way of committing rules
and communicating it (using the cli provided by commitizen).

The reasoning behind it is that it is easier to read, and enforces writing
descriptive commits.

Besides that, having a convention on your commits makes it possible to
parse them and use them for something else, like generating automatically
the version or a changelog.


Installation
=============

::

pip install -U commitizen

::

poetry add commitizen --dev


**Global installation**

::

sudo pip3 install -U commitizen

Features
========

- Command-line utility to create commits with your rules. Defaults: `conventional commits`_
- Display information about your commit rules (commands: schema, example, info)
- Bump version automatically using semantic verisoning based on the commits. `Read More <./docs/bump.md>`_
- Generate a changelog using "Keep a changelog" (Planned feature)


Commit rules
============

This client tool prompts the user with information about the commit.

Based on `conventional commits`_

This is an example of how the git messages history would look like:

::

fix: minor typos in code
feat: new command update
docs: improved commitizens tab in readme
feat(cz): jira smart commits
refactor(cli): renamed all to ls command
feat: info command for angular
docs(README): added badges
docs(README): added about, installation, creating, etc
feat(config): new loads from ~/.cz and working project .cz .cz.cfg and setup.cfg

And then, by using ``cz bump`` , you can change the version of your project.

``feat`` to ``MINOR``
``fix`` to ``PATCH``


Commitizens
===========

These are the available committing styles by default:

* cz_conventional_commits: `conventional commits`_
* cz_jira: `jira smart commits <https://confluence.atlassian.com/fisheye/using-smart-commits-298976812.html>`_


The installed ones can be checked with:

::

cz ls



Commiting
=========

Run in your terminal

::

cz commit

or the shortcut

::

cz c


Usage
=====

::

$ cz --help
usage: cz [-h] [--debug] [-n NAME] [--version]
{init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
...

Commitizen is a cli tool to generate conventional commits.
For more information about the topic go to https://conventionalcommits.org/

optional arguments:
-h, --help show this help message and exit
--debug use debug mode
-n NAME, --name NAME use the given commitizen (default:
cz_conventional_commits)
--version get the version of the installed commitizen

commands:
{init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
init init commitizen configuration
commit (c) create new commit
ls show available commitizens
example show commit example
info show information about the cz
schema show commit schema
bump bump semantic version based on the git log
changelog (ch) generate changelog (note that it will overwrite
existing file)
check validates that a commit message matches the commitizen
schema
version get the version of the installed commitizen or the
current project (default: installed commitizen)

Contributing
============

Feel free to create a PR.

1. Clone the repo.
2. Add your modifications
3. Create a virtualenv
4. Run :code:`./scripts/test`


.. _conventional commits: https://conventionalcommits.org/
133 changes: 133 additions & 0 deletions commitizen/changelog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"""
# DESIGN

## Parse CHANGELOG.md

1. Get LATEST VERSION from CONFIG
1. Parse the file version to version
2. Build a dict (tree) of that particular version
3. Transform tree into markdown again

## Parse git log

1. get commits between versions
2. filter commits with the current cz rules
3. parse commit information
4. generate tree

Options:
- Generate full or partial changelog
"""
from typing import Generator, List, Dict, Iterable
import re

MD_VERSION_RE = r"^##\s(?P<version>[a-zA-Z0-9.+]+)\s?\(?(?P<date>[0-9-]+)?\)?"
MD_CATEGORY_RE = r"^###\s(?P<category>[a-zA-Z0-9.+\s]+)"
MD_MESSAGE_RE = r"^-\s(\*{2}(?P<scope>[a-zA-Z0-9]+)\*{2}:\s)?(?P<message>.+)"
md_version_c = re.compile(MD_VERSION_RE)
md_category_c = re.compile(MD_CATEGORY_RE)
md_message_c = re.compile(MD_MESSAGE_RE)


CATEGORIES = [
("fix", "fix"),
("breaking", "BREAKING CHANGES"),
("feat", "feat"),
("refactor", "refactor"),
("perf", "perf"),
("test", "test"),
("build", "build"),
("ci", "ci"),
("chore", "chore"),
]


def find_version_blocks(filepath: str) -> Generator:
"""
version block: contains all the information about a version.

E.g:
```
## 1.2.1 (2019-07-20)

## Bug fixes

- username validation not working

## Features

- new login system

```
"""
with open(filepath, "r") as f:
block: list = []
for line in f:
line = line.strip("\n")
if not line:
continue

if line.startswith("## "):
if len(block) > 0:
yield block
block = [line]
else:
block.append(line)
yield block


def parse_md_version(md_version: str) -> Dict:
m = md_version_c.match(md_version)
if not m:
return {}
return m.groupdict()


def parse_md_category(md_category: str) -> Dict:
m = md_category_c.match(md_category)
if not m:
return {}
return m.groupdict()


def parse_md_message(md_message: str) -> Dict:
m = md_message_c.match(md_message)
if not m:
return {}
return m.groupdict()


def transform_category(category: str) -> str:
_category_lower = category.lower()
for match_value, output in CATEGORIES:
if re.search(match_value, _category_lower):
return output
else:
raise ValueError(f"Could not match a category with {category}")


def generate_block_tree(block: List[str]) -> Dict:
tree: Dict = {"commits": []}
category = None
for line in block:
if line.startswith("## "):
category = None
tree = {**tree, **parse_md_version(line)}
elif line.startswith("### "):
result = parse_md_category(line)
if not result:
continue
category = transform_category(result.get("category", ""))

elif line.startswith("- "):
commit = parse_md_message(line)
commit["category"] = category
tree["commits"].append(commit)
else:
print("it's something else: ", line)
return tree


def generate_full_tree(blocks: Iterable) -> Iterable[Dict]:
for block in blocks:
yield generate_block_tree(block)
Loading