Skip to content

Instantly share code, notes, and snippets.

@erichsend
Last active March 17, 2023 03:29
Show Gist options
  • Save erichsend/a05db1bb1c46be45889cff79f909bf79 to your computer and use it in GitHub Desktop.
Save erichsend/a05db1bb1c46be45889cff79f909bf79 to your computer and use it in GitHub Desktop.
Jimux
# Reset
Color_Off='\033[0m' # Text Reset
# Regular Colors
Black='\033[0;30m' # Black
Red='\033[0;31m' # Red
Green='\033[0;32m' # Green
Yellow='\033[0;33m' # Yellow
Blue='\033[0;34m' # Blue
Purple='\033[0;35m' # Purple
Cyan='\033[0;36m' # Cyan
White='\033[0;37m' # White
# Bold
BBlack='\033[1;30m' # Black
BRed='\033[1;31m' # Red
BGreen='\033[1;32m' # Green
BYellow='\033[1;33m' # Yellow
BBlue='\033[1;34m' # Blue
BPurple='\033[1;35m' # Purple
BCyan='\033[1;36m' # Cyan
BWhite='\033[1;37m' # White
# Underline
UBlack='\033[4;30m' # Black
URed='\033[4;31m' # Red
UGreen='\033[4;32m' # Green
UYellow='\033[4;33m' # Yellow
UBlue='\033[4;34m' # Blue
UPurple='\033[4;35m' # Purple
UCyan='\033[4;36m' # Cyan
UWhite='\033[4;37m' # White
# Background
On_Black='\033[40m' # Black
On_Red='\033[41m' # Red
On_Green='\033[42m' # Green
On_Yellow='\033[43m' # Yellow
On_Blue='\033[44m' # Blue
On_Purple='\033[45m' # Purple
On_Cyan='\033[46m' # Cyan
On_White='\033[47m' # White
# High Intensity
IBlack='\033[0;90m' # Black
IRed='\033[0;91m' # Red
IGreen='\033[0;92m' # Green
IYellow='\033[0;93m' # Yellow
IBlue='\033[0;94m' # Blue
IPurple='\033[0;95m' # Purple
ICyan='\033[0;96m' # Cyan
IWhite='\033[0;97m' # White
# Bold High Intensity
BIBlack='\033[1;90m' # Black
BIRed='\033[1;91m' # Red
BIGreen='\033[1;92m' # Green
BIYellow='\033[1;93m' # Yellow
BIBlue='\033[1;94m' # Blue
BIPurple='\033[1;95m' # Purple
BICyan='\033[1;96m' # Cyan
BIWhite='\033[1;97m' # White
# High Intensity backgrounds
On_IBlack='\033[0;100m' # Black
On_IRed='\033[0;101m' # Red
On_IGreen='\033[0;102m' # Green
On_IYellow='\033[0;103m' # Yellow
On_IBlue='\033[0;104m' # Blue
On_IPurple='\033[0;105m' # Purple
On_ICyan='\033[0;106m' # Cyan
On_IWhite='\033[0;107m' # White
# This file goes in ~/.config/jimux/jimux.conf. Remove this line and adjust the filters
"To be Triaged - No Component"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND component is EMPTY AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"Admin/Billing - Prioritization Required"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND (labels not in (prioritize,deprioritize) OR labels is EMPTY) AND component in (billing-provisioning,admin-cx-tool) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"Admin/Billing - Refinement Required"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND labels not in (deprioritize) AND labels in (needs-refinement) AND component in (billing-provisioning,admin-cx-tool) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"Admin/Billing - Planning Required"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND labels in (prioritize) AND component in (billing-provisioning,admin-cx-tool) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"Service Hub/Runtime Manager - Prioritization Required"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND (labels not in (prioritize,deprioritize) OR labels is EMPTY) AND component in (service-hub,runtime-manager) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"Service Hub/Runtime Manager - Refinement Required"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND labels not in (deprioritize) AND labels in (needs-refinement) AND component in (service-hub,runtime-manager) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"Service Hub/Runtime Manager - Planning Required"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND labels in (prioritize) AND component in (service-hub,runtime-manager) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"Konnect Backend - Prioritization Required"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND (labels not in (prioritize,deprioritize) OR labels is EMPTY) AND component in (konnect-backend) AND component not in (ng-service-hub, runtime-manager, service-hub, billing-provisioning, admin-cx-tool) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"Konnect Backend - Refinement Required"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND labels not in (deprioritize) AND labels in (needs-refinement) AND component in (konnect-backend) AND component not in (ng-service-hub, runtime-manager, service-hub, billing-provisioning, admin-cx-tool) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"Konnect Backend - Planning Required"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND labels in (prioritize) AND component in (konnect-backend) AND component not in (ng-service-hub, runtime-manager, service-hub, billing-provisioning, admin-cx-tool) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
"All Depriotized"|"type in standardIssueTypes() AND type != Epic AND statusCategory != Done AND labels in (deprioritize) AND component in (admin-cx-tool,billing-provisioning,konnect-backend,service-hub,runtime-manager) AND project = KHCP AND (sprint not in openSprints() OR sprint is empty)"
#!/bin/zsh
JIMUX_DIR="$XDG_CONFIG_HOME/jimux"
LIST_FILE_BASE="$JIMUX_DIR/jimux-list"
LOG_FILE_BASE="$JIMUX_DIR/jimux-log"
JIMUX_CONFIG_FILE="$JIMUX_DIR/jimux.conf"
JIMUX_SPRINT_FILE="$JIMUX_DIR/sprints.out"
JIRPL_USAGE=$(cat <<-END
# Quick-Change Components (Add)
(A)dmin-cx-tool (B)illing-provisioning
(R)untime-manager (S)ervice-hub
(U)onnect-ui (Q)sdet
(G)ng-service-hub
# Quick-Change Labels (Add)
(K)onnect-backend
(N)eeds-refinement
(P)rioritized
(D)eprioritized
# Quick Transition
(C)lose
# Interactive Commands
(a)ssign (e)dit (o)pen
(m)ove (s)print
(v)iew (p)arent
(x) Next Issue
(?) Search History
(q) Quit
END
)
function _searchHistory() {
tmux display-popup "tail -r $LOG_FILE | fzf"
}
# Add 'S' to add to sprint. Starts new display/loop based on sprints.out
# Then set their selection and use grep -F "$f" sprints.out | jq .id
function _loadActiveSprints() {
curl --request GET \
--url 'https://konghq.atlassian.net/rest/agile/1.0/board/182/sprint?state=active' \
--header "Authorization: Basic ${JIRA_BASIC}" \
--header 'Accept: application/json' --silent | jq -c '.values[] | {id: .id, name: .name }' > $JIMUX_SPRINT_FILE
curl --request GET \
--url 'https://konghq.atlassian.net/rest/agile/1.0/board/183/sprint?state=active' \
--header "Authorization: Basic ${JIRA_BASIC}" \
--header 'Accept: application/json' --silent | jq -c '.values[] | {id: .id, name: .name }' >> $JIMUX_SPRINT_FILE
# cat $JIMUX_SPRINT_FILE | sort | uniq > $JIMUX_SPRINT_FILE
}
function _printActiveSprints() {
echo "# Quick Add to Active Sprint"
_optNum=1
while read -s line
do
echo "(${_optNum}) $(echo $line | jq .name)"
(( _optNum++ ))
done < $JIMUX_SPRINT_FILE
}
function _printStatus() {
clear
echo "${BIPurple}"
echo "Tickets Remaining: $(cat $LIST_FILE | wc -l)\n\n"
echo "${BIBlue}Coming Up...${Blue}"
sed -n '1,10p' $LIST_FILE | cut -f 1-2 | cut -c -100
echo "${BIGreen}\nJiREPL Key Bindings"
echo "${Green}" && _printActiveSprints
echo "${Green}\n$JIRPL_USAGE"
echo "\n${Color_Off}"
echo "${BICyan}Recent History..."
tail -n 10 $LOG_FILE | nl | sort -nr | cut -f 2-
}
function _startJirepl() {
tmux send -t right "q" Enter "clear" Enter \
"jirepl $LIST_FILE $LOG_FILE" Enter
tmux select-pane -t right
}
function jimux() {
mkdir -p $JIMUX_DIR
clear
_loadActiveSprints
_setSearchLoop
clear
_printStatus
tmux split-window -h -l 55%
_startJirepl
while read -sk; do
case $REPLY in
s) _printStatus ;;
h) _searchHistory ;;
y) clear && tmux select-pane -t left && _setSearchLoop && clear && _printStatus && _startJirepl;;
z) clear && tmux kill-pane -t right && _setSearchLoop && clear && _printStatus && tmux split-window -h -l 55% && _startJirepl;;
q) tmux kill-window ;;
*) echo "Try again..." ;;
esac
done
}
function _listSummary() {
echo "${BIPurple}Select a Search: ${Color_Off}\n"
for file in "$JIMUX_DIR/"*list*;do
_searchNumber="${file##*.}"
_search=$(sed -n "${_searchNumber}p" $JIMUX_CONFIG_FILE | cut -f1 -d '|')
_listFile="${LIST_FILE_BASE}.${_searchNumber}"
_timeStamp=$(date -r ${_listFile} +'%m/%d @ %H:%M')
_listSize=$(wc -l < $_listFile | xargs)
echo "${BIPurple}$(([##16]_searchNumber)): ${BICyan}${_search} ${Green}[Total Issues: ${_listSize}] ${Blue}[Last Updated: ${_timeStamp}]\n"
done
echo "${BIPurple}Or press R to Refresh All${Color_Off}\n"
}
function _setSearchLoop() {
_listSummary
_selection=""
# selection=$(cat $JIMUX_CONFIG_FILE | cut -f1 -d '|' | fzf --height 40% --reverse)
while read -sk ; do
case $REPLY in
[1-9A-F]) _selection=$(sed -n "$((16#${REPLY}))p" $JIMUX_CONFIG_FILE | cut -f1 -d '|') && break ;;
q) tmux kill-window ;;
R) _refreshLists && _listSummary ;;
*) echo "Try again..." ;;
esac
done
echo "${Cyan}Loading Jimux for >>> ${BIYellow}$_selection${Color_Off}"
_loadList $_selection
}
function _loadList() {
# determine list names
lineNum=$(grep -n $1 $JIMUX_CONFIG_FILE | cut -f1 -d ':')
LIST_FILE="${LIST_FILE_BASE}.$lineNum"
LOG_FILE="${LOG_FILE_BASE}.$lineNum"
# Trying out only refreshing using refresh all
# populate with results from jira
# query=$(grep $1 $JIMUX_CONFIG_FILE | cut -f2 -d '|')
# local _jira_cmd="jira issue list -q \"$(echo $query | xargs)\" --plain --columns key,summary,status,assignee | tail -n +2"
# (eval $_jira_cmd) > $LIST_FILE
}
# used by refereshAll, otherwise only used from jirepl on current list
function _refreshLists() {
clear
while read -s line
do
echo "${BIYellow}Updating List: $(echo $line | cut -f1 -d '|' )... ${Color_Off}"
lineNum=$(grep -n $line $JIMUX_CONFIG_FILE | cut -f1 -d ':')
touch "${LIST_FILE_BASE}.$lineNum"
query=$(echo $line | cut -f2 -d '|')
local _jira_cmd="jira issue list -q \"$(echo $query | xargs)\" --plain --columns key,summary,status,assignee | tail -n +2"
(eval $_jira_cmd) > "${LIST_FILE_BASE}.$lineNum"
echo "${Green}\t\t\tUpdated! Issues Found:$(cat ${LIST_FILE_BASE}.$lineNum | wc -l)\n\n"
done < $JIMUX_CONFIG_FILE
sleep 2
clear
}
#######
# The section below defines functions meant to be called from 'jrepl'.
# Just doing this to keep all of the tmux commands in one file.
#########
# Assumes we are already in a side-by-side jimux/jrepl split
function remoteKey() {
tmux send -t left "$1"
}
#!/bin/zsh
function _popList() {
_result=$(head -n 1 $LIST_FILE)
sed -i.bak '1d' $LIST_FILE && rm $LIST_FILE.bak
echo $_result
}
function _addToSprint() {
_selectedLine=$(sed -n "${1}p" $JIMUX_SPRINT_FILE)
echo "Adding to Sprint $(echo $_selectedLine | jq .name)"
jira sprint add $(echo $_selectedLine | jq .id) $2
}
function _printCurrentTicket () {
_delimitedLine=$(sed -E 's/\t+/|/g' <<< $1)
echo "\n\n${BIYellow}Current Ticket:\t$(cut -f2 -d'|' <<< $_delimitedLine)"
echo "${Blue}Key:\t\t$(cut -f1 -d'|' <<< $_delimitedLine)${Color_Off}"
echo "${Blue}Status:\t\t$(cut -f3 -d'|' <<< $_delimitedLine)${Color_Off}"
echo "${Blue}Assignee:\t$(cut -f4 -d'|' <<< $_delimitedLine)\n${Color_Off}"
}
function _logChange () {
echo "$(date +'%m/%d @ %H:%M') -- $1" | tee -a ${LOG_FILE}
}
# Helper function since jira-cli has no way to get an issue parent
# Note: ${JIRA_BASIC} must be set on the environment
# JIRA_BASIC=$(echo -n david.erichsen@konghq.com:${JIRA_API_TOKEN} | base64)
function _viewParent() {
jira issue view --plain $(curl --request GET \
--url "https://konghq.atlassian.net/rest/api/3/issue/${1}" \
--header "Authorization: Basic ${JIRA_BASIC}" \
--header 'Accept: application/json' --silent | jq -r '.fields.parent.key')
}
function jirepl() {
clear
LIST_FILE=$1
LOG_FILE=$2
_line=$(_popList)
key=$(cut -f 1 <<< $_line)
_printCurrentTicket $_line
while echo "${BWhite}Choose an action\n${Color_Off}" && read -sk; do case $REPLY in
# Jira Commands
a) _logChange "$key | Assigned" && jira issue assign $key ;;
e) _logChange "$key | Edited" && jira issue edit $key ;;
m) _logChange "$key | Moved" && jira issue move $key ;;
o) echo "Opening Issue...\n\n\n" && jira open $key ;;
p) echo "Fetching Parent...\n\n\n" && _viewParent $key ;;
v) echo "Fetching Issue...\n\n\n" && jira issue view $key --plain ;;
# Quick-Change Commands
# Consider making the component add be a function, and having it remove other components.
# Consider adding to a 'history' array to display on next issue
A) _logChange "$key | Adding Component: admin-cx-tool" && jira issue edit $key -Cadmin-cx-tool --no-input ;;
B) _logChange "$key | Adding Component: billing-provisioning" && jira issue edit $key -Cbilling-provisioning --no-input ;;
C) _logChange "$key | Closing Issue" && jira issue move $key "Resolved" ;;
D) _logChange "$key | Adding Label: deprioritized" && jira issue edit $key -ldeprioritize --no-input ;;
G) _logChange "$key | Adding Component: ng-service-hub" && jira issue edit $key -Cng-service-hub --no-input ;;
K) _logChange "$key | Adding Component: konnect-backend" && jira issue edit $key -Ckonnect-backend --no-input ;;
N) _logChange "$key | Adding Label: needs-refinement" && jira issue edit $key -lneeds-refinement --no-input ;;
P) _logChange "$key | Adding Label: prioritized" && jira issue edit $key -lprioritize --no-input ;;
Q) _logChange "$key | Adding Component: sdet" && jira issue edit $key -Csdet --no-input ;;
R) _logChange "$key | Adding Component: runtime-manager" && jira issue edit $key -Cruntime-manager --no-input ;;
S) _logChange "$key | Adding Component: service-hub" && jira issue edit $key -Cservice-hub --no-input ;;
U) _logChange "$key | Adding Component: konnect-ui" && jira issue edit $key -Ckonnect-ui --no-input ;;
[0-9]) _addToSprint $REPLY $key ;;
# TMUX Commands
x)
_line=$(_popList)
key=$(cut -f 1 <<< $_line)
clear
_printCurrentTicket $_line
remoteKey "s"
;;
\?)
echo "Displaying History...\n\n\n"
remoteKey "h" ;;
z) remoteKey "z" ;;
q) remoteKey "q" ;;
*) echo "Try again..." ;;
esac
done
}
# add somewhere in tmux.conf
bind J new-window \; send "jimux" Enter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment