Skip to content

Instantly share code, notes, and snippets.

@chrismytton
Last active October 9, 2025 18:31
Show Gist options
  • Select an option

  • Save chrismytton/d7780ea9706a7fff41e9a0645217755e to your computer and use it in GitHub Desktop.

Select an option

Save chrismytton/d7780ea9706a7fff41e9a0645217755e to your computer and use it in GitHub Desktop.
Get a list of pull requests created by the authenticated user for a given year
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests",
# ]
# ///
import requests
from datetime import datetime
import os
from typing import List, Dict
import argparse
import subprocess
import shutil
from io import StringIO
def fetch_prs(github_token: str, username: str, year: int, org: str | None = None) -> List[Dict]:
"""
Fetch all pull requests created by a user in a specific year across all repositories.
Args:
github_token (str): GitHub personal access token
username (str): GitHub username
year (int): Year to fetch PRs for
org (str | None): Optional organization to filter PRs by
Returns:
List[Dict]: List of pull request information
"""
headers = {
'Authorization': f'token {github_token}',
'Accept': 'application/vnd.github.v3+json'
}
# Search query parameters
query = f'author:{username} is:pr created:{year}-01-01..{year}-12-31'
if org:
query += f' org:{org}'
base_url = 'https://api.github.com/search/issues'
all_prs = []
page = 1
while True:
params = {
'q': query,
'per_page': 100,
'page': page
}
response = requests.get(base_url, headers=headers, params=params)
if response.status_code != 200:
raise Exception(f'API request failed: {response.status_code}\n{response.text}')
data = response.json()
items = data.get('items', [])
if not items:
break
for pr in items:
pr_info = {
'title': pr['title'],
'url': pr['html_url'],
'repo': pr['repository_url'].split('/')[-1],
'state': pr['state'],
'created_at': pr['created_at'],
'updated_at': pr['updated_at']
}
all_prs.append(pr_info)
page += 1
return all_prs
def get_configuration() -> tuple[str, str, int, str | None]:
"""
Parse command line arguments and get GitHub token from environment.
Returns:
tuple[str, str, int, str | None]: GitHub token, username, year, and optional org
"""
current_year = datetime.now().year
parser = argparse.ArgumentParser(description='Fetch GitHub PRs created by a user in a specific year')
parser.add_argument('username', help='GitHub username to fetch PRs for')
parser.add_argument('--year', type=int, default=current_year,
help=f'Year to fetch PRs for (default: {current_year})')
parser.add_argument('--org', type=str, default=None,
help='GitHub organization to filter PRs by (optional)')
args = parser.parse_args()
github_token = os.getenv('GITHUB_TOKEN')
if not github_token:
raise ValueError("Please set the GITHUB_TOKEN environment variable")
return github_token, args.username, args.year, args.org
def sort_prs_by_date(prs: List[Dict]) -> List[Dict]:
"""
Sort pull requests by creation date.
Args:
prs (List[Dict]): List of pull requests
Returns:
List[Dict]: Sorted list of pull requests
"""
return sorted(prs, key=lambda x: x['created_at'])
def format_prs_markdown(prs: List[Dict], username: str, year: int, org: str | None = None) -> str:
"""
Format pull requests as markdown string.
Args:
prs (List[Dict]): List of pull requests
username (str): GitHub username
year (int): Year of the PRs
org (str | None): Optional organization filter
Returns:
str: Markdown formatted string
"""
output = StringIO()
header = f"# Pull Requests by {username} in {year}"
if org:
header += f" (Organization: {org})"
output.write(f"{header}\n\n")
output.write(f"Total PRs: {len(prs)}\n\n")
for pr in prs:
created_date = datetime.fromisoformat(pr['created_at'].replace('Z', '+00:00')).strftime('%Y-%m-%d')
output.write(f"### {pr['title']}\n")
output.write(f"- **Repository:** {pr['repo']}\n")
output.write(f"- **Status:** {pr['state']}\n")
output.write(f"- **Created:** {created_date}\n")
output.write(f"- **URL:** {pr['url']}\n")
output.write("\n")
return output.getvalue()
def display_output(content: str) -> None:
"""
Display content, piping through glow if available.
Args:
content (str): Content to display
"""
# Check if glow is installed
if shutil.which('glow'):
try:
# Pipe through glow with pager
process = subprocess.Popen(
['glow', '-p'],
stdin=subprocess.PIPE,
text=True
)
process.communicate(input=content)
except Exception:
# If glow fails, fall back to regular print
print(content)
else:
# Glow not installed, print normally
print(content)
def main():
try:
github_token, username, year, org = get_configuration()
prs = fetch_prs(github_token, username, year, org)
sorted_prs = sort_prs_by_date(prs)
markdown_output = format_prs_markdown(sorted_prs, username, year, org)
display_output(markdown_output)
except Exception as e:
print(f"Error: {str(e)}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment