Files
clio/pre-commit-hooks/verify-commits.sh
2026-05-28 11:20:19 +01:00

57 lines
1.9 KiB
Bash
Executable File

#!/bin/bash
# Annotated tags have object type "tag"; lightweight tags have type "commit".
# To inspect tags: git for-each-ref refs/tags
#
# To always sign commits and tags, configure:
# git config --global commit.gpgsign true
# git config --global tag.gpgsign true
verify_commit_signed() {
if git verify-commit HEAD &>/dev/null; then
echo "HEAD commit is signed."
else
echo "HEAD commit is not signed!"
exit 1
fi
}
verify_tag_annotated() {
local version="$1"
# git cat-file -t returns "tag" for annotated tags, "commit" for lightweight.
if [[ "$(git cat-file -t "$version")" == "tag" ]]; then
echo "Tag '$version' is annotated."
else
echo "Tag '$version' is not annotated!"
echo "Re-create it with: git tag -a -s -m \"$version\" \"$version\""
exit 1
fi
}
verify_tag_signed() {
local version="$1"
if git verify-tag "$version" &>/dev/null; then
echo "Tag '$version' is signed."
else
echo "Tag '$version' is not signed!"
echo "Sign it with: git tag -a -s -m \"$version\" \"$version\""
exit 1
fi
}
# Enforce signing and annotated tags when pushing to a release branch.
if echo "$PRE_COMMIT_REMOTE_BRANCH" | grep -q "^refs/heads/release/"; then
# git describe --exact-match guarantees a single tag; git tag --points-at HEAD
# can return multiple newline-separated values, which breaks downstream commands.
version=$(git describe --exact-match --tags HEAD 2>/dev/null)
if [[ -z "$version" ]]; then
echo "No tag found at HEAD — cannot push an untagged release commit!"
exit 1
fi
echo "Looks like you're trying to push a '$version' release..."
echo "Verifying the commit is signed and the tag is annotated and signed."
verify_commit_signed
verify_tag_annotated "$version"
verify_tag_signed "$version"
fi