From ed1d37d5f137c12130c33903e3a3e13a004d3a3f Mon Sep 17 00:00:00 2001 From: Alexander Lais Date: Mon, 17 Jul 2023 08:09:05 +0200 Subject: [PATCH] ci(commitlint): add local hook to enforce commit convention Co-authored-by: Soha Alboghdady Co-authored-by: Raghunath Deshpande --- .hooks/README.md | 21 ++++++++++++++++++++ .hooks/commit-msg | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 .hooks/README.md create mode 100755 .hooks/commit-msg diff --git a/.hooks/README.md b/.hooks/README.md new file mode 100644 index 00000000..1bee1455 --- /dev/null +++ b/.hooks/README.md @@ -0,0 +1,21 @@ +# Git Hooks + +Run conventional commit checks locally without any tool installation + +## Usage + +Adjust the git commit hook configuration as follows, from the root directory of pcap-release: + +```shell +git config core.hooksPath .hooks +``` + +Please note that any hooks you had in other directories may not work. + +Alternatively you can also soft-link the commit-msg script: + +```shell +ln -s .hooks/commit-msg .git/hooks/commit-msg +``` + +This invocation will fail if you have a commit-msg hook already, in order to not break existing hooks. \ No newline at end of file diff --git a/.hooks/commit-msg b/.hooks/commit-msg new file mode 100755 index 00000000..eb6ecc9f --- /dev/null +++ b/.hooks/commit-msg @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# use commitlint with its full config if available +if command -v commitlint >/dev/null && commitlint -v >/dev/null; then + # Find base directory (script_location/..) + COMMITLINT_CONFIG="$(realpath "$(dirname "$0")/..")/commitlint.config.js" + # execute commitlint only if the commitlint config exists + [[ -f "$COMMITLINT_CONFIG" ]] && exec commitlint --edit "$1" --verbose --config "$COMMITLINT_CONFIG" +fi + +# Configuration + +# list of allowed commit types, space separated +TYPES="fix feat dep ci doc refactor test" +# scope length +SCOPE_LENGTH=25 +# commit subject length +SUBJECT_LENGTH=70 + +# Logic +first_line=$(head -n1 "$1") +conv_commit_msg="^(${TYPES// /|})(\(.{1,$SCOPE_LENGTH}\))?(!?): (.{1,$SUBJECT_LENGTH})\$" + +_print_convention() { + echo "ERROR: Commit message does not confirm to commit conventions." + echo " ----" + sed 's/^/ > /' "$1" + echo + echo "Rules: type(scope)!: commit subject" + echo " - type: must be one of: ${TYPES// /, }" + echo " - scope: (optional) arbitrary text: " + echo " - !: breaking change indicator. Body MUST contain 'breaking-change:' header (case in-sensitive)" +} + +# trap will be fired when the script exits. It will exit if any of the commands, including the grep below, fail. +trap '_print_convention "$1"' EXIT + +# check that the first line conforms to the convention pattern +grep -qE "$conv_commit_msg" <<< "$first_line" + +# if there is a !, indicating breaking change, ensure that there is a "breaking-change:" header. +if [[ "$(sed -nE "s/$conv_commit_msg/\3/p" <<<"$first_line")" == "!" ]]; then + grep -qiE "^breaking(-| )change: .+" "$1" +fi + +# All rules passed. Disable _print_convention printing +trap "" EXIT