Files
mimic/scripts/open-pr.sh

137 lines
3.8 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
# Open a pull request against the Mimic Gitea repository using the credentials
# already stored in ~/.git-credentials (the same token used for `git push`).
#
# Usage:
# scripts/open-pr.sh --title "feat: sprint N — short summary" \
# --body path/to/body.md \
# [--base main] \
# [--head <current branch by default>]
#
# Or via the Makefile wrapper:
# make open-pr TITLE="feat: sprint 4 — UI polish" BODY=tasks/pr-body-sprint-4.md
#
# Output: prints the PR URL on success, exits non-zero on failure.
set -euo pipefail
# --- Arg parsing ------------------------------------------------------------
TITLE=""
BODY_FILE=""
BASE="main"
HEAD=""
while [[ $# -gt 0 ]]; do
case "$1" in
--title)
TITLE="${2:-}"
shift 2
;;
--body)
BODY_FILE="${2:-}"
shift 2
;;
--base)
BASE="${2:-}"
shift 2
;;
--head)
HEAD="${2:-}"
shift 2
;;
--sprint)
# purely informational; ignored — the title is what carries semantics
shift 2
;;
-h|--help)
sed -n '2,15p' "$0"
exit 0
;;
*)
echo "Unknown arg: $1" >&2
exit 2
;;
esac
done
[[ -n "$TITLE" ]] || { echo "--title is required" >&2; exit 2; }
[[ -n "$BODY_FILE" ]] || { echo "--body is required" >&2; exit 2; }
[[ -f "$BODY_FILE" ]] || { echo "body file not found: $BODY_FILE" >&2; exit 2; }
# --- Credentials ------------------------------------------------------------
CRED_FILE="${HOME}/.git-credentials"
[[ -f "$CRED_FILE" ]] || { echo "no ~/.git-credentials — git push must have run at least once" >&2; exit 3; }
# Detect Gitea host from origin remote
ORIGIN_URL=$(git remote get-url origin)
# Strip protocol, .git suffix → host/owner/repo
case "$ORIGIN_URL" in
https://*)
REST="${ORIGIN_URL#https://}"
;;
*)
echo "origin is not https (got: $ORIGIN_URL) — this script supports HTTPS Gitea only" >&2
exit 3
;;
esac
REST="${REST%.git}"
HOST="${REST%%/*}"
PATHPART="${REST#*/}" # owner/repo
OWNER="${PATHPART%%/*}"
REPO="${PATHPART#*/}"
REPO="${REPO%%/*}" # belt + braces in case of trailing slash
# Match the credential line for this host
CRED_LINE=$(grep -E "^https://[^@]+@${HOST}\$" "$CRED_FILE" || true)
[[ -n "$CRED_LINE" ]] || { echo "no credential for host ${HOST} in ${CRED_FILE}" >&2; exit 3; }
USER_PART=$(echo "$CRED_LINE" | sed -E 's|^https://([^:]+):.*|\1|')
TOKEN=$(echo "$CRED_LINE" | sed -E 's|^https://[^:]+:([^@]+)@.*$|\1|')
[[ -n "$USER_PART" && -n "$TOKEN" ]] || { echo "could not parse user/token from credential" >&2; exit 3; }
# --- Branch -----------------------------------------------------------------
if [[ -z "$HEAD" ]]; then
HEAD=$(git rev-parse --abbrev-ref HEAD)
fi
[[ "$HEAD" != "HEAD" ]] || { echo "detached HEAD — pass --head explicitly" >&2; exit 3; }
# --- Compose payload --------------------------------------------------------
API_URL="https://${HOST}/api/v1/repos/${OWNER}/${REPO}/pulls"
PAYLOAD=$(jq -n \
--arg title "$TITLE" \
--rawfile body "$BODY_FILE" \
--arg head "$HEAD" \
--arg base "$BASE" \
'{title:$title, body:$body, head:$head, base:$base}')
# --- POST -------------------------------------------------------------------
RESPONSE_FILE=$(mktemp)
HTTP_CODE=$(curl -sS -u "${USER_PART}:${TOKEN}" \
-H "Content-Type: application/json" \
-X POST \
-d "$PAYLOAD" \
-o "$RESPONSE_FILE" \
-w "%{http_code}" \
"$API_URL")
if [[ "$HTTP_CODE" != "201" ]]; then
echo "PR creation failed (HTTP $HTTP_CODE):" >&2
jq -r '.message // empty' "$RESPONSE_FILE" >&2 2>/dev/null || cat "$RESPONSE_FILE" >&2
rm -f "$RESPONSE_FILE"
exit 4
fi
PR_URL=$(jq -r '.html_url' "$RESPONSE_FILE")
PR_NUMBER=$(jq -r '.number' "$RESPONSE_FILE")
rm -f "$RESPONSE_FILE"
echo "Opened PR #${PR_NUMBER}"
echo "$PR_URL"