Files
trailofbits__skills/plugins/gh-cli/hooks/setup-shims.bats
David Maynor 38793f6757 fix(gh-cli): exit 0 when CLAUDE_ENV_FILE is unset (#135)
* fix(gh-cli): exit 0 when CLAUDE_ENV_FILE is unset in setup-shims.sh

When CLAUDE_ENV_FILE is not set by the runtime, setup-shims.sh exits 1,
causing a SessionStart hook error in Claude Code. This is a graceful
degradation case (shims simply won't be installed), not a fatal error.

The gh-not-found guard on line 10 already exits 0 for the same reason.
This change makes the CLAUDE_ENV_FILE guard consistent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(gh-cli): update bats test for exit 0 and bump version to 1.4.1

The bats test for the CLAUDE_ENV_FILE-unset guard still expected exit 1.
Update it to match the new graceful-degradation behavior, and bump the
plugin version so clients pick up the fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: David Maynor <dmaynor@Davids-MacBook-Air-2.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-04-28 19:28:59 -04:00

98 lines
2.9 KiB
Bash

#!/usr/bin/env bats
# Tests for setup-shims.sh SessionStart hook
SETUP_SCRIPT="${BATS_TEST_DIRNAME}/setup-shims.sh"
setup() {
export CLAUDE_ENV_FILE
CLAUDE_ENV_FILE="$(mktemp)"
# Create a fake gh so the guard passes
FAKE_BIN="$(mktemp -d)"
echo '#!/usr/bin/env bash' >"$FAKE_BIN/gh"
chmod +x "$FAKE_BIN/gh"
export FAKE_BIN
export ORIG_PATH="$PATH"
}
teardown() {
rm -f "$CLAUDE_ENV_FILE"
rm -rf "$FAKE_BIN"
}
@test "exits gracefully when CLAUDE_ENV_FILE is not set" {
run env -u CLAUDE_ENV_FILE PATH="${FAKE_BIN}:${ORIG_PATH}" \
bash "$SETUP_SCRIPT" 2>&1
[[ $status -eq 0 ]]
[[ "$output" == *"CLAUDE_ENV_FILE not set"* ]]
}
@test "exits gracefully when gh is not available" {
local path_without_gh=""
local IFS=:
for dir in $ORIG_PATH; do
[[ "$dir" == "$FAKE_BIN" ]] && continue
[[ -x "$dir/gh" ]] && continue
path_without_gh="${path_without_gh:+${path_without_gh}:}$dir"
done
# Use absolute bash path since filtering gh may remove /usr/bin from PATH
local bash_path
bash_path="$(command -v bash)"
run env PATH="$path_without_gh" CLAUDE_ENV_FILE="$CLAUDE_ENV_FILE" \
"$bash_path" "$SETUP_SCRIPT" 2>&1
[[ $status -eq 0 ]]
[[ ! -s "$CLAUDE_ENV_FILE" ]]
[[ "$output" == *"gh not found on PATH"* ]]
}
@test "writes PATH export to CLAUDE_ENV_FILE" {
run env PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
[[ $status -eq 0 ]]
grep -q 'export PATH=' "$CLAUDE_ENV_FILE"
}
@test "shims dir appears in PATH export" {
env PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
local shims_dir
shims_dir="$(cd "${BATS_TEST_DIRNAME}/shims" && pwd)"
grep -q "$shims_dir" "$CLAUDE_ENV_FILE"
}
@test "shims dir is an absolute path" {
env PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
local line
line="$(cat "$CLAUDE_ENV_FILE")"
[[ "$line" =~ export\ PATH=\"/ ]]
}
@test "exits with error when shims/gh is not executable" {
local tmpdir
tmpdir="$(mktemp -d)"
cp "$SETUP_SCRIPT" "$tmpdir/setup-shims.sh"
mkdir -p "$tmpdir/shims"
# Create a non-executable gh file
echo '#!/usr/bin/env bash' >"$tmpdir/shims/gh"
run env PATH="${FAKE_BIN}:${ORIG_PATH}" CLAUDE_ENV_FILE="$CLAUDE_ENV_FILE" \
bash "$tmpdir/setup-shims.sh" 2>&1
[[ $status -ne 0 ]]
[[ "$output" == *"shims/gh not found or not executable"* ]]
rm -rf "$tmpdir"
}
@test "exits with error when shims directory is missing" {
local tmpdir
tmpdir="$(mktemp -d)"
cp "$SETUP_SCRIPT" "$tmpdir/setup-shims.sh"
run env PATH="${FAKE_BIN}:${ORIG_PATH}" CLAUDE_ENV_FILE="$CLAUDE_ENV_FILE" \
bash "$tmpdir/setup-shims.sh" 2>&1
[[ $status -ne 0 ]]
[[ "$output" == *"shims directory not found"* ]]
rm -rf "$tmpdir"
}
@test "appends to existing CLAUDE_ENV_FILE content" {
echo 'export FOO=bar' >"$CLAUDE_ENV_FILE"
env PATH="${FAKE_BIN}:${ORIG_PATH}" bash "$SETUP_SCRIPT"
grep -q 'export FOO=bar' "$CLAUDE_ENV_FILE"
grep -q 'export PATH=' "$CLAUDE_ENV_FILE"
}