From 9339fec374e04029beb927c1de1f69bd6ba23e7d Mon Sep 17 00:00:00 2001 From: edfig Date: Fri, 17 Oct 2025 00:48:09 +0200 Subject: [PATCH] Add prch.sh --- prch.sh | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 prch.sh diff --git a/prch.sh b/prch.sh new file mode 100644 index 0000000..7ba5412 --- /dev/null +++ b/prch.sh @@ -0,0 +1,219 @@ +#!/bin/bash + +# Pretty display for GitHub PR checks using gum +# Usage: ./gh-pr-checks-pretty.sh [--watch] + +set -euo pipefail + +# Parse arguments +WATCH_MODE=false +PR_NUMBER="" + +while [[ $# -gt 0 ]]; do + case $1 in + --watch|-w) + WATCH_MODE=true + shift + ;; + *) + PR_NUMBER=$1 + shift + ;; + esac +done + +# Check if PR number is provided +if [ -z "$PR_NUMBER" ]; then + echo "Usage: $0 [--watch]" + exit 1 +fi + +# Check if gum is installed +if ! command -v gum &> /dev/null; then + echo "Error: gum is not installed. Install it from https://github.com/charmbracelet/gum" + exit 1 +fi + +# Check if gh is installed +if ! command -v gh &> /dev/null; then + echo "Error: gh (GitHub CLI) is not installed." + exit 1 +fi + +# Function to display checks +display_checks() { + # Get PR details including reviews, comments, and state + PR_INFO=$(gh pr view "$PR_NUMBER" --json number,title,url,state,isDraft,reviews,comments) + PR_TITLE=$(echo "$PR_INFO" | jq -r '.title') + PR_URL=$(echo "$PR_INFO" | jq -r '.url') + PR_STATE=$(echo "$PR_INFO" | jq -r '.state') + PR_DRAFT=$(echo "$PR_INFO" | jq -r '.isDraft') + + # Count comments + COMMENT_COUNT=$(echo "$PR_INFO" | jq '.comments | length') + + # Get approval status + APPROVED_COUNT=$(echo "$PR_INFO" | jq '[.reviews[] | select(.state == "APPROVED")] | length') + CHANGES_REQUESTED=$(echo "$PR_INFO" | jq '[.reviews[] | select(.state == "CHANGES_REQUESTED")] | length') + + # Determine PR status string + if [ "$PR_DRAFT" = "true" ]; then + PR_STATUS="Draft" + STATUS_COLOR="8" # Gray + elif [ "$PR_STATE" = "MERGED" ]; then + PR_STATUS="Merged" + STATUS_COLOR="13" # Purple + elif [ "$PR_STATE" = "CLOSED" ]; then + PR_STATUS="Closed" + STATUS_COLOR="9" # Red + else + PR_STATUS="Open" + STATUS_COLOR="10" # Green + fi + + # Determine approval string + if [ "$CHANGES_REQUESTED" -gt 0 ]; then + APPROVAL_STATUS="Changes requested" + APPROVAL_COLOR="9" # Red + elif [ "$APPROVED_COUNT" -gt 0 ]; then + APPROVAL_STATUS="✓ Approved ($APPROVED_COUNT)" + APPROVAL_COLOR="10" # Green + else + APPROVAL_STATUS="No reviews" + APPROVAL_COLOR="8" # Gray + fi + + # Get checks with full details + CHECKS_JSON=$(gh pr checks "$PR_NUMBER" --json bucket,name,link,completedAt,description,state) + + # Count all checks + TOTAL_ALL=$(echo "$CHECKS_JSON" | jq '. | length') + SUCCESSFUL_ALL=$(echo "$CHECKS_JSON" | jq '[.[] | select(.state == "SUCCESS")] | length') + FAILING_ALL=$(echo "$CHECKS_JSON" | jq '[.[] | select(.state == "FAILURE")] | length') + PENDING_ALL=$(echo "$CHECKS_JSON" | jq '[.[] | select(.state == "PENDING" or .state == "IN_PROGRESS")] | length') + + # Filter checks: only include Terraform results, failures, or ongoing checks + FILTERED_JSON=$(echo "$CHECKS_JSON" | jq '[.[] | select( + (.description | contains("Run not triggered") | not) and + ( + (.description | contains("Terraform plan:")) or + (.state == "FAILURE") or + (.state == "PENDING") or + (.state == "IN_PROGRESS") + ) + )]') + + # Count filtered checks + TOTAL=$(echo "$FILTERED_JSON" | jq '. | length') + HIDDEN=$((SUCCESSFUL_ALL - TOTAL)) + + # Clear screen in watch mode + if [ "$WATCH_MODE" = true ]; then + clear + fi + + # Display header + gum style \ + --border double \ + --border-foreground 212 \ + --padding "1 2" \ + --margin "1 0" \ + --align center \ + "#$PR_NUMBER | $PR_TITLE" "$PR_URL" + + # Display PR status, approval, and comments + echo "" + gum style --foreground "$STATUS_COLOR" --bold "Status: $PR_STATUS" | tr '\n' ' ' + echo -n " | " + gum style --foreground "$APPROVAL_COLOR" "Reviews: $APPROVAL_STATUS" | tr '\n' ' ' + echo -n " | " + gum style --foreground 12 "Comments: $COMMENT_COUNT" + + # Display summary statistics + echo "" + if [ "$TOTAL" -eq 0 ]; then + gum style --foreground 8 "Total: $TOTAL_ALL | Success: $SUCCESSFUL_ALL | Failed: $FAILING_ALL | Pending: $PENDING_ALL" + echo "" + gum style \ + --foreground 10 \ + --bold \ + "✓ All checks passed" + + if [ "$WATCH_MODE" = false ]; then + exit 0 + else + return 0 + fi + else + gum style --foreground 8 "Total: $TOTAL_ALL | Success: $SUCCESSFUL_ALL ($HIDDEN hidden) | Failed: $FAILING_ALL | Pending: $PENDING_ALL" + fi + + echo "" + + # Prepare table data + TABLE_DATA=$(echo "$FILTERED_JSON" | jq -r ' + [" STATUS", "NAME", "DESCRIPTION", "URL"], + [" ──────", "────", "───────────", "───"], + (.[] | [ + " " + (if .state == "SUCCESS" then "✓" + elif .state == "FAILURE" then "✗" + elif .state == "PENDING" or .state == "IN_PROGRESS" then "⏳" + else "○" end), + # Shorten name - extract workspace from Terraform Cloud checks + (if .name | startswith("Terraform Cloud/") then + "TF - " + (.name | split("/") | last) + else + .name + end), + # Format description - compact Terraform plan output + (if .description and (.description | contains("Terraform plan:")) then + (.description | + gsub("Terraform plan: "; "") | + gsub(" to add"; "") | + gsub(" to change"; "") | + gsub(" to destroy\\."; "") | + gsub(", "; " ") | + split(" ") | + "🟢+" + .[0] + " 🛠~" + .[1] + " 🗑-" + .[2]) + else + (.description // "No description" | + if (. | length) > 50 then .[0:47] + "..." else . end) + end), + # Full URL + (.link // "") + ]) | @tsv + ' | column -t -s $'\t') + + # Display table with gum + echo "$TABLE_DATA" | gum format + + # Show timestamp in watch mode + if [ "$WATCH_MODE" = true ]; then + echo "" + gum style --foreground 8 --italic "Last updated: $(date '+%Y-%m-%d %H:%M:%S')" + fi +} + +# Run in watch mode or single run +if [ "$WATCH_MODE" = true ]; then + # Trap Ctrl+C to exit gracefully + trap 'echo ""; echo "Watch mode stopped."; exit 0' INT + + while true; do + display_checks + + # Check if all checks are complete + CHECKS_JSON=$(gh pr checks "$PR_NUMBER" --json state) + PENDING_COUNT=$(echo "$CHECKS_JSON" | jq '[.[] | select(.state == "PENDING" or .state == "IN_PROGRESS")] | length') + + if [ "$PENDING_COUNT" -eq 0 ]; then + echo "" + gum style --foreground 10 --bold "All checks complete!" + break + fi + + sleep 10 + done +else + display_checks +fi