Skip to content

Commit c5a89e6

Browse files
jdclaude
andauthored
feat(stack): add git hooks with sourcing architecture (#926)
Implement a new hook structure that separates user-modifiable wrappers from managed scripts: - .git/hooks/{hook} - Thin wrapper (user can add custom logic) - .git/hooks/mergify-hooks/{hook}.sh - Managed script (auto-upgradable) This allows automatic upgrades of hook logic without touching user customizations. Legacy hooks are detected and can be migrated with --force flag. CLI changes: - `mergify stack setup --force`: Force reinstall wrappers - `mergify stack setup --check`: Check status without changes - `mergify stack push --no-upgrade-hooks`: Skip auto-upgrade Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 23fccfc commit c5a89e6

File tree

7 files changed

+266
-55
lines changed

7 files changed

+266
-55
lines changed

mergify_cli/stack/cli.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,20 @@ def github_server_to_context(
9797

9898

9999
@stack.command(help="Configure the required git commit-msg hooks") # type: ignore[untyped-decorator]
100+
@click.option(
101+
"--force",
102+
"-f",
103+
is_flag=True,
104+
help="Force reinstall of hook wrappers, even if user modified them",
105+
)
106+
@click.option(
107+
"--check",
108+
is_flag=True,
109+
help="Only check hook status without making changes",
110+
)
100111
@utils.run_with_asyncio
101-
async def setup() -> None:
102-
await stack_setup_mod.stack_setup()
112+
async def setup(*, force: bool, check: bool) -> None:
113+
await stack_setup_mod.stack_setup(force=force, check_only=check)
103114

104115

105116
@stack.command(help="Edit the stack history") # type: ignore[untyped-decorator]
@@ -115,6 +126,11 @@ async def edit() -> None:
115126
is_flag=True,
116127
hidden=True,
117128
)
129+
@click.option(
130+
"--no-upgrade-hooks",
131+
is_flag=True,
132+
help="Skip automatic hook script upgrades",
133+
)
118134
@click.option("--dry-run", "-n", is_flag=True, default=False, help="dry run")
119135
@click.option(
120136
"--next-only",
@@ -177,6 +193,7 @@ async def push(
177193
ctx: click.Context,
178194
*,
179195
setup: bool,
196+
no_upgrade_hooks: bool,
180197
dry_run: bool,
181198
next_only: bool,
182199
skip_rebase: bool,
@@ -192,6 +209,10 @@ async def push(
192209
await stack_setup_mod.stack_setup()
193210
return
194211

212+
# Auto-upgrade hook scripts (not wrappers) unless disabled
213+
if not no_upgrade_hooks:
214+
await stack_setup_mod.ensure_hooks_updated()
215+
195216
await stack_push_mod.stack_push(
196217
github_server=ctx.obj["github_server"],
197218
token=ctx.obj["token"],

mergify_cli/stack/hooks/commit-msg renamed to mergify_cli/stack/hooks/scripts/commit-msg.sh

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
#!/bin/sh
2+
# Mergify CLI Hook Script
3+
# This file is managed by mergify-cli and will be auto-upgraded.
4+
# Do not modify - add custom logic to the wrapper file instead.
5+
#
26
# Based on Gerrit Code Review 3.1.3
37
#
48
# Part of Gerrit Code Review (https://www.gerritcodereview.com/)
@@ -28,11 +32,6 @@ if test ! -f "$1" ; then
2832
exit 1
2933
fi
3034

31-
# Do not create a change id if requested
32-
#if test "false" = "`git config --bool --get gerrit.createChangeId`" ; then
33-
# exit 0
34-
#fi
35-
3635
# $RANDOM will be undefined if not using bash, so don't use set -u
3736
random=$( (whoami ; hostname ; date; cat $1 ; echo $RANDOM) | git hash-object --stdin)
3837
dest="$1.tmp.${random}"

mergify_cli/stack/hooks/prepare-commit-msg renamed to mergify_cli/stack/hooks/scripts/prepare-commit-msg.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#!/bin/sh
2+
# Mergify CLI Hook Script
3+
# This file is managed by mergify-cli and will be auto-upgraded.
4+
# Do not modify - add custom logic to the wrapper file instead.
25
#
36
# Copyright © 2021-2024 Mergify SAS
47
#
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh
2+
# Mergify CLI Hook Wrapper
3+
# This file is managed by mergify-cli. You can add custom logic below the marker.
4+
5+
MERGIFY_HOOKS_DIR="$(dirname "$0")/mergify-hooks"
6+
if [ -f "$MERGIFY_HOOKS_DIR/commit-msg.sh" ]; then
7+
"$MERGIFY_HOOKS_DIR/commit-msg.sh" "$@" || exit $?
8+
fi
9+
10+
# --- USER CUSTOM LOGIC BELOW ---
11+
# Add your custom hook logic here (preserved during upgrades)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh
2+
# Mergify CLI Hook Wrapper
3+
# This file is managed by mergify-cli. You can add custom logic below the marker.
4+
5+
MERGIFY_HOOKS_DIR="$(dirname "$0")/mergify-hooks"
6+
if [ -f "$MERGIFY_HOOKS_DIR/prepare-commit-msg.sh" ]; then
7+
"$MERGIFY_HOOKS_DIR/prepare-commit-msg.sh" "$@" || exit $?
8+
fi
9+
10+
# --- USER CUSTOM LOGIC BELOW ---
11+
# Add your custom hook logic here (preserved during upgrades)

0 commit comments

Comments
 (0)