Last active
May 23, 2025 02:13
-
-
Save avinayak/2054c61262bebb41b1600acaaf534fe2 to your computer and use it in GitHub Desktop.
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
#!/usr/bin/env python3 | |
# <xbar.title>prs</xbar.title> | |
# <xbar.version>v1.0</xbar.version> | |
# <xbar.author>Atul Vinayak</xbar.author> | |
# <xbar.author.github>avinayak</xbar.author.github> | |
# <xbar.desc>Shows a list of merged pull requests for the current user</xbar.desc> | |
# <xbar.dependencies>bash</xbar.dependencies> | |
import subprocess | |
import json | |
from datetime import datetime, timedelta, timezone | |
def get_username(): | |
return subprocess.check_output( | |
["/opt/homebrew/bin/gh", "api", "user", "--jq", ".login"], encoding="utf-8" | |
).strip() | |
def get_last_monday_iso(): | |
today = datetime.now(timezone.utc) | |
monday = today - timedelta(days=today.weekday()) | |
return monday.strftime("%Y-%m-%dT00:00:00Z") | |
def get_one_month_ago_iso(): | |
today = datetime.now(timezone.utc) | |
one_month_ago = today - timedelta(days=30) | |
return one_month_ago.strftime("%Y-%m-%dT00:00:00Z") | |
def get_merged_prs_since_monday(username): | |
cmd = [ | |
"/opt/homebrew/bin/gh", "search", "prs", | |
"--author", username, | |
"--merged", | |
"--sort", "updated", | |
"--order", "desc", | |
"--json", "title,number,url,updatedAt,repository", | |
"--jq", f'.[] | select(.updatedAt >= "{get_last_monday_iso()}")' | |
] | |
output = subprocess.check_output(cmd, encoding="utf-8").strip() | |
if not output: | |
return [] | |
return [json.loads(line) for line in output.splitlines()] | |
def get_open_prs(username): | |
cmd = [ | |
"/opt/homebrew/bin/gh", "search", "prs", | |
"--author", username, | |
"--state", "open", | |
"--sort", "updated", | |
"--order", "desc", | |
"--json", "title,number,url,updatedAt,repository,isDraft", # Added isDraft | |
"--jq", f'.[] | select(.updatedAt >= "{get_one_month_ago_iso()}") | select(.isDraft == false)' # Added isDraft filter | |
] | |
output = subprocess.check_output(cmd, encoding="utf-8").strip() | |
if not output: | |
return [] | |
return [json.loads(line) for line in output.splitlines()] | |
def get_approved_not_merged_prs(username): | |
cmd = [ | |
"/opt/homebrew/bin/gh", "search", "prs", | |
"--author", username, | |
"--state", "open", | |
"--review", "approved", | |
"--sort", "updated", | |
"--order", "desc", | |
"--json", "title,number,url,updatedAt,repository,isDraft", | |
"--jq", f'.[] | select(.updatedAt >= "{get_one_month_ago_iso()}") | select(.isDraft == false)' # Ensure draft PRs are excluded | |
] | |
output = subprocess.check_output(cmd, encoding="utf-8").strip() | |
if not output: | |
return [] | |
return [json.loads(line) for line in output.splitlines()] | |
def get_growth_emoji(count): | |
if count <= 1: | |
return "π±" | |
elif count <= 3: | |
return "π" | |
elif count <= 5: | |
return "πΏ" | |
elif count <= 7: | |
return "πͺ΄" | |
elif count <= 9: | |
return "π΄" | |
elif count <= 11: | |
return "π²" | |
elif count <= 13: | |
return "π³" | |
elif count <= 15: | |
return "πΈ" | |
elif count <= 17: | |
return "πΊ" | |
elif count <= 19: | |
return "π»" | |
else: | |
return "π" | |
def main(): | |
try: | |
username = get_username() | |
merged_prs = get_merged_prs_since_monday(username) | |
open_prs = get_open_prs(username) | |
approved_not_merged_prs = get_approved_not_merged_prs(username) | |
growth_emoji = get_growth_emoji(len(merged_prs)) | |
print(f"{growth_emoji}{len(merged_prs)}/{len(open_prs)}/{len(approved_not_merged_prs)}") | |
print("---") | |
print(f"β Merged PRs since last Monday: {len(merged_prs)}") | |
for pr in merged_prs: | |
print(f"--{pr['title']} (#{pr['number']}) | href={pr['url']}") | |
print(f"β³ Open PRs: {len(open_prs)}") | |
for pr in open_prs: | |
print(f"--{pr['title']} (#{pr['number']}) | href={pr['url']}") | |
print(f"π Approved but not merged PRs: {len(approved_not_merged_prs)}") | |
for pr in approved_not_merged_prs: | |
print(f"--{pr['title']} (#{pr['number']}) | href={pr['url']}") | |
except Exception as e: | |
print(f"β Error: {e}") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment