Files
stack/packages/mosaic/framework/tools/git/pr-close.sh
T
marcie e3f4a45b88
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/manual/ci Pipeline is running
framework tools/git: R3 --body-file across all nine body/comment carriers
--body-file <path> and --body-file - (stdin) load the body/comment from
a file, killing the fragile shell-quoting class for long Markdown
(Jason remediation R3). Contract: mutually exclusive with --body
(rc 2), unreadable file rc 2 naming the path, resolution runs AFTER
parsing and BEFORE the required-value checks. Full arm set on the
issue-comment suite (file, stdin, exclusive, missing); all nine
carrier suites and the readback suite green. Mirrored to brain.
2026-08-29 11:27:32 -05:00

114 lines
4.2 KiB
Bash
Executable File

#!/bin/bash
# pr-close.sh - Close a pull request without merging on GitHub or Gitea
# Usage: pr-close.sh -n <pr_number> [-b <comment>]
# (-c/--comment is a backward-compatible alias for -b/--body; R1/R4 2026-08-28)
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
PR_NUMBER=""
COMMENT=""
BODY_FILE=""
# 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: pr-close.sh -n <pr_number> [-b <comment>] (see --help)" >&2
exit 2
}
while [[ $# -gt 0 ]]; do
case $1 in
-n|--number)
[[ $# -ge 2 && "$2" != - && "$2" != --* && ! "$2" =~ ^-[[:alnum:]] ]] || usage_error "option $1 requires a value (option-like values are rejected; bare - is reserved)"
PR_NUMBER="$2"
shift 2
;;
-b|--body|-c|--comment)
# R1 (2026-08-28): --body is the canonical flag; -c/--comment stays
# a backward-compatible alias.
[[ $# -ge 2 && "$2" != - && "$2" != --* && ! "$2" =~ ^-[[:alnum:]] ]] || usage_error "option $1 requires a value (option-like values are rejected; bare - is reserved)"
COMMENT="$2"
shift 2
;;
--body-file)
# R3: body from file (or '-' = stdin); mutually exclusive with --body.
[[ $# -ge 2 && "$2" != --* ]] || usage_error "option $1 requires a path (or - for stdin)"
BODY_FILE="$2"
shift 2
;;
-h|--help)
echo "Usage: pr-close.sh -n <pr_number> [-b <comment>]"
echo ""
echo "Options:"
echo " -n, --number PR number (required)"
echo " -b, --body Comment 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
;;
*)
usage_error "unknown option: $1"
;;
esac
done
# R3 (2026-08-29): resolve --body-file into COMMENT (file or stdin '-');
# exclusive with an explicit --body/--comment value.
if [[ -n "$BODY_FILE" ]]; then
[[ -z "$COMMENT" ]] || usage_error "--body-file and --body are mutually exclusive"
if [[ "$BODY_FILE" == "-" ]]; then
COMMENT=$(cat) || usage_error "could not read body from stdin"
else
[[ -r "$BODY_FILE" ]] || usage_error "body file not readable: $BODY_FILE"
COMMENT=$(cat "$BODY_FILE") || usage_error "could not read body file: $BODY_FILE"
fi
fi
if [[ -z "$PR_NUMBER" ]]; then
usage_error "PR number is required (-n/--number)"
fi
detect_platform >/dev/null
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_rc=0
gh pr comment "$PR_NUMBER" --body "$COMMENT" || gh_rc=$?
if [[ "$gh_rc" -ne 0 ]]; then
echo "Error: GitHub PR comment before close failed (gh exit $gh_rc)" >&2
exit 1
fi
fi
gh_rc=0
gh pr close "$PR_NUMBER" || gh_rc=$?
if [[ "$gh_rc" -ne 0 ]]; then
echo "Error: GitHub PR close failed (gh exit $gh_rc)" >&2
exit 1
fi
echo "Closed GitHub PR #$PR_NUMBER"
elif [[ "$PLATFORM" == "gitea" ]]; then
if [[ -n "$COMMENT" ]]; then
prov_rc=0
tea pr comment "$PR_NUMBER" "$COMMENT" $(get_gitea_repo_args) || prov_rc=$?
[[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; }
fi
prov_rc=0
tea pr close "$PR_NUMBER" $(get_gitea_repo_args) || prov_rc=$?
[[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; }
echo "Closed Gitea PR #$PR_NUMBER"
else
echo "Error: Unknown platform"
exit 1
fi