Skip to content

fix(hooks): guard GRAPHIFY_BIN assignment against sh -e exit when graphify not in PATH#1078

Open
j-strum wants to merge 1 commit into
safishamsi:v8from
j-strum:fix/husky-sh-e-graphify-bin-assignment
Open

fix(hooks): guard GRAPHIFY_BIN assignment against sh -e exit when graphify not in PATH#1078
j-strum wants to merge 1 commit into
safishamsi:v8from
j-strum:fix/husky-sh-e-graphify-bin-assignment

Conversation

@j-strum
Copy link
Copy Markdown

@j-strum j-strum commented May 29, 2026

Problem

Husky v9's h runner invokes hooks with sh -e. On macOS (and any POSIX sh), a failing command substitution in a variable assignment — VAR=$(cmd_that_returns_1) — propagates the non-zero exit code, and sh -e terminates the script immediately.

When graphify is installed via pyenv (shim at ~/.pyenv/shims/graphify) and a GUI git client like SourceTree runs git with a stripped PATH that excludes ~/.pyenv/shims, command -v graphify returns exit code 1. The entire hook exits with code 1 before reaching the graceful exit 0 fallback — causing Husky to report:

husky - post-checkout script failed (code 1)
husky - post-commit script failed (code 1)

Reproducible with:

sh -e -c 'VAR=$(command -v does_not_exist 2>/dev/null); echo "survived"'
# exits 1, "survived" never prints

The same issue affects any tool that strips user PATH entries: SourceTree, Tower, VS Code's built-in git, cron, and CI runners.

Fix

|| true absorbs the non-zero exit so the assignment always succeeds. GRAPHIFY_BIN is left empty, and the existing if [ -n "$GRAPHIFY_BIN" ] guard + python3 fallback + final exit 0 handle the "not found" case correctly as intended.

-GRAPHIFY_BIN=$(command -v graphify 2>/dev/null)
+GRAPHIFY_BIN=$(command -v graphify 2>/dev/null) || true

Change

One line in graphify/hooks.py — the _PYTHON_DETECT shell template string shared by both the post-commit and post-checkout hook generators.

…phify not in PATH

Husky v9's `h` runner invokes hooks with `sh -e`. On macOS (and any
POSIX sh), a failing command substitution in a variable assignment —
VAR=$(cmd_that_returns_1) — propagates the non-zero exit code, and
sh -e terminates the script immediately.

When graphify is installed via pyenv (shim at ~/.pyenv/shims/graphify)
and a GUI git client like SourceTree runs git with a stripped PATH
that excludes ~/.pyenv/shims, `command -v graphify` returns exit
code 1. The entire hook exits with code 1 before reaching the graceful
`exit 0` fallback — causing Husky to report "post-checkout script
failed (code 1)" and "post-commit script failed (code 1)".

The fix: || true absorbs the non-zero exit so the assignment always
succeeds. GRAPHIFY_BIN is left empty, and the existing
if [ -n "$GRAPHIFY_BIN" ] guard + python3 fallback + final exit 0
handle the "not found" case correctly as intended.

Affects any tool that strips user PATH entries: SourceTree, Tower,
VS Code's built-in git, cron, and CI runners.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 29, 2026 13:03
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Improves the robustness of the embedded shell snippet used to detect the graphify executable so the hook logic doesn’t fail when graphify isn’t on PATH.

Changes:

  • Make command -v graphify non-fatal by appending || true to the assignment line.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants