From 5ffc9dfe861db660018dec42b5145c7ed026a3d0 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Tue, 14 Jan 2020 23:20:41 +0800 Subject: [PATCH 01/12] feat(git): add find_git_project_root #117 --- commitizen/git.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/commitizen/git.py b/commitizen/git.py index bbd4d7b84b..7b5b175a45 100644 --- a/commitizen/git.py +++ b/commitizen/git.py @@ -1,4 +1,5 @@ import os +from pathlib import Path from tempfile import NamedTemporaryFile from typing import Optional, List @@ -55,3 +56,8 @@ def get_all_tags() -> Optional[List[str]]: if c.err: return [] return [tag.strip() for tag in c.out.split("\n") if tag.strip()] + + +def find_git_project_root() -> Path: + c = cmd.run("git rev-parse --show-toplevel") + return Path(c.out) From cce9977665c5a2c8048974ed4837bf2ae95f3dcf Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Tue, 14 Jan 2020 23:24:26 +0800 Subject: [PATCH 02/12] feat(config): look up configuration in git project root #117 --- commitizen/config/__init__.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/commitizen/config/__init__.py b/commitizen/config/__init__.py index 461789784f..1f6b87411b 100644 --- a/commitizen/config/__init__.py +++ b/commitizen/config/__init__.py @@ -3,12 +3,15 @@ from pathlib import Path from typing import Optional -from commitizen import defaults +from commitizen import defaults, git, out from .base_config import BaseConfig from .toml_config import TomlConfig from .ini_config import IniConfig +NOT_A_GIT_PROJECT = 10 + + def load_global_conf() -> Optional[IniConfig]: home = str(Path.home()) global_cfg = os.path.join(home, ".cz") @@ -35,8 +38,20 @@ def load_global_conf() -> Optional[IniConfig]: def read_cfg() -> BaseConfig: conf = BaseConfig() + git_project_root = git.find_git_project_root() + if not git_project_root: + out.error( + "fatal: not a git repository (or any of the parent directories): .git" + ) + raise SystemExit(NOT_A_GIT_PROJECT) + allowed_cfg_files = defaults.config_files - for filename in allowed_cfg_files: + cfg_paths = ( + str(path / Path(filename)) + for path in [Path("."), git_project_root] + for filename in allowed_cfg_files + ) + for filename in cfg_paths: config_file_exists = os.path.exists(filename) if not config_file_exists: continue From 1e2c475558ae8758cc0559eafaa62b657749034e Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Tue, 14 Jan 2020 23:31:21 +0800 Subject: [PATCH 03/12] refactor(config): replace string type path with pathlib.Path --- commitizen/config/__init__.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/commitizen/config/__init__.py b/commitizen/config/__init__.py index 1f6b87411b..5cdba7bd26 100644 --- a/commitizen/config/__init__.py +++ b/commitizen/config/__init__.py @@ -1,4 +1,3 @@ -import os import warnings from pathlib import Path from typing import Optional @@ -13,9 +12,9 @@ def load_global_conf() -> Optional[IniConfig]: - home = str(Path.home()) - global_cfg = os.path.join(home, ".cz") - if not os.path.exists(global_cfg): + home = Path.home() + global_cfg = home / Path(".cz") + if not global_cfg.exists(): return None # global conf doesnt make sense with commitizen bump @@ -47,19 +46,18 @@ def read_cfg() -> BaseConfig: allowed_cfg_files = defaults.config_files cfg_paths = ( - str(path / Path(filename)) + path / Path(filename) for path in [Path("."), git_project_root] for filename in allowed_cfg_files ) for filename in cfg_paths: - config_file_exists = os.path.exists(filename) - if not config_file_exists: + if not filename.exists(): continue with open(filename, "r") as f: data: str = f.read() - if "toml" in filename: + if "toml" in filename.suffix: _conf = TomlConfig(data=data, path=filename) else: warnings.warn( From 59c3106e138c47ffd4c8985e77029d24fbe53bcd Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 15 Jan 2020 14:49:42 +0800 Subject: [PATCH 04/12] docs(config): add git project root lookup for configuration files --- docs/config.md | 90 ++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/docs/config.md b/docs/config.md index 7b720d3f1a..88f4850d45 100644 --- a/docs/config.md +++ b/docs/config.md @@ -1,61 +1,65 @@ # Configuration -Commitizen has support for `toml` and `ini` files. +Commitizen has support for `toml` and `ini` files. It first looks up the configuration file in the current working directory and then the root directory of the git project. ## pyproject.toml or .cz.toml -Add an entry to `pyproject.toml or .cz.toml`. Recommended for **python** projects. +Add an entry to `pyproject.toml` or `.cz.toml`. Recommended for **python** projects. - [tool.commitizen] - name = "cz_conventional_commits" - version = "0.1.0" - version_files = [ - "src/__version__.py", - "pyproject.toml:version" - ] - style = [ - ["qmark", "fg:#ff9d00 bold"], - ["question", "bold"], - ["answer", "fg:#ff9d00 bold"], - ["pointer", "fg:#ff9d00 bold"], - ["highlighted", "fg:#ff9d00 bold"], - ["selected", "fg:#cc5454"], - ["separator", "fg:#cc5454"], - ["instruction", ""], - ["text", ""], - ["disabled", "fg:#858585 italic"] - ] +```toml +[tool.commitizen] +name = "cz_conventional_commits" +version = "0.1.0" +version_files = [ + "src/__version__.py", + "pyproject.toml:version" +] +style = [ + ["qmark", "fg:#ff9d00 bold"], + ["question", "bold"], + ["answer", "fg:#ff9d00 bold"], + ["pointer", "fg:#ff9d00 bold"], + ["highlighted", "fg:#ff9d00 bold"], + ["selected", "fg:#cc5454"], + ["separator", "fg:#cc5454"], + ["instruction", ""], + ["text", ""], + ["disabled", "fg:#858585 italic"] +] +``` ## INI files -**INI files will not be supported in next major version. Please use toml instead** +**INI files will not be supported in the next major version. Please use toml instead** -Supported files: `.cz`, `.cz.cfg`, `setup.py`, and `$HOME/.cz` +Supported files: `.cz`, `.cz.cfg`, `setup.cfg`, and `$HOME/.cz` The format is slightly different to the `toml`, so pay attention. Recommended for **other languages** projects (js, go, etc). - [commitizen] - name = cz_conventional_commits - version = 0.1.0 - version_files = [ - "src/__version__.py", - "pyproject.toml:version" - ] - style = [ - ["qmark", "fg:#ff9d00 bold"], - ["question", "bold"], - ["answer", "fg:#ff9d00 bold"], - ["pointer", "fg:#ff9d00 bold"], - ["highlighted", "fg:#ff9d00 bold"], - ["selected", "fg:#cc5454"], - ["separator", "fg:#cc5454"], - ["instruction", ""], - ["text", ""], - ["disabled", "fg:#858585 italic"] - ] +```ini +[commitizen] +name = cz_conventional_commits +version = 0.1.0 +version_files = [ + "src/__version__.py", + "pyproject.toml:version" + ] +style = [ + ["qmark", "fg:#ff9d00 bold"], + ["question", "bold"], + ["answer", "fg:#ff9d00 bold"], + ["pointer", "fg:#ff9d00 bold"], + ["highlighted", "fg:#ff9d00 bold"], + ["selected", "fg:#cc5454"], + ["separator", "fg:#cc5454"], + ["instruction", ""], + ["text", ""], + ["disabled", "fg:#858585 italic"] + ] +``` -The extra tab before the square brakets (`]`) at the end is required. +The extra tab before the square brackets (`]`) at the end is required. ## Settings From 421c89fc98a4f3a4cef6c1e2ecb808f1d74690d2 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 15 Jan 2020 15:09:44 +0800 Subject: [PATCH 05/12] docs(all): fix typo and grammar error #80 --- README.rst | 25 +++++++++++++++---------- commitizen/cli.py | 2 +- docs/bump.md | 12 ++++++------ docs/customization.md | 9 ++++----- docs/index.md | 8 ++++---- docs/init.md | 10 +++++----- docs/tutorials/github_actions.md | 10 +++++----- docs/tutorials/gitlab_ci.md | 24 ++++++++++++------------ docs/tutorials/writing_commits.md | 17 +++++++---------- 9 files changed, 59 insertions(+), 58 deletions(-) diff --git a/README.rst b/README.rst index c9cae65df3..34c9284da3 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ Commitizen ============= - Python 3 command line utility to standardize commit messages and bump version + Python 3 command-line utility to standardize commit messages and bump version .. image:: https://github.com/Woile/commitizen/workflows/Python%20package/badge.svg @@ -43,13 +43,13 @@ About Commitizen is a tool designed for teams. -Its main purpose is to define a standard way of commiting rules +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 is easier to read, and enforces writing +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 +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. @@ -75,7 +75,7 @@ Installation Features ======== -- Command line utility to create commits with your rules. Defaults: `conventional commits`_ +- 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) @@ -102,7 +102,7 @@ This is an example of how the git messages history would look like: docs(README): added about, installation, creating, etc feat(config): new loads from ~/.cz and working project .cz .cz.cfg and setup.cfg -And then using ``cz bump`` you can change the version of your project +And then, by using ``cz bump`` , you can change the version of your project. ``feat`` to ``MINOR`` ``fix`` to ``PATCH`` @@ -111,7 +111,7 @@ And then using ``cz bump`` you can change the version of your project Commitizens =========== -These are the available commiting styles by default: +These are the available committing styles by default: * cz_conventional_commits: `conventional commits`_ * cz_jira: `jira smart commits `_ @@ -156,18 +156,23 @@ Usage optional arguments: -h, --help show this help message and exit --debug use debug mode - -n NAME, --name NAME use the given commitizen + -n NAME, --name NAME use the given commitizen (default: + cz_conventional_commits) --version get the version of the installed commitizen commands: - {ls,commit,c,example,info,schema,bump,check} + {ls,commit,c,example,info,schema,bump,version,check,init} ls show available commitizens commit (c) create new commit example show commit example info show information about the cz schema show commit schema bump bump semantic version based on the git log - check enforce the project to always use conventional commits + version get the version of the installed commitizen or the + current project (default: installed commitizen) + check validates that a commit message matches the commitizen + schema + init init commitizen configuration Contributing ============ diff --git a/commitizen/cli.py b/commitizen/cli.py index 552ee36184..658b4bba9f 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -89,7 +89,7 @@ { "name": "--tag-format", "help": ( - "format used to tag the commmit and read it, " + "the format used to tag the commit and read it, " "use it in existing projects, " "wrap around simple quotes" ), diff --git a/docs/bump.md b/docs/bump.md index 5a222c18ce..bac589a3b2 100644 --- a/docs/bump.md +++ b/docs/bump.md @@ -4,7 +4,7 @@ The version is bumped **automatically** based on the commits. -The commits should follow the rules of the commiter in order to be parsed properly. +The commits should follow the rules of the committer to be parsed correctly. It is possible to specify a **prerelease** (alpha, beta, release candidate) version. @@ -65,7 +65,7 @@ optional arguments: --files-only bump version in the files from the config --yes accept automatically questions done --tag-format TAG_FORMAT - format used to tag the commmit and read it, use it in + the format used to tag the commit and read it, use it in existing projects, wrap around simple quotes --bump-message BUMP_MESSAGE template used to create the release commmit, useful @@ -80,9 +80,9 @@ optional arguments: ### `tag_format` -Used to read the format from the git tags, and also to generate the tags. +It is used to read the format from the git tags, and also to generate the tags. -Supports 2 types of formats, a simple and a more complex. +Commitizen supports 2 types of formats, a simple and a more complex. ```bash cz bump --tag_format="v$version" @@ -122,7 +122,7 @@ Suppported variables: ### `version_files` * -Used to identify the files which should be updated with the new version. +It is used to identify the files which should be updated with the new version. It is also possible to provide a pattern for each file, separated by colons (`:`). Commitizen will update it's configuration file automatically (`pyproject.toml`, `.cz`) when bumping, @@ -160,7 +160,7 @@ in a line containing the `version` substring. ### `bump_message` -Template used to specify the commit message generated when bumping +Template used to specify the commit message generated when bumping. defaults to: `bump: version $current_version → $new_version` diff --git a/docs/customization.md b/docs/customization.md index 5baa967bae..09c996d88c 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -1,6 +1,6 @@ Customizing commitizen is not hard at all. -## Customize through customize class +## Customize through customizing a class The basic steps are: @@ -21,8 +21,7 @@ See [Lee-W/commitizen_cz_template](https://github.com/Lee-W/commitizen_cz_templa ### Custom commit rules -Create a file starting with `cz_` for example `cz_jira.py`. This prefix -is used to detect the plugin. Same method [flask uses] +Create a file starting with `cz_`, for example `cz_jira.py`. This prefix is used to detect the plugin. Same method [flask uses] Inherit from `BaseCommitizen`, and you must define `questions` and `message`. The others are optional. @@ -114,7 +113,7 @@ You need to define 2 parameters inside `BaseCommitizen`. | `bump_pattern` | `str` | `None` | Regex to extract information from commit (subject and body) | | `bump_map` | `dict` | `None` | Dictionary mapping the extracted information to a `SemVer` increment type (`MAJOR`, `MINOR`, `PATCH`) | -Let's see an example +Let's see an example. ```python from commitizen.cz.base import BaseCommitizen @@ -125,7 +124,7 @@ class StrangeCommitizen(BaseCommitizen): bump_map = {"break": "MAJOR", "new": "MINOR", "fix": "PATCH", "hotfix": "PATCH"} ``` -That's it, your commitizen now supports custom rules, and you can run +That's it, your commitizen now supports custom rules, and you can run. ```bash cz -n cz_strange bump diff --git a/docs/index.md b/docs/index.md index 8b20991081..561d9487e1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,19 +13,19 @@ versions](https://img.shields.io/pypi/pyversions/commitizen.svg?style=flat-squar Commitizen is a tool designed for teams. -Its main purpose is to define a standard way of commiting rules +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 is easier to read, and enforces writing +The reasoning behind it is that it is easier to read, and enforces writing descriptive commits. -Besides that, having a convetion on your commits, makes it possible to +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. ### Commitizen features -- Command line utility to create commits with your rules. Defaults: [Conventional commits][conventional_commits] +- Command-line utility to create commits with your rules. Defaults: [Conventional commits][conventional_commits] - Display information about your commit rules (commands: schema, example, info) - Bump version automatically using [semantic verisoning][semver] based on the commits. [Read More](./bump.md) - Generate a changelog using [Keep a changelog][keepchangelog] (Planned feature) diff --git a/docs/init.md b/docs/init.md index fabc402b21..38a3afd431 100644 --- a/docs/init.md +++ b/docs/init.md @@ -1,4 +1,4 @@ -For new projects is possible to run `cz init`. +For new projects, it is possible to run `cz init`. This command will prompt the user for information about the project and will configure the selected file type (`pyproject.toml`, `.cz.toml`, etc). @@ -7,9 +7,9 @@ This will help you quickly set up your project with `commitizen`. Currently `init` is detecting -1. Commit convetion rules (`name`). -1. Version detection based on the existing tags (`version`). -1. Tag format, if your tag convention uses for example `v*` in front of the version. (`tag_format`) +1. Commit convention rules (`name`). +2. Version detection based on the existing tags (`version`). +3. Tag format, if your tag convention uses, for example `v*` in front of the version. (`tag_format`) -We hope to eventually detect the files where the version is also repeated, +We hope to detect the files where the version is also repeated eventually, like `package.json` or `__version__`. diff --git a/docs/tutorials/github_actions.md b/docs/tutorials/github_actions.md index 1a4eba292a..b151c9e77a 100644 --- a/docs/tutorials/github_actions.md +++ b/docs/tutorials/github_actions.md @@ -1,13 +1,13 @@ -## Create new release with Github Actions +## Create a new release with Github Actions ### Automatic bumping of version -In order to execute `cz bump` in your CI, and push the new commit and +To execute `cz bump` in your CI, and push the new commit and the new tag, back to your master branch, we have to: 1. Create a personal access token. [Follow the instructions here](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line#creating-a-token). And copy the generated key 2. Create a secret called `PERSONAL_ACCESS_TOKEN`, with the copied key, by going to your project repository and then `Settings > Secrets > Add new secret`. -3. In your repostiroy create a new file `.github/workflows/bumpversion.yml` +3. In your repository create a new file `.github/workflows/bumpversion.yml` with the following content. ```yaml @@ -56,7 +56,7 @@ Push to master and that's it. Once the new tag is created, triggering an automatic publish command would be desired. -In order to do so, first 2 secrets need to be added with the information +In order to do so, the first two secrets need to be added with the information of our pypi account. Go to `Settings > Secrets > Add new secret` and add the secrets: `PYPI_USERNAME` and `PYPI_PASSWORD`. @@ -94,6 +94,6 @@ jobs: ``` Notice that we are calling a bash script in `./scripts/publish`, you should -configure it with your tools (twine, poetry, etc). Check [commitizen example](https://github.com/Woile/commitizen/blob/master/scripts/publish) +configure it with your tools (twine, poetry, etc.). Check [commitizen example](https://github.com/Woile/commitizen/blob/master/scripts/publish) Push the changes and that's it. diff --git a/docs/tutorials/gitlab_ci.md b/docs/tutorials/gitlab_ci.md index 79fabf61a5..e2da81d63d 100644 --- a/docs/tutorials/gitlab_ci.md +++ b/docs/tutorials/gitlab_ci.md @@ -1,8 +1,8 @@ -### Create a new release usign GitLab CI +### Create a new release using GitLab CI -For this example, we have a `python/django` application and `Docker` as containerization tool. +For this example, we have a `python/django` application and `Docker` as a containerization tool. -*Goal*: Bump a new version every time that a change occurs on `master` branch. The bump should be executed automatically by the `CI` process. +*Goal*: Bump a new version every time that a change occurs on the `master` branch. The bump should be executed automatically by the `CI` process. #### Development Workflow: @@ -10,11 +10,11 @@ For this example, we have a `python/django` application and `Docker` as containe 2. A developer creates a merge request (MR) against `master` branch 3. When the `MR` is merged into master, the 2 stages of the CI are executed 4. For simplification, we store the software version in a file called `VERSION`. You can use any file that you want as `commitizen` supports it. -5. The commit message executed automatically by the `CI` must include `[skip-ci]` in the message, otherwise the process will generate a loop. You can define the message structure in [commitizen](https://woile.github.io/commitizen/bump/) as well. +5. The commit message executed automatically by the `CI` must include `[skip-ci]` in the message; otherwise, the process will generate a loop. You can define the message structure in [commitizen](https://woile.github.io/commitizen/bump/) as well. #### Gitlab Configuration: -In order to be able to change files and push new changes with `Gitlab CI` runners, we need to have a `ssh` key and configure a git user. +To be able to change files and push new changes with `Gitlab CI` runners, we need to have a `ssh` key and configure a git user. First, let's create a `ssh key`. The only requirement is to create it without a passphrase: @@ -24,15 +24,15 @@ ssh-keygen -f deploy_key -N "" The previous command will create a private and public key under the files `deploy_key` and `deploy_key.pub`. We will use them later. -For the git user, we need an email and username. You can choose whatever you want, in this example, we choose `ci-runner@myproject.com` and `admin` respectively. +For the git user, we need an email and username. You can choose whatever you want; in this example, we choose `ci-runner@myproject.com` and `admin`, respectively. Now, we need to create three environment variables that will be visible for the runners. They should be created in the `variables` section under `settings/ci_cd`: ![gitlab variables](../images/gitlab_ci/gitlab_variables.png) -Create `SSH_PRIVATE_KEY`, `CI_EMAIL`, `CI_USERNAME` variables and fill them with the `private_key`, `email` and `username` that we have created previously. +Create `SSH_PRIVATE_KEY`, `CI_EMAIL`, `CI_USERNAME` variables, and fill them with the `private_key`, `email` and `username` that we have created previously. -The latest step is to create a `deploy key.` To do this, we should create it under the section `settings/repository` and fill it with the `public key` generated before. Check `Write access allowed`, otherwise, the runner won't be able to write the changes to the repository. +The latest step is to create a `deploy key.` To do this, we should create it under the section `settings/repository` and fill it with the `public key` generated before. Check `Write access allowed`; otherwise, the runner won't be able to write the changes to the repository. ![gitlab deploy key](../images/gitlab_ci/gitlab_deploy_key.png) @@ -46,7 +46,7 @@ tip: If the CI raise some errors, try to unprotect the private key. 2. Define `stages` and `jobs`. For this example, we define two `stages` with one `job` each one. * Test the application. - * Auto bump the version. Means changing the file/s that reflects the version, creating a new commit and git tag. + * Auto bump the version. This means changing the file/s that reflects the version, creating a new commit and git tag. #### Stages and Jobs @@ -105,9 +105,9 @@ auto-bump: - variables ``` -So, every time that a developer push to any branch the `test` job is executed. If the branch is `master` and the test jobs success, the `auto-bump` takes place. -To be able to push using the Gitlab runner we have to set the ssh key, configure git and finally execute the auto bump. +So, every time that a developer push to any branch, the `test` job is executed. If the branch is `master` and the test jobs success, the `auto-bump` takes place. +To be able to push using the Gitlab runner, we have to set the ssh key, configure git, and finally execute the auto bump. -After merging the new changed into master we have the final result: +After merging the new changed into master, we have the final result: ![gitlab final ci result](../images/gitlab_ci/gitlab_final_ci_result.png) diff --git a/docs/tutorials/writing_commits.md b/docs/tutorials/writing_commits.md index e72a005527..37b83b36b7 100644 --- a/docs/tutorials/writing_commits.md +++ b/docs/tutorials/writing_commits.md @@ -1,5 +1,5 @@ -In order for this project to work well in your pipeline, a commit convention -must be follow. +For this project to work well in your pipeline, a commit convention +must be followed. By default commitizen uses the known [conventional commits][conventional_commits], but you can create your own following the docs information over [customization][customization]. @@ -7,15 +7,14 @@ your own following the docs information over [customization][customization]. ## Conventional commits If you are using [conventional commits][conventional_commits], the most important -thing to know, is that you must begin your commits with at least one of this -tags: `fix`, `feat`. And if you introduce a breaking change, then, you must +thing to know is that you must begin your commits with at least one of these tags: `fix`, `feat`. And if you introduce a breaking change, then, you must add to your commit body the following `BREAKING CHANGE`. Using these 3 keywords will allow the proper identification of the semantic version. -Of course there are other keywords, but I'll leave it to the reader to explore them. +Of course, there are other keywords, but I'll leave it to the reader to explore them. ## Writing commits -Not to the important part, when writing commits it's important to think about: +Not to the important part, when writing commits, it's important to think about: - Your future self - Your colleagues @@ -28,10 +27,8 @@ understand what happened. - **Keep the message short**: Makes the list of commits more readable (~50 chars). - **Talk imperative**: Follow this rule: `If applied, this commit will ` - **Think about the CHANGELOG**: Your commits will probably end up in the changelog - so try writing for it, but also keep in mind that you can skip sending commits to - the CHANGELOG by using diffrent keywords (like `build`). -- **Use a commit per new feature**: if you introduce multiple things related to - the same commit, squash them. This is useful for auto-generating CHANGELOG. + so try writing for it, but also keep in mind that you can skip sending commits to the CHANGELOG by using different keywords (like `build`). +- **Use a commit per new feature**: if you introduce multiple things related to the same commit, squash them. This is useful for auto-generating CHANGELOG. | Do's | Don'ts | | ---- | ------ | From 24909fde81c6318b1c3ea27a0bd32e411e67f070 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 15 Jan 2020 15:31:57 +0800 Subject: [PATCH 06/12] fix(git): remove breakline in the return value of find_git_project_root --- commitizen/git.py | 2 +- tests/test_conf.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/commitizen/git.py b/commitizen/git.py index 7b5b175a45..1d34d2e0e8 100644 --- a/commitizen/git.py +++ b/commitizen/git.py @@ -60,4 +60,4 @@ def get_all_tags() -> Optional[List[str]]: def find_git_project_root() -> Path: c = cmd.run("git rev-parse --show-toplevel") - return Path(c.out) + return Path(c.out.strip()) diff --git a/tests/test_conf.py b/tests/test_conf.py index 09b94b396b..58a2a5c6c9 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -1,8 +1,10 @@ import os +from pathlib import Path import pytest -from commitizen import config, defaults +from commitizen import config, defaults, git + PYPROJECT = """ [tool.commitizen] @@ -126,3 +128,7 @@ def test_set_key(configure_supported_files, config_files_manager): _conf.set_key("version", "2.0.0") cfg = config.read_cfg() assert cfg.settings == _new_settings + + +def test_find_git_project_root(): + assert git.find_git_project_root() == Path(os.getcwd()) From 038e0c7c45d7b227222f5a9eec161d27ab0cf54c Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 15 Jan 2020 15:39:47 +0800 Subject: [PATCH 07/12] refactor(error_codes): move all the error_codes to a module --- commitizen/commands/bump.py | 13 +++++++------ commitizen/commands/check.py | 5 +---- commitizen/commands/commit.py | 14 +++++++------- commitizen/config/__init__.py | 4 +--- commitizen/error_codes.py | 23 +++++++++++++++++++++++ commitizen/factory.py | 3 +-- 6 files changed, 40 insertions(+), 22 deletions(-) create mode 100644 commitizen/error_codes.py diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index cf325447df..53f03c3eec 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -5,12 +5,13 @@ from commitizen import bump, factory, git, out from commitizen.config import BaseConfig - -NO_COMMITS_FOUND = 3 -NO_VERSION_SPECIFIED = 4 -NO_PATTERN_MAP = 7 -COMMIT_FAILED = 8 -TAG_FAILED = 9 +from commitizen.error_codes import ( + NO_COMMITS_FOUND, + NO_VERSION_SPECIFIED, + NO_PATTERN_MAP, + COMMIT_FAILED, + TAG_FAILED, +) class Bump: diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index 04ae58538e..2a068e83e3 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -3,10 +3,7 @@ from commitizen import factory, out from commitizen.config import BaseConfig - - -NO_COMMIT_MSG = 3 -INVALID_COMMIT_MSG = 5 +from commitizen.error_codes import NO_COMMIT_MSG, INVALID_COMMIT_MSG class Check: diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 627568132b..0dbbe8fe9d 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -7,13 +7,13 @@ from commitizen import factory, git, out from commitizen.cz.exceptions import CzException from commitizen.config import BaseConfig - - -NO_ANSWERS = 5 -COMMIT_ERROR = 6 -NO_COMMIT_BACKUP = 7 -NOTHING_TO_COMMIT = 8 -CUSTOM_ERROR = 9 +from commitizen.error_codes import ( + NO_ANSWERS, + COMMIT_ERROR, + NO_COMMIT_BACKUP, + NOTHING_TO_COMMIT, + CUSTOM_ERROR, +) class Commit: diff --git a/commitizen/config/__init__.py b/commitizen/config/__init__.py index 5cdba7bd26..88949f327d 100644 --- a/commitizen/config/__init__.py +++ b/commitizen/config/__init__.py @@ -3,14 +3,12 @@ from typing import Optional from commitizen import defaults, git, out +from commitizen.error_codes import NOT_A_GIT_PROJECT from .base_config import BaseConfig from .toml_config import TomlConfig from .ini_config import IniConfig -NOT_A_GIT_PROJECT = 10 - - def load_global_conf() -> Optional[IniConfig]: home = Path.home() global_cfg = home / Path(".cz") diff --git a/commitizen/error_codes.py b/commitizen/error_codes.py new file mode 100644 index 0000000000..c6eeac7a27 --- /dev/null +++ b/commitizen/error_codes.py @@ -0,0 +1,23 @@ +# Commitizen factory +NO_COMMITIZEN_FOUND = 1 + +# Config +NOT_A_GIT_PROJECT = 2 + +# Bump +NO_COMMITS_FOUND = 3 +NO_VERSION_SPECIFIED = 4 +NO_PATTERN_MAP = 5 +COMMIT_FAILED = 6 +TAG_FAILED = 7 + +# Commit +NO_ANSWERS = 8 +COMMIT_ERROR = 9 +NO_COMMIT_BACKUP = 10 +NOTHING_TO_COMMIT = 11 +CUSTOM_ERROR = 12 + +# Check +NO_COMMIT_MSG = 13 +INVALID_COMMIT_MSG = 14 diff --git a/commitizen/factory.py b/commitizen/factory.py index b42ab7c9a9..62b7ba9cfa 100644 --- a/commitizen/factory.py +++ b/commitizen/factory.py @@ -1,8 +1,7 @@ from commitizen import BaseCommitizen, out from commitizen.cz import registry from commitizen.config import BaseConfig - -NO_COMMITIZEN_FOUND = 2 +from commitizen.error_codes import NO_COMMITIZEN_FOUND def commiter_factory(config: BaseConfig) -> BaseCommitizen: From ff0cac454990a8aa5aafce8a278d13b929fd1351 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 15 Jan 2020 15:45:57 +0800 Subject: [PATCH 08/12] refactor(config/base_config): make set_key not implemented it's not used in base_config but should be overwritten in a child class --- commitizen/config/base_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commitizen/config/base_config.py b/commitizen/config/base_config.py index f2dd46ae54..7f5951d790 100644 --- a/commitizen/config/base_config.py +++ b/commitizen/config/base_config.py @@ -23,7 +23,7 @@ def set_key(self, key, value): For now only strings are supported. We use to update the version number. """ - return self + raise NotImplementedError() def update(self, data: dict): self._settings.update(data) From 8d90e6644b9833417d54b012e5c5eedefe2a54b2 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 15 Jan 2020 15:52:29 +0800 Subject: [PATCH 09/12] test(config/toml_config): add test case to init_empty_config_file --- tests/test_conf.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_conf.py b/tests/test_conf.py index 58a2a5c6c9..86957e5992 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -132,3 +132,13 @@ def test_set_key(configure_supported_files, config_files_manager): def test_find_git_project_root(): assert git.find_git_project_root() == Path(os.getcwd()) + + +class TestTomlConfig: + def test_init_empty_config_file(self, tmpdir): + path = tmpdir.mkdir("commitizen").join('.cz.toml') + toml_config = config.TomlConfig(data="", path=path) + toml_config.init_empty_config_file() + + with open(path, "r") as toml_file: + assert toml_file.read() == "[tool.commitizen]" From 74654df828a197d2b2546333983e07ad3bc903d7 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 15 Jan 2020 15:59:16 +0800 Subject: [PATCH 10/12] test(git): add test case for find_git_project_root --- tests/test_conf.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/test_conf.py b/tests/test_conf.py index 86957e5992..bc80245266 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -130,13 +130,16 @@ def test_set_key(configure_supported_files, config_files_manager): assert cfg.settings == _new_settings -def test_find_git_project_root(): +def test_find_git_project_root(tmpdir): assert git.find_git_project_root() == Path(os.getcwd()) + with tmpdir.as_cwd() as tmp_cwd: + assert git.find_git_project_root() == None + class TestTomlConfig: def test_init_empty_config_file(self, tmpdir): - path = tmpdir.mkdir("commitizen").join('.cz.toml') + path = tmpdir.mkdir("commitizen").join(".cz.toml") toml_config = config.TomlConfig(data="", path=path) toml_config.init_empty_config_file() From 225a8c2d45a7ff02102b85a3892abe0fc82f66b6 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 15 Jan 2020 16:00:04 +0800 Subject: [PATCH 11/12] refactor(git): make find_git_project_root return None if it's not a git project pathlib returns Path('.') if empty is passed --- commitizen/git.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/commitizen/git.py b/commitizen/git.py index 1d34d2e0e8..9f831e5b54 100644 --- a/commitizen/git.py +++ b/commitizen/git.py @@ -58,6 +58,8 @@ def get_all_tags() -> Optional[List[str]]: return [tag.strip() for tag in c.out.split("\n") if tag.strip()] -def find_git_project_root() -> Path: +def find_git_project_root() -> Optional[Path]: c = cmd.run("git rev-parse --show-toplevel") - return Path(c.out.strip()) + if not c.err: + return Path(c.out.strip()) + return None From 84a2118cdf647da49cd06f05812d3dadf516f5ff Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 15 Jan 2020 16:04:41 +0800 Subject: [PATCH 12/12] style(config): remove unused variables --- commitizen/commands/check.py | 2 +- tests/test_conf.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index 2a068e83e3..de5f5e39f9 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -3,7 +3,7 @@ from commitizen import factory, out from commitizen.config import BaseConfig -from commitizen.error_codes import NO_COMMIT_MSG, INVALID_COMMIT_MSG +from commitizen.error_codes import INVALID_COMMIT_MSG class Check: diff --git a/tests/test_conf.py b/tests/test_conf.py index bc80245266..c7527cef79 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -133,8 +133,14 @@ def test_set_key(configure_supported_files, config_files_manager): def test_find_git_project_root(tmpdir): assert git.find_git_project_root() == Path(os.getcwd()) - with tmpdir.as_cwd() as tmp_cwd: - assert git.find_git_project_root() == None + with tmpdir.as_cwd() as _: + assert git.find_git_project_root() is None + + +def test_read_cfg_when_not_in_a_git_project(tmpdir): + with tmpdir.as_cwd() as _: + with pytest.raises(SystemExit): + config.read_cfg() class TestTomlConfig: