framework tools/git: issue-close R1/R4 conversion (P1 first wrapper)

Same contract as issue-comment (PR #1462): -b/--body canonical comment
flag with -c/--comment alias; usage errors stderr + exit 2 (unknown
option, missing -i, value-less flags); provider failures normalized to
exit 1 on the GitHub path (gh's own usage errors exit 2 and would
collide with the reserved status).

New suite test-issue-close-usage-contract.sh, enrolled in
framework-shell CI (enumeration guard OK, population 74). Probe
assertions split: parser arms must contact zero providers; sandbox arms
may issue detection reads only (tea login list), never gh/curl.
Existing fail-closed suite still green. Mirrored to the brain tree.
This commit is contained in:
2026-08-28 17:53:02 -05:00
parent 41f1bc0d37
commit 7a38eed18a
3 changed files with 167 additions and 11 deletions
@@ -1,6 +1,7 @@
#!/bin/bash
# issue-close.sh - Close an issue on GitHub or Gitea
# Usage: issue-close.sh -i <issue_number> [-c <comment>]
# Usage: issue-close.sh -i <issue_number> [-b <comment>]
# (-c/--comment is a backward-compatible alias for -b/--body; R1/R4 2026-08-28)
set -e
@@ -12,35 +13,49 @@ source "$SCRIPT_DIR/detect-platform.sh"
ISSUE_NUMBER=""
COMMENT=""
# Usage-error contract (R4, 2026-08-28): usage errors print to STDERR and exit 2,
# distinct from provider, credential, and verification failures (exit 1), so a
# caller or stop gate can tell an invocation defect from a delivery blocker.
usage_error() {
echo "Error: $*" >&2
echo "Usage: issue-close.sh -i <issue_number> [-b <comment>] (see --help)" >&2
exit 2
}
while [[ $# -gt 0 ]]; do
case $1 in
-i|--issue)
[[ $# -ge 2 ]] || usage_error "option $1 requires a value"
ISSUE_NUMBER="$2"
shift 2
;;
-c|--comment)
-b|--body|-c|--comment)
# R1 (2026-08-28): --body is the canonical flag; -c/--comment stays
# a backward-compatible alias.
[[ $# -ge 2 ]] || usage_error "option $1 requires a value"
COMMENT="$2"
shift 2
;;
-h|--help)
echo "Usage: issue-close.sh -i <issue_number> [-c <comment>]"
echo "Usage: issue-close.sh -i <issue_number> [-b <comment>]"
echo ""
echo "Options:"
echo " -i, --issue Issue number (required)"
echo " -c, --comment Comment to add before closing (optional)"
echo " -b, --body Comment to add before closing (optional; canonical)"
echo " -c, --comment Alias for --body"
echo " -h, --help Show this help"
echo ""
echo "Exit codes: 0 success; 2 usage error (stderr); 1 provider/credential/verification failure."
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
usage_error "unknown option: $1"
;;
esac
done
if [[ -z "$ISSUE_NUMBER" ]]; then
echo "Error: Issue number is required (-i)"
exit 1
usage_error "issue number is required (-i/--issue)"
fi
# Detect platform and close issue
@@ -82,10 +97,22 @@ gitea_issue_close_api() {
}
if [[ "$PLATFORM" == "github" ]]; then
# R4: normalize provider failures to exit 1 (gh's own usage errors exit 2
# and would collide with the reserved usage-error status).
if [[ -n "$COMMENT" ]]; then
gh issue comment "$ISSUE_NUMBER" --body "$COMMENT"
gh_rc=0
gh issue comment "$ISSUE_NUMBER" --body "$COMMENT" || gh_rc=$?
if [[ "$gh_rc" -ne 0 ]]; then
echo "Error: GitHub comment before close failed (gh exit $gh_rc)" >&2
exit 1
fi
fi
gh_rc=0
gh issue close "$ISSUE_NUMBER" || gh_rc=$?
if [[ "$gh_rc" -ne 0 ]]; then
echo "Error: GitHub issue close failed (gh exit $gh_rc)" >&2
exit 1
fi
gh issue close "$ISSUE_NUMBER"
echo "Closed GitHub issue #$ISSUE_NUMBER"
elif [[ "$PLATFORM" == "gitea" ]]; then
GITEA_LOGIN_NAME=$(get_gitea_login || true)