Something went wrong. Try again.
Data management tools for playing BattleTech
Something went wrong. Try again.
Shell
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113#!/usr/bin/env bash## Check a commit message against Conventional Commits, and its scope against# the epics this repo's work belongs to.## Two differences from headquarters' hook of the same name, both deliberate.## It enforces the *form* as well as the scope. headquarters lets an# unconventional subject through, because that repo has years of them; this# one has had the convention from its second commit and there is no reason to# let it slip.## And the epic ids are written down here rather than read from plan/, because# helm has no plan/ - its epics live in headquarters, which is not guaranteed# to be checked out beside this repo and is certainly not guaranteed to be at# any particular revision. A hardcoded list that is occasionally stale is# better than a hook that passes silently whenever a sibling directory is# missing.## Run by prek at the commit-msg stage, with the message file as $1.
set -euo pipefail
# Conventional Commits types.TYPES="feat fix docs style refactor perf test build ci chore revert"
# Epic ids from headquarters' plan/. Add one here when an epic that helm does# work for is added there.EPIC_SCOPES="unit-library unit-search unit-rules forces"
# Scopes that are deliberately not epics. Keep this short: every entry is a# commit that cannot be found from an epic.NON_EPIC_SCOPES="deps scripts bridge ci repo"
msg_file="${1:?usage: check-commit-scope.sh <commit-msg-file>}"
# First line that is not a comment or blank; git strips the comments later.subject="$(grep -v '^#' "$msg_file" | grep -m1 . || true)"
# An empty message aborts the commit on git's side, so it is not this hook's# to complain about.[ -n "$subject" ] || exit 0
# A revert or a merge git wrote itself is not the author's prose to police.case "$subject" inRevert\ * | Merge\ *) exit 0 ;;esac
# type(scope)!: subject, where the scope is optional. The pattern is a# variable because bash's [[ ]] parser trips on an unquoted ")".full_re='^([a-z]+)(\(([^)]*)\))?!?: .+'if [[ ! "$subject" =~ $full_re ]]; then { echo "commit subject is not Conventional Commits:" echo " $subject" echo echo "Write: type(scope): what changed" echo " type: what changed" echo # shellcheck disable=SC2086 echo "Types: $(printf '%s, ' $TYPES | sed 's/, $//')" echo "Scopes: $EPIC_SCOPES $NON_EPIC_SCOPES" } >&2 exit 1fi
type="${BASH_REMATCH[1]}"scopes="${BASH_REMATCH[3]}"
case " $TYPES " in*" $type "*) ;;*) { echo "unknown commit type: $type" echo # shellcheck disable=SC2086 printf ' %s\n' $TYPES | sort } >&2 exit 1 ;;esac
# No scope is allowed: not every commit belongs to an epic.[ -n "$scopes" ] || exit 0
known="$EPIC_SCOPES $NON_EPIC_SCOPES"bad=""IFS=',' read -ra parts <<<"$scopes"for scope in "${parts[@]}"; do scope="$(printf '%s' "$scope" | tr -d '[:space:]')" [ -n "$scope" ] || continue case " $known " in *" $scope "*) ;; *) bad="$bad $scope" ;; esacdone
[ -n "$bad" ] || exit 0
{ echo "commit scope is not an epic or a known non-epic:$bad" echo echo "A scope names the epic in headquarters' plan/ that the work belongs" echo "to, so a commit is findable from it. Use one of:" echo # shellcheck disable=SC2086 printf ' %s\n' $known | sort -u echo echo "or drop the scope. If a new epic exists in headquarters, add its id" echo "to EPIC_SCOPES in this script."} >&2exit 1