Add hooks to run shell snippets around git operations (#411)

* feat: add _run_hook helper and eight hook inputs

* fix(_run_hook): default snippet to empty when arg unset

* feat: wire add/commit hooks into _main

* feat: wire tag and push hooks into _main

* test: verify failing hook aborts the action

* docs: document hooks system in README

* test: tighten failing-hook assertion

* docs(hooks): note set -eu semantics for snippet authors

* refactor(hooks): rename action inputs to suffix with _hook

* refactor(hooks): include _hook suffix in event identifier

* docs(hooks): add notes about security implications of hooks
This commit is contained in:
Stefan Zweifel
2026-06-28 10:52:27 +02:00
committed by GitHub
parent c365a749b4
commit 9f6c933320
4 changed files with 360 additions and 2 deletions
+42 -2
View File
@@ -26,6 +26,16 @@ _log() {
echo "::$level::$message";
}
_run_hook() {
local name=${1}
local snippet=${2:-}
if [ -n "$snippet" ]; then
_log "debug" "Running $name";
eval "$snippet"
fi
}
_main() {
_check_if_git_is_available
@@ -40,26 +50,56 @@ _main() {
if "$INPUT_CREATE_GIT_TAG_ONLY"; then
_log "debug" "Create git tag only";
_set_github_output "create_git_tag_only" "true"
_tag_commit
if [ -n "$INPUT_TAG_NAME" ] || [ -n "$INPUT_TAGGING_MESSAGE" ]; then
_run_hook "before_tag_hook" "$INPUT_BEFORE_TAG_HOOK"
_tag_commit
_run_hook "after_tag_hook" "$INPUT_AFTER_TAG_HOOK"
else
_tag_commit
fi
if ! "$INPUT_SKIP_PUSH"; then
_run_hook "before_push_hook" "$INPUT_BEFORE_PUSH_HOOK"
fi
_push_to_github
if ! "$INPUT_SKIP_PUSH"; then
_run_hook "after_push_hook" "$INPUT_AFTER_PUSH_HOOK"
fi
elif _git_is_dirty || "$INPUT_SKIP_DIRTY_CHECK"; then
_set_github_output "changes_detected" "true"
_switch_to_branch
_run_hook "before_add_hook" "$INPUT_BEFORE_ADD_HOOK"
_add_files
_run_hook "after_add_hook" "$INPUT_AFTER_ADD_HOOK"
# Check dirty state of repo again using git-diff.
# (git-diff detects better if CRLF of files changes and does NOT
# proceed, if only CRLF changes are detected. See #241 and #265
# for more details.)
if [ -n "$(git diff --staged)" ] || "$INPUT_SKIP_DIRTY_CHECK"; then
_run_hook "before_commit_hook" "$INPUT_BEFORE_COMMIT_HOOK"
_local_commit
_run_hook "after_commit_hook" "$INPUT_AFTER_COMMIT_HOOK"
_tag_commit
if [ -n "$INPUT_TAG_NAME" ] || [ -n "$INPUT_TAGGING_MESSAGE" ]; then
_run_hook "before_tag_hook" "$INPUT_BEFORE_TAG_HOOK"
_tag_commit
_run_hook "after_tag_hook" "$INPUT_AFTER_TAG_HOOK"
else
_tag_commit
fi
if ! "$INPUT_SKIP_PUSH"; then
_run_hook "before_push_hook" "$INPUT_BEFORE_PUSH_HOOK"
fi
_push_to_github
if ! "$INPUT_SKIP_PUSH"; then
_run_hook "after_push_hook" "$INPUT_AFTER_PUSH_HOOK"
fi
else
_set_github_output "changes_detected" "false"