mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 08:25:32 +00:00
These changes come out of discussion in the team; we want to make use of git trailers and improve the quality of our commit messages. Starting by adding more hints to the commit suggestions. Includes some minor cleanup of the hooks, and hopefully also improves tests so that they don't interfere with interactions with non-Keyman repos. Note: the scopes list may need maintenance as the list still includes sub-scopes and 'oem'.
139 lines
No EOL
4.4 KiB
Bash
Executable file
139 lines
No EOL
4.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
#
|
|
# This commit-msg hook validates commit messages
|
|
# to ensure that they meet our conventional commit standard.
|
|
#
|
|
#
|
|
# "type: message"
|
|
# "type(scope): message"
|
|
# Optionally, append ". Fixes #1234"
|
|
#
|
|
# Reference: https://github.com/keymanapp/keyman/wiki/Pull-Request-and-Commit-workflow-notes
|
|
#
|
|
|
|
# Get the directory where this script lives, i.e. resources/git-hooks
|
|
HOOK_DIRECTORY="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
|
|
|
|
if [ -f $(dirname "${BASH_SOURCE[0]}")/commit-msg-defs ]; then
|
|
# This script was run from a symlink and the repo in question has its own commit-msg-defs.
|
|
. $(dirname "${BASH_SOURCE[0]}")/commit-msg-defs
|
|
else
|
|
# We'll grab the settings from the keymanapp/keyman repository.
|
|
. "$HOOK_DIRECTORY/../build/jq.inc.sh"
|
|
|
|
# Configurable options for message length.
|
|
min_length=4
|
|
max_length=128
|
|
|
|
# Read from our globally shared JSON-formatted scopes and types
|
|
scopes=( $("$JQ" -r '[.scopes | paths | reduce .[] as $item (""; if . == "" then $item else . + "/" + $item end)] | join(" ")' < "$HOOK_DIRECTORY/../scopes/scopes.json") )
|
|
types=( $("$JQ" -r '.commitTypes | join(" ")' < "$HOOK_DIRECTORY/../scopes/commit-types.json") )
|
|
fi
|
|
|
|
#
|
|
# Define terminal colours.
|
|
#
|
|
|
|
if [ -t 2 ]; then
|
|
t_red=$'\e[1;31m'
|
|
t_grn=$'\e[1;32m'
|
|
t_yel=$'\e[1;33m'
|
|
t_blu=$'\e[1;34m'
|
|
t_mag=$'\e[1;35m'
|
|
t_cyn=$'\e[1;36m'
|
|
t_end=$'\e[0m'
|
|
fi
|
|
|
|
#
|
|
# Test the repository upstream/origin: ignore if not keymanapp/keyman
|
|
#
|
|
|
|
GIT_ORIGIN="$(git remote get-url origin)"
|
|
|
|
if [[ ! "$GIT_ORIGIN" =~ github\.com/keymanapp ]]; then
|
|
# Not a Keyman repository. We have no opinion.
|
|
# echo "DEBUG: Not a Keyman repository. We don't care"
|
|
exit 0
|
|
fi
|
|
|
|
|
|
if [[ "$GIT_ORIGIN" =~ keyboards|lexical-models ]]; then
|
|
# We don't enforce commit messages on keyboards or lexical-models repositories
|
|
# echo "DEBUG: Keyboards or Lexical-Models. We still don't care."
|
|
exit 0
|
|
fi
|
|
|
|
# If this script is called by another hook, it may insert a -q parameter to silence the help text.
|
|
QUIET=0
|
|
case $1 in
|
|
-q|--quiet)
|
|
shift # Remove the parameter, making it equivalent to a standard git-hook call.
|
|
QUIET=1
|
|
;;
|
|
esac
|
|
|
|
# build the regex pattern based on the config file
|
|
function build_regex() {
|
|
retypes=
|
|
for type in "${types[@]}"
|
|
do
|
|
retypes="${retypes}$type|"
|
|
done
|
|
retypes="(${retypes%?})"
|
|
|
|
rescope=
|
|
for scope in "${scopes[@]}"
|
|
do
|
|
rescope="${rescope}$scope|"
|
|
done
|
|
# %? removes last |
|
|
rescope="(\((${rescope%?})\))?"
|
|
|
|
remessage=".{$min_length,$max_length}[^.]"
|
|
refixes="(\. Fixes #[[:digit:]]+)?"
|
|
|
|
# Regex for the commit message title. It's ok if the commit message starts with "fixup!".
|
|
# (This allows to run `git commit --fixup=<sha>` without complaining about the commit
|
|
# message not being in conventional commit format. This helps in squashing with a previous
|
|
# commit.)
|
|
regexp="^(fixup\! )?${retypes}${rescope}: ${remessage}${refixes}[[:space:]]*$"
|
|
}
|
|
|
|
# Print out a standard error message which explains
|
|
# how the commit message should be structured
|
|
function print_error() {
|
|
echo -e "\n${t_red}ERROR: Commit message is not in Conventional Commit format"
|
|
echo -e "----------------------------------------------------------${t_end}"
|
|
echo -e "Valid types: ${t_grn}${types[@]}${t_end}"
|
|
echo -e "Valid scopes: ${t_grn}${scopes[@]}${t_end}"
|
|
echo -e "Max length (first line): ${t_grn}$max_length${t_end}"
|
|
echo -e "Min length (first line): ${t_grn}$min_length${t_end}"
|
|
echo -e "If possible, append git trailers:"
|
|
echo -e " * ${t_grn}Fixes: #1234${t_end}"
|
|
echo -e " * ${t_grn}Fixes: KEYMAN-MODULE-XYZ${t_end}"
|
|
echo -e " * ${t_grn}Cherry-pick-of: #2468${t_end}"
|
|
echo -e " * ${t_grn}Co-authored-by: Firstname Lastname <email@keyman.com>${t_end}"
|
|
echo -e "${t_cyn}Example:${t_end} fix(windows): Re-attach the widget plug which had fallen out"
|
|
echo -e "${t_cyn}Reference${t_end}: https://github.com/keymanapp/keyman/wiki/Pull-Request-and-Commit-workflow-notes"
|
|
echo -e ""
|
|
echo -e "Tips: "
|
|
echo -e " * Don't include a period at the end of the title"
|
|
echo -e " * Always include a blank line before trailers"
|
|
echo -e " * Use imperative, present tense ('attach' not 'attaches', 'attached' etc)"
|
|
echo -e ""
|
|
echo -e "This script: $0"
|
|
}
|
|
|
|
# get the first line of the commit message
|
|
msg=$(head -1 $1)
|
|
|
|
build_regex
|
|
|
|
if [[ ! $msg =~ $regexp ]]; then
|
|
# commit message is invalid according to config - block commit
|
|
if [ $QUIET -eq 0 ]; then
|
|
print_error
|
|
fi
|
|
exit 1
|
|
fi |