Skip to content

Instantly share code, notes, and snippets.

@xpepper
Last active February 24, 2026 18:40
Show Gist options
  • Select an option

  • Save xpepper/ae551dbd20782ea79f989658a44f7e24 to your computer and use it in GitHub Desktop.

Select an option

Save xpepper/ae551dbd20782ea79f989658a44f7e24 to your computer and use it in GitHub Desktop.
A script for using gh and copilot to create PR descriptions out of their git diff
#!/usr/bin/env bash
# pr-summarise: Generate and apply a PR description using GitHub Models.
# Usage: pr-summarise [PR number]
# If no PR number is given, uses the current branch's open PR.
#
# Required tools:
# gh - GitHub CLI (https://cli.github.com), authenticated via `gh auth login`
# curl - HTTP client, used to call the GitHub Models API
# jq - JSON processor (https://jqlang.org)
set -euo pipefail
# ── Config ────────────────────────────────────────────────────────────────────
MODEL="${PR_SUMMARISE_MODEL:-openai/gpt-4.1}"
MAX_DIFF_CHARS="${PR_SUMMARISE_MAX_DIFF_CHARS:-28000}"
ENDPOINT="${PR_SUMMARISE_ENDPOINT:-https://models.github.ai/inference/chat/completions}"
# For org attribution, set:
# export PR_SUMMARISE_ENDPOINT="https://models.github.ai/orgs/<ORG>/inference/chat/completions"
# ── Resolve PR number ─────────────────────────────────────────────────────────
if [[ $# -ge 1 ]]; then
PR="$1"
else
if ! PR=$(gh pr view --json number -q '.number' 2>/dev/null); then
echo "Error: no PR number given and no open PR found for the current branch." >&2
exit 1
fi
fi
# ── Fetch existing PR description ─────────────────────────────────────────────
EXISTING_BODY=$(gh pr view "$PR" --json body -q '.body // ""')
MARKER="<!-- pr-summarise -->"
if [[ -n "$EXISTING_BODY" && "$EXISTING_BODY" != *"$MARKER"* ]]; then
echo "PR #$PR already has a human-written description. Skipping." >&2
echo ""
echo "$EXISTING_BODY"
exit 0
fi
# ── Fetch diff ────────────────────────────────────────────────────────────────
echo "Fetching diff for PR #$PR..."
FULL_DIFF=$(gh pr diff "$PR" --patch)
DIFF="${FULL_DIFF:0:$MAX_DIFF_CHARS}"
if [[ -z "$DIFF" ]]; then
echo "Error: no diff found for PR #$PR." >&2
exit 1
fi
# ── Call GitHub Models ────────────────────────────────────────────────────────
echo "Generating summary via GitHub Models ($MODEL)..."
RESPONSE=$(curl -sS -L "$ENDPOINT" \
-H "Authorization: Bearer $(gh auth token)" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg model "$MODEL" \
--arg diff "$DIFF" \
'{
model: $model,
temperature: 0.2,
max_tokens: 500,
messages: [{
role: "user",
content:
"Write a concise GitHub PR description in Markdown for this diff.\n" +
"Format:\n" +
"1) One short summary paragraph.\n" +
"2) A \"## Changes\" section with bullet points.\n" +
"3) A \"## Notes for reviewers\" section (optional, only if useful).\n" +
"Output only Markdown, nothing else.\n\n" + $diff
}]
}')")
SUMMARY=$(echo "$RESPONSE" | jq -r '.choices[0].message.content')
if [[ -z "$SUMMARY" || "$SUMMARY" == "null" ]]; then
echo "Error: empty response from GitHub Models. Raw response:" >&2
echo "$RESPONSE" >&2
exit 1
fi
# ── Compose final body ────────────────────────────────────────────────────────
FINAL_BODY="${SUMMARY}"$'\n\n'"${MARKER}"
# ── Review and confirm ────────────────────────────────────────────────────────
echo ""
echo "──── Generated description ────────────────────────────────────────────────"
echo "$FINAL_BODY"
echo "───────────────────────────────────────────────────────────────────────────"
echo ""
read -r -p "Apply this description to PR #$PR? [y/N] " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
gh pr edit "$PR" --body "$FINAL_BODY"
echo "PR #$PR description updated."
else
echo "Aborted. No changes made."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment