commitizen / cz-cli

The commitizen command line utility. #BlackLivesMatter
http://commitizen.github.io/cz-cli/
MIT License
16.7k stars 547 forks source link

Add `pre-commit` hook that will run Commitizen on `git commit` #801

Open ShaneKosieradzki opened 3 years ago

ShaneKosieradzki commented 3 years ago

Background

pre-commit is a package manager for git hooks. The project allows hooks to be downloaded locally and run in an isolated environment. This allows for easy adoption of hooks written in a variety of languages and allows for quick adoption by contributors who are unfamiliar with any particular hook.

Possible Solution

This project can make itself pre-commit compatible by adding a .pre-commit-hooks.yaml file. You can use this file to make your existing prepare-commit-msg hook and the Commitizen project as a whole more accessible.

paulmboyce commented 3 years ago

Hi @ShaneKosieradzki , if it helps, you can use husky to run pre commit hooks.

Install husky:

npm install--save-dev husky

Then run this to add a pre commit message hook:

npx husky add .husky/prepare-commit-msg "exec < /dev/tty && git cz --hook || true"

Note, you will probably want to add the resulting hook file to git:

.husky/prepare-commit-msg

I know that isn't enhancing commitizen itself, but it does get you the pre commit hooks

Hope that helps!

offbyone commented 2 years ago

That doesn't help if a team already has hooks written for pre-commit -- it would be nice to be able to share the same rules and commit message checking here.

phitoduck commented 2 years ago

+1 for this! Our team just set up the pre-commit framework. It's nice because there is zero learning curve for contributors. Contributors run a single make install command which runs pip install pre-commit and pre-commit install behind the scenes... and they're off!

When they run git commit ..., they are suddenly greeted with all of our automated quality checks. It would be super cool if we could do the same with commitizen: a subset of our developers could be versed with commitizen for things like setting up the commit message schema, bumping the version, etc. But the rest of the developers wouldn't know anything about it.

All they would know is that, for some reason, when they run git commit ... in our repo, they are suddenly greeted by a wizard asking them structured questions about the commit they are trying to make.

I could totally be thinking about commitizen wrong, but in my mind, it would be so cool if we could achieve this behavior somehow.

donhector commented 2 years ago

Try with this hook

- repo: https://github.com/commitizen-tools/commitizen
  rev: master
  hooks:
    - id: commitizen
      stages: [commit-msg]

Or if you don't want to add external links to your repo, then create your own local hook in .pre-commit-config.yaml that calls your cz binary.

I generally wrap the calls in a make target, so the hook's entry is make and in the args, I put the target name. I use system as the language since we are executing a system binary (ie: make). Notice that I explicitly set pass_filenames to false since we are not interested en receiving the list of changed files in our commit, but our commit message:

  - repo: local
    hooks:
      - id: commitizen
        name: My commitizen check
        entry: make
        args: ['commitizen']
        pass_filenames: false
        language: system
        stages: [commit-msg]

Then in your Makefile

.PHONY commitizen
commitizen:
    @cz check --commit-msg-file .git/COMMIT_EDITMSG

Or if you are not very found of Make, then just call commitizen directly:

  - repo: local
    hooks:
      - id: commitizen
        name: My commitizen check
        entry: cz
        args: ['check', '--commit-msg-file', '.git/COMMIT_EDITMSG']
        pass_filenames: false
        language: system
        stages: [commit-msg]

Don't forget to tell pre-commit to install any hooks associated with the commit-msg stage with:

pre-commit install --hook-type commit-msg

For more info on creating custom pre-commit hooks, it's all pretty well documented in their official website pre-commit.com

lays147 commented 2 years ago

@donhector I'm trying to use your hook, and it's failing because cz is receiving the list of my staged files instead of the check argument.

commitizen check.........................................................Failed
- hook id: commitizen
- exit code: 13

usage: cz
       [-h]
       [--debug]
       [-n NAME]
       {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
       ...
cz: error: unrecognized arguments: settings.toml Dockerfile .dockerignore Template/config.py .editorconfig .gitignore pyproject.toml tests/conftest.py poetry.lock .pre-commit-config.yaml .github/workflows/python.yml tox.ini README.md Template/logging/__init__.py
Command is required

Any tips on how to fix it? Do I need to add any arguments?

Thanks

donhector commented 2 years ago

@donhector I'm trying to use your hook, and it's failing because cz is receiving the list of my staged files instead of the check argument.

commitizen check.........................................................Failed
- hook id: commitizen
- exit code: 13

usage: cz
       [-h]
       [--debug]
       [-n NAME]
       {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
       ...
cz: error: unrecognized arguments: settings.toml Dockerfile .dockerignore Template/config.py .editorconfig .gitignore pyproject.toml tests/conftest.py poetry.lock .pre-commit-config.yaml .github/workflows/python.yml tox.ini README.md Template/logging/__init__.py
Command is required

Any tips on how to fix it? Do I need to add any arguments?

Thanks

@lays147 Could you share your .pre-commit-config.yaml file? I've updated my previous comment with actual examples.

lays147 commented 2 years ago

@donhector

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.0.1
    hooks:
      - id: check-toml
      - id: check-yaml
      - id: check-docstring-first
      - id: detect-aws-credentials

  - repo: https://github.com/pre-commit/pygrep-hooks 
    rev: v1.9.0 
    hooks:
      - id: python-check-mock-methods
      - id: python-use-type-annotations

  - repo: https://github.com/hadolint/hadolint
    rev: master
    hooks:
      - id: hadolint-docker

  - repo: local
    hooks:
    - id: lint and format
      name: Lint and format files
      entry: poetry run tox -e lint
      language: system
    - id: compliance and quality
      name: Run for compliance and quality checks
      entry: poetry run tox -e compliance
      language: system

  - repo: https://github.com/commitizen-tools/commitizen
    rev: v2.20.0
    hooks:
      - id: commitizen
    stages: [commit-msg]
donhector commented 2 years ago

@lays147 Your stages: [commit-msg] indentation looks incorrect. Should be like this:

  - repo: https://github.com/commitizen-tools/commitizen
    rev: v2.20.0
    hooks:
      - id: commitizen
        stages: [commit-msg]
lays147 commented 2 years ago

@donhector ouch. Thanks for pointing that out. :see_no_evil: Now it works!

cas-- commented 2 years ago

@donhector That pre-commit hook described is for commitizen-tools project which is a different commitizen tool from this one so that is rather misleading for this issue.

commitizen/cz-cli a JS commit message creator commitizen-tools/commitizen an unrelated Python commit message creator and checker

Summary of my research:

sethidden commented 2 years ago

If you came across this issue and are trying to fix Command is required and you don't use .pre-commit-config.yml then make sure your command in the hook is exec < /dev/tty && npx cz --hook || true as shown here

The error was happening to me because I was using git cz instead of npx cz in the hook command

adam-grant-hendry commented 2 years ago

Could someone here help me with this?:

https://stackoverflow.com/questions/72264186/post-merge-hook-to-commitizen-bump-and-changelog

cas-- commented 2 years ago

@adam-grant-hendry Seems a bit cheeky to post a barely on-topic SO question here but also this is the wrong project to ask for help in, this is a JavaScript project and not commitizen-tools Python based commitizen.

adam-grant-hendry commented 2 years ago

@cas-- If there was a Discussions tab, I would have put my question there, but fair enough. My mistake for assuming this was the python page.