Skip to content

Instantly share code, notes, and snippets.

@racecarparts
Last active July 17, 2024 20:20
Show Gist options
  • Save racecarparts/6d71c38be5c3650fab4b92376630ee53 to your computer and use it in GitHub Desktop.
Save racecarparts/6d71c38be5c3650fab4b92376630ee53 to your computer and use it in GitHub Desktop.
Script and config to display a list of Github org PRs.
#!/bin/bash
# Load configuration variables from ~/.github_config
CONFIG_FILE="$HOME/.github_org.cfg"
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
else
echo "Configuration file not found: $CONFIG_FILE"
exit 1
fi
# Validate required configuration variables
if [[ -z "$GITHUB_TOKEN" || -z "$ORG_NAME" || -z "$TEAM_SLUG" || -z "$MAX_TITLE_LENGTH" || -z "$GRAPHQL_QUERY" || -z "$DATE_RANGE_START" || -z "$INTERVAL_MINUTES" ]]; then
echo "Missing required configuration variables. Please update your ~/.github_config."
exit 1
fi
# Function to convert ISO 8601 date to Unix timestamp
iso_to_unix() {
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS date command
date -j -f "%Y-%m-%dT%H:%M:%SZ" "$1" "+%s" 2>/dev/null || echo ""
else
# Linux (GNU date command)
date -d "$1" "+%s" 2>/dev/null || echo ""
fi
}
# Function to make GraphQL request
graphql_query() {
local query=$1
curl -s -H "Authorization: bearer $GITHUB_TOKEN" \
-H "Content-Type: application/json" \
-X POST \
-d "{\"query\": $query}" \
https://api.github.com/graphql
}
# Truncate title function
truncate_title() {
local title="$1"
if [ -z "$title" ]; then
echo "(No Title)"
elif [ ${#title} -gt "$MAX_TITLE_LENGTH" ]; then
echo "${title:0:$MAX_TITLE_LENGTH}..."
else
echo "$title"
fi
}
# Function to compare two dates using Unix timestamps
date_in_range() {
local created_date_unix
local date_range_start_unix
# Trim leading/trailing whitespace and convert to Unix timestamp
created_date_unix=$(iso_to_unix "$(echo "$1" | sed 's/^ *//;s/ *$//')")
date_range_start_unix=$(iso_to_unix "$DATE_RANGE_START")
if [ -z "$created_date_unix" ] || [ -z "$date_range_start_unix" ]; then
return 1 # False
fi
if [ "$created_date_unix" -gt "$date_range_start_unix" ]; then
return 0 # True
else
return 1 # False
fi
}
# Escape newlines and quotes to create a valid JSON payload
GRAPHQL_QUERY_JSON=$(echo "$GRAPHQL_QUERY" | jq -aRs .)
# Function to execute the GraphQL query and print results
fetch_pull_requests() {
local response=$(graphql_query "$GRAPHQL_QUERY_JSON")
# Clear the screen
clear
url_spacer=0
# Parse and print response (using jq and awk)
echo "Repository Title PR Link Author Created At Reviewers"
echo "-----------------------------------------------------------------------------------------------------------------------------------------------------------"
echo "$response" | jq -r '
.data.organization.team.repositories.edges[]
| .node.name as $repo
| .node.pullRequests.edges[]
| .node as $pr
| $pr.reviews.edges | map(.node.author.login) | unique | join(", ") as $reviewers
| "\($repo) |\($pr.title) |\($pr.url)|\($pr.author.login) |\($reviewers) |\($pr.createdAt) |\($pr.number)"
' | while IFS='|' read -r repo title url author reviewers created_at number; do
if date_in_range "$created_at"; then
truncated_title=$(truncate_title "$title")
# Create a hyperlink for terminals that support it
number=$(printf %-10s $number)
pr_url=$(printf "\e]8;;%s\e\\\\%s\e]8;;\e\\" "$url" "$number")
# Adjust printf formatting to match the widest expected content
printf "%-25s %-40s %-10s %-15s %-25s %-15s\n" "$repo" "$truncated_title" "$pr_url" "$author" "$created_at" "$reviewers"
fi
done
}
# Calculate refresh interval in seconds
REFRESH_INTERVAL=$((INTERVAL_MINUTES * 60))
# Continuously fetch and print pull requests at the specified interval
while true; do
fetch_pull_requests
echo
echo "Press Enter to refresh immediately."
echo "fetched: $(date '+%H:%M:%S %p')"
echo "next: $(date -v+${REFRESH_INTERVAL}S '+%H:%M:%S %p')"
read -s -r -n 1 -t "$REFRESH_INTERVAL" key
if [[ $key == $'\x0a' ]]; then # Check for the Enter key (newline)
continue # Refresh the results immediately on Enter key press
else
continue # Refresh after timeout if no key is pressed
fi
done
GITHUB_TOKEN="<gh token>"
ORG_NAME="<gh org name>"
TEAM_SLUG="<gh team name>" # depending on org this might be relevant to filter repos
MAX_TITLE_LENGTH=32
DATE_RANGE_START=$(date -v-6m '+%Y-%m-%dT%H:%M:%SZ') # For macOS (adjust accordingly)
INTERVAL_MINUTES=10 # Refresh interval in minutes
GRAPHQL_QUERY=$(cat <<EOF
{
organization(login: "$ORG_NAME") {
team(slug: "$TEAM_SLUG") {
repositories(first: 100) {
edges {
node {
name
pullRequests(states: OPEN, first: 100, orderBy: {field: CREATED_AT, direction: ASC}) {
edges {
node {
title
url
number
createdAt
author {
login
}
reviews(first: 10) {
edges {
node {
author {
login
}
}
}
}
}
}
}
}
}
}
}
}
}
EOF
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment