diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..f59457a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: Canonical Ltd. +# +# SPDX-License-Identifier: Apache-2.0 + +default_install_hook_types: [commit-msg, pre-push] + +repos: + - repo: local + hooks: + - id: gitlance-commit-msg + name: Validate commit message with gitlance + entry: bash githooks/commit-msg + language: system + stages: [commit-msg] + - id: gitlance-pre-push + name: Validate commits with gitlance + entry: python githooks/pre_commit_pre_push.py + language: python + stages: [pre-push] + always_run: true + pass_filenames: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9deb64c..a48cfa7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,6 +17,21 @@ Contributions are welcome! Please follow these guidelines. 5. Add `Signed-off-by` trailer to commits 6. Open a pull request +### Local commit validation + +Gitlance can validate commit messages and pushed commits locally. Install +[pre-commit](https://pre-commit.com/#install), install the local Gitlance +binary, and register both hooks: + +```console +cargo install --path . --locked +task install-githooks +``` + +The installation is idempotent. If a `commit-msg` or `pre-push` hook already +exists, pre-commit preserves it as a legacy hook and runs it alongside +Gitlance. Running `pre-commit uninstall` restores the previous hooks. + ## Commit Requirements - Use conventional format: `feat:`, `fix:`, `docs:`, etc. diff --git a/Taskfile.yml b/Taskfile.yml index 0da335a..addd074 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -21,15 +21,14 @@ tasks: install-githooks: desc: "Install git hooks for commit validation" - vars: - HOOKS_DIR: - sh: git rev-parse --git-path hooks - cmds: - - cp githooks/pre-push "{{.HOOKS_DIR}}/" - - chmod +x "{{.HOOKS_DIR}}/pre-push" - - cp githooks/commit-msg "{{.HOOKS_DIR}}/" - - chmod +x "{{.HOOKS_DIR}}/commit-msg" - - echo "✓ Git hooks installed to {{.HOOKS_DIR}}" + preconditions: + - sh: pre-commit --version + msg: "pre-commit is required: https://pre-commit.com/#install" + - sh: gitlance --help + msg: "gitlance must be installed and available in PATH: cargo install --path . --locked" + cmds: + - pre-commit install + - echo "✓ Git hooks installed with pre-commit" setup: desc: "Setup Rust toolchain and development environment" diff --git a/githooks/pre_commit_pre_push.py b/githooks/pre_commit_pre_push.py new file mode 100644 index 0000000..7bd04fe --- /dev/null +++ b/githooks/pre_commit_pre_push.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: Canonical Ltd. +# +# SPDX-License-Identifier: Apache-2.0 + +import os +import subprocess +import sys + + +def main() -> int: + local_branch = os.environ.get("PRE_COMMIT_LOCAL_BRANCH", "HEAD") + if local_branch != "HEAD" and not local_branch.startswith("refs/heads/"): + return 0 + + head = os.environ.get("PRE_COMMIT_TO_REF") or local_branch + return subprocess.call( + ["gitlance", "--head", head, "--not-on-remotes"], + ) + + +if __name__ == "__main__": + sys.exit(main())