Skip to content

Instantly share code, notes, and snippets.

@netj
Last active April 22, 2023 18:50
Show Gist options
  • Save netj/082aa1d431db0e240eb492f0a3f16873 to your computer and use it in GitHub Desktop.
Save netj/082aa1d431db0e240eb492f0a3f16873 to your computer and use it in GitHub Desktop.
macOS xbar menu item for GitHub Pull Requests/Issues
#!/usr/bin/env bash
# macOS xbar menu item for GitHub Pull Requests/Issues
#
# <xbar.title>GitHub assigned Pull Requests and Issues</xbar.title>
# <xbar.version>v2023.16.0</xbar.version>
# <xbar.author>Jaeho Shin</xbar.author>
# <xbar.author.github>netj</xbar.author.github>
# <xbar.desc>Quick handle for showing number of assigned Github Pull Requests / Issues and giving access to the most recent ones</xbar.desc>
# <xbar.image>https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png</xbar.image>
# <xbar.abouturl>https://gist.github.com/netj/082aa1d431db0e240eb492f0a3f16873</xbar.abouturl>
# (cf. https://github.com/matryer/xbar-plugins/blob/main/CONTRIBUTING.md#metadata)
set -euo pipefail
# find GitHub instance hostname from the filename
basenameWithInterval=$(basename "$0" .sh)
basename=${basenameWithInterval%.*}
export githubHostname=${basename#*=}
# optional filename prefix ending with an = can define menubar icon/label (e.g.: 🎨=github.com.5m.sh)
icon=${basename%%$githubHostname}; icon=${icon%=}; : ${icon:=$githubHostname}
export PATH=/opt/homebrew/bin:"$PATH" # XXX for jq from Homebrew
case $githubHostname in
github.com|api.github.*) # public Github or API hostname for GHE
githubHostname=${githubHostname#api.}
githubUrlApi=https://api.$githubHostname
;;
*) # Github Enterprise
githubUrlApi=https://$githubHostname/api/v3
esac
githubUrlBase=https://$githubHostname
export githubUrlBase githubHostname githubUrlApi
githubApiCall() { local urlPath=$1; shift; curl -nfgsSL "$githubUrlApi$urlPath" "$@"; }
search_total_count() { jq -s '[.[].total_count] | add'; }
search2bitbar_menu_items() {
# TODO parameterize limit
limit=10 \
jq -s '
([.[].items[] | select(.archived | not)] | sort_by(.updated_at) | reverse | .[:(env.limit | tonumber)][] |
"\(.repository_url | ltrimstr("\(env.githubUrlApi)/repos/"))#\(.number) \(.title) | href=\(.html_url | @sh) terminal=false"
)' -r
}
XBAR_MENU() {
githubUser=$( githubApiCall "/user" | jq .login -r)
prs_assigned=$( githubApiCall "/search/issues?sort=updated&order=desc&q=archived:false+state:open+is:pr+assignee:$githubUser")
prs_authored=$( githubApiCall "/search/issues?sort=updated&order=desc&q=archived:false+state:open+is:pr+author:$githubUser")
prs_mentioning=$( githubApiCall "/search/issues?sort=updated&order=desc&q=archived:false+state:open+is:pr+mentions:$githubUser")
prs_requesting_review=$( githubApiCall "/search/issues?sort=updated&order=desc&q=archived:false+state:open+is:pr+review-requested:$githubUser")
prs="$prs_assigned $prs_authored $prs_mentioning $prs_requesting_review"
issues_assigned=$( githubApiCall "/search/issues?sort=updated&order=desc&q=archived:false+state:open+is:issue+assignee:$githubUser")
issues_authored=$( githubApiCall "/search/issues?sort=updated&order=desc&q=archived:false+state:open+is:issue+author:$githubUser")
issues_mentioning=$( githubApiCall "/search/issues?sort=updated&order=desc&q=archived:false+state:open+is:issue+mentions:$githubUser")
issues="$issues_assigned $issues_authored $issues_mentioning"
num_prs_assigned=$(search_total_count <<<"$prs_assigned")
num_issues_assigned=$(search_total_count <<<"$issues_assigned")
num_prs=$(search_total_count <<<"$prs")
num_issues=$(search_total_count <<<"$issues")
###############################################################################
# render xbar menu and menu items
echo -n "$icon"
echo "$(($num_prs_assigned + $num_issues_assigned))"
echo "---"
echo "$githubUser@$githubHostname | href=$githubUrlBase/$githubUser"
echo "$num_prs open pull requests"
echo "$num_issues open issues"
start_bitbar_menu_section() {
local title=$1; shift
echo "---"
echo "$title | color=#666666 $*"
}
start_bitbar_menu_section "$num_prs_assigned open PRs assigned to you" "href=$githubUrlBase/pulls/assigned"
search2bitbar_menu_items <<<"$prs_assigned"
start_bitbar_menu_section "$(search_total_count <<<"$issues_assigned") open issues assigned to you" "href=$githubUrlBase/issues/assigned"
search2bitbar_menu_items <<<"$issues_assigned"
start_bitbar_menu_section "$(search_total_count <<<"$prs_requesting_review") open PRs requested your review" "href=$githubUrlBase/pulls/review-requested"
search2bitbar_menu_items <<<"$prs_requesting_review"
start_bitbar_menu_section "$(search_total_count <<<"$prs_authored") open PRs authored by you" "href=$githubUrlBase/pulls"
search2bitbar_menu_items <<<"$prs_authored"
# TODO fold some items into submenu to give more focus to assigned+review-requested ones?
start_bitbar_menu_section "$(search_total_count <<<"$issues_authored") open issues authored by you" "href=$githubUrlBase/issues"
search2bitbar_menu_items <<<"$issues_authored"
start_bitbar_menu_section "$(search_total_count <<<"$prs_mentioning") open PRs mention you" "href=$githubUrlBase/pulls/mentioned"
search2bitbar_menu_items <<<"$prs_mentioning"
start_bitbar_menu_section "$(search_total_count <<<"$issues_mentioning") open issues mention you" "href=$githubUrlBase/issues/mentioned"
search2bitbar_menu_items <<<"$issues_mentioning"
}
[[ $# -gt 0 ]] || set -- XBAR_MENU
"$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment