Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and versions are tracked in the repo-root `VERSION` file.

## [Unreleased]

### Fixed

- Made `gh_run` report failed GitHub CLI commands even when callers enable
`set -e`, and preserved argument boundaries in GitHub command failure logs.

## [1.2.0] - 2026-07-04

### Added
Expand Down
14 changes: 10 additions & 4 deletions lib/bash/gh/lib_gh.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,24 @@ gh_auth_status_diagnostics() {
gh_report_command_failure() {
local status="$1"
shift
local printable_args=""

log_error "GitHub command failed: gh $*"
if (($#)); then
printf -v printable_args '%q ' "$@"
printable_args="${printable_args% }"
log_error "GitHub command failed: gh $printable_args"
else
log_error "GitHub command failed: gh"
fi
gh_auth_status_diagnostics || true
return "$status"
}

gh_run() {
local status
local status=0

gh_require_cli || return 1
gh "$@"
status=$?
gh "$@" || status=$?
((status == 0)) && return 0
gh_report_command_failure "$status" "$@"
}
Expand Down
64 changes: 64 additions & 0 deletions lib/bash/gh/tests/lib_gh.bats
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,70 @@ EOF
[[ "$output" == *"Run 'gh auth login -h github.com' and retry."* ]]
}

@test "gh_run reports command failure under set -e" {
local script="$TEST_TMPDIR/gh-run-set-e.sh"

create_fake_gh <<'EOF'
#!/usr/bin/env bash
if [[ "$1" == "auth" && "$2" == "status" ]]; then
printf 'not logged in\n' >&2
exit 1
fi
printf 'command failed\n' >&2
exit 7
EOF
cat > "$script" <<EOF
#!/usr/bin/env bash
set -euo pipefail
source "$BASE_BASH_DIR/std/lib_std.sh"
source "$BASE_BASH_DIR/gh/lib_gh.sh"
PATH="$TEST_TMPDIR/bin:$BASE_TEST_ORIG_PATH"
gh_run issue create --title Example
printf 'after\n'
EOF
chmod +x "$script"

bats_run bash "$script"

[ "$status" -eq 7 ]
[[ "$output" == *"command failed"* ]]
[[ "$output" == *"GitHub command failed: gh issue create --title Example"* ]]
[[ "$output" == *"gh auth status: not logged in"* ]]
[[ "$output" != *"after"* ]]
}

@test "gh_run quotes arguments when reporting command failure" {
create_fake_gh <<'EOF'
#!/usr/bin/env bash
if [[ "$1" == "auth" && "$2" == "status" ]]; then
exit 0
fi
exit 7
EOF

bats_run gh_run issue create --title "Example Title" --body "body value"

[ "$status" -eq 7 ]
[[ "$output" == *"GitHub command failed: gh issue create --title Example\\ Title --body body\\ value"* ]]
[[ "$output" != *"GitHub command failed: gh issue create --title Example Title --body body value"* ]]
}

@test "gh_run returns 1 with an error when gh is not on PATH" {
mkdir -p "$TEST_TMPDIR/no-gh-bin"

bats_run "$BASH" -c '
source "$1"
source "$2"
PATH="$3"
gh_run issue list
' bash "$BASE_BASH_DIR/std/lib_std.sh" "$BASE_BASH_DIR/gh/lib_gh.sh" "$TEST_TMPDIR/no-gh-bin"

[ "$status" -eq 1 ]
[[ "$output" == *"Required command 'gh' was not found on PATH."* ]]
[[ "$output" != *"GitHub command failed"* ]]
[[ "$output" != *"gh auth status"* ]]
}

@test "gh_repo_from_remote_url parses supported GitHub remotes" {
local repo

Expand Down
Loading