Last active
August 19, 2025 04:35
-
-
Save ezynda3/f47c92049256d2633d20cded915e3416 to your computer and use it in GitHub Desktop.
Fetch all comments from pr and user
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Script to fetch and display PR comments from GitHub | |
# Automatically detects repository from current git directory | |
# Usage: ./fetch_pr_comments.sh <PR_NUMBER> [USERNAME] | |
# Color codes for better output | |
RED='\033[0;31m' | |
GREEN='\033[0;32m' | |
YELLOW='\033[1;33m' | |
BLUE='\033[0;34m' | |
CYAN='\033[0;36m' | |
NC='\033[0m' # No Color | |
BOLD='\033[1m' | |
# Function to display usage | |
show_usage() { | |
echo "Usage: $0 <PR_NUMBER> [USERNAME]" | |
echo "" | |
echo "This script must be run from within a git repository with a GitHub origin remote." | |
echo "" | |
echo "Arguments:" | |
echo " PR_NUMBER - Required. The pull request number" | |
echo " USERNAME - Optional. Filter comments by specific user" | |
echo "" | |
echo "Examples:" | |
echo " $0 123 # Show all comments from PR #123" | |
echo " $0 123 Bob # Show only comments from user Bob in PR #123" | |
exit 1 | |
} | |
# Function to check if required commands are available | |
check_dependencies() { | |
if ! command -v git &> /dev/null; then | |
echo -e "${RED}Error: git is not installed${NC}" | |
exit 1 | |
fi | |
if ! command -v gh &> /dev/null; then | |
echo -e "${RED}Error: GitHub CLI (gh) is not installed${NC}" | |
echo "Please install it from: https://cli.github.com/" | |
exit 1 | |
fi | |
if ! command -v jq &> /dev/null; then | |
echo -e "${RED}Error: jq is not installed${NC}" | |
echo "Please install it using your package manager" | |
exit 1 | |
fi | |
# Check if gh is authenticated | |
if ! gh auth status &> /dev/null; then | |
echo -e "${RED}Error: GitHub CLI is not authenticated${NC}" | |
echo "Please run: gh auth login" | |
exit 1 | |
fi | |
} | |
# Function to extract repo info from git remote | |
get_repo_info() { | |
# Check if we're in a git repository | |
if ! git rev-parse --git-dir > /dev/null 2>&1; then | |
echo -e "${RED}Error: Not in a git repository${NC}" | |
echo "Please run this script from within a git repository" | |
exit 1 | |
fi | |
# Get the origin remote URL | |
REMOTE_URL=$(git config --get remote.origin.url 2>/dev/null) | |
if [ -z "$REMOTE_URL" ]; then | |
echo -e "${RED}Error: No 'origin' remote found${NC}" | |
echo "Please ensure your repository has an origin remote set" | |
exit 1 | |
fi | |
# Parse the URL to extract owner and repo name | |
# Handle both HTTPS and SSH URLs | |
if [[ "$REMOTE_URL" =~ ^https://github.com/([^/]+)/([^/]+)(\.git)?$ ]]; then | |
# HTTPS format: https://github.com/owner/repo.git | |
REPO_OWNER="${BASH_REMATCH[1]}" | |
REPO_NAME="${BASH_REMATCH[2]}" | |
elif [[ "$REMOTE_URL" =~ ^[email protected]:([^/]+)/([^/]+)(\.git)?$ ]]; then | |
# SSH format: [email protected]:owner/repo.git | |
REPO_OWNER="${BASH_REMATCH[1]}" | |
REPO_NAME="${BASH_REMATCH[2]}" | |
elif [[ "$REMOTE_URL" =~ ^ssh://[email protected]/([^/]+)/([^/]+)(\.git)?$ ]]; then | |
# SSH alternative format: ssh://[email protected]/owner/repo.git | |
REPO_OWNER="${BASH_REMATCH[1]}" | |
REPO_NAME="${BASH_REMATCH[2]}" | |
else | |
echo -e "${RED}Error: Unable to parse GitHub repository from remote URL${NC}" | |
echo "Remote URL: $REMOTE_URL" | |
echo "Expected format: https://github.com/owner/repo.git or [email protected]:owner/repo.git" | |
exit 1 | |
fi | |
# Remove .git extension if present | |
REPO_NAME="${REPO_NAME%.git}" | |
echo -e "${GREEN}Repository detected: ${BOLD}${REPO_OWNER}/${REPO_NAME}${NC}" | |
} | |
# Function to display a single comment with formatting | |
display_comment() { | |
local comment="$1" | |
# Extract fields from JSON | |
local id=$(echo "$comment" | jq -r '.id') | |
local author=$(echo "$comment" | jq -r '.user.login') | |
local created=$(echo "$comment" | jq -r '.created_at') | |
local updated=$(echo "$comment" | jq -r '.updated_at') | |
local file=$(echo "$comment" | jq -r '.path') | |
local line=$(echo "$comment" | jq -r '.line // .original_line // "N/A"') | |
local position=$(echo "$comment" | jq -r '.position // "outdated"') | |
local body=$(echo "$comment" | jq -r '.body') | |
# Determine status | |
local status | |
if [ "$position" = "outdated" ]; then | |
status="${RED}Outdated${NC}" | |
else | |
status="Active" | |
fi | |
# Display formatted comment | |
echo -e "${YELLOW}═══════════════════════════════════════════════════${NC}" | |
echo -e "${GREEN}Comment ID:${NC} $id" | |
echo -e "${GREEN}Author:${NC} $author" | |
echo -e "${GREEN}Created:${NC} $created" | |
echo -e "${GREEN}Updated:${NC} $updated" | |
echo -e "${GREEN}File:${NC} ${BLUE}$file${NC}" | |
echo -e "${GREEN}Line:${NC} $line" | |
echo -e "${GREEN}Status:${NC} $status" | |
echo -e "${GREEN}Comment:${NC}" | |
echo "$body" | |
echo "" | |
} | |
# Check if at least one argument is provided | |
if [ $# -lt 1 ]; then | |
show_usage | |
fi | |
# Parse arguments | |
PR_NUMBER=$1 | |
USERNAME=$2 | |
# Validate PR number is a positive integer | |
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then | |
echo -e "${RED}Error: PR number must be a positive integer${NC}" | |
exit 1 | |
fi | |
# Check dependencies | |
check_dependencies | |
# Get repository information from git | |
get_repo_info | |
# Build the API endpoint | |
API_ENDPOINT="repos/${REPO_OWNER}/${REPO_NAME}/pulls/${PR_NUMBER}/comments" | |
# Display what we're doing | |
if [ -n "$USERNAME" ]; then | |
echo -e "${CYAN}Fetching comments from ${BOLD}${REPO_OWNER}/${REPO_NAME}${NC} PR #${PR_NUMBER} by user: ${BOLD}${USERNAME}${NC}\n" | |
else | |
echo -e "${CYAN}Fetching all comments from ${BOLD}${REPO_OWNER}/${REPO_NAME}${NC} PR #${PR_NUMBER}${NC}\n" | |
fi | |
echo -e "${YELLOW}Fetching comments...${NC}\n" | |
# Fetch all comments | |
ALL_COMMENTS=$(gh api "$API_ENDPOINT" --paginate 2>/dev/null) | |
# Check if the API call was successful | |
if [ $? -ne 0 ] || [ -z "$ALL_COMMENTS" ] || [ "$ALL_COMMENTS" = "[]" ]; then | |
# Try to get more specific error information | |
ERROR_MSG=$(gh api "$API_ENDPOINT" 2>&1) | |
if [[ "$ERROR_MSG" == *"404"* ]] || [[ "$ERROR_MSG" == *"Not Found"* ]]; then | |
echo -e "${RED}Error: PR #${PR_NUMBER} not found in ${REPO_OWNER}/${REPO_NAME}${NC}" | |
elif [[ "$ERROR_MSG" == *"401"* ]] || [[ "$ERROR_MSG" == *"403"* ]]; then | |
echo -e "${RED}Error: Access denied to ${REPO_OWNER}/${REPO_NAME}${NC}" | |
echo "Please check your GitHub permissions" | |
else | |
echo -e "${YELLOW}No comments found in PR #${PR_NUMBER}${NC}" | |
fi | |
exit 1 | |
fi | |
# Filter comments by username if provided | |
if [ -n "$USERNAME" ]; then | |
FILTERED_COMMENTS=$(echo "$ALL_COMMENTS" | jq -c ".[] | select(.user.login == \"$USERNAME\")") | |
else | |
FILTERED_COMMENTS=$(echo "$ALL_COMMENTS" | jq -c ".[]") | |
fi | |
# Check if any comments match the filter | |
if [ -z "$FILTERED_COMMENTS" ]; then | |
if [ -n "$USERNAME" ]; then | |
echo -e "${YELLOW}No comments found from user '${USERNAME}' in PR #${PR_NUMBER}${NC}" | |
else | |
echo -e "${YELLOW}No comments found in PR #${PR_NUMBER}${NC}" | |
fi | |
exit 0 | |
fi | |
# Display each comment | |
while IFS= read -r comment; do | |
display_comment "$comment" | |
done <<< "$FILTERED_COMMENTS" | |
# Display summary | |
echo -e "${YELLOW}═══════════════════════════════════════════════════${NC}" | |
if [ -n "$USERNAME" ]; then | |
COMMENT_COUNT=$(echo "$ALL_COMMENTS" | jq "[.[] | select(.user.login == \"$USERNAME\")] | length") | |
echo -e "${GREEN}Total comments by ${USERNAME}: ${BOLD}${COMMENT_COUNT}${NC}" | |
else | |
COMMENT_COUNT=$(echo "$ALL_COMMENTS" | jq ". | length") | |
echo -e "${GREEN}Total comments: ${BOLD}${COMMENT_COUNT}${NC}" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment