mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 08:25:32 +00:00
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' instead of '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 |