#!/usr/bin/bash
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
# Author: Dusty Mabe
# Note this script uses the `bugzilla` CLI to interact with Red Hat's
# bugzilla instance. First install it and login before proceeding:
#
# - dnf install /usr/bin/bugzilla
# - bugzilla login
#
# In order to use it:
# - `./bz-sprint-bugs.sh show` will show bugs assigned to you
# - `./bz-sprint-bugs.sh update` will modify bugs with keyword/comment
# Guidance from the "Every Bug, Every Sprint" email:
#
# Literally every single bug every single sprint must be reviewed by the team.
# The team must leave a comment every sprint if a bug isn’t resolved.
# The team must add the keyword ‘UpcomingSprint’ if a bug isn’t resolved.
# We don’t have to fix every bug every sprint but we must look at them.
# If we have too many bugs, re-evaluate team priorities.
# At the beginning of every sprint, ‘UpcomingSprint’ will be removed and teams repeat
#
# For me I'll use personal tags to indicate what state my bugs are in.
# Personal tags in bugzilla are only visible to you as an individual and
# can be used for whatever you like. In this case I'm using them to denote
# the state of the bug in order to customize the comment. The two I recognize
# at this point are:
#
# - 'waiting_needinfo' - waiting on someone else
# - 'waiting_assignee' - waiting on me to schedule/do the work
# - 'waiting_workinfo' - in progress, but won't be completed this sprint
# Set the comments we want associated with each state.
WAITING_NEEDINFO_COMMENT="This bug needs more information. It is not scheduled to be worked on in the current sprint."
WAITING_ASSIGNEE_COMMENT="This bug has not been selected for work in the current sprint."
WAITING_WORKINFO_COMMENT="This is being worked on, but is currently awaiting more investigation or more information and won't be completed this sprint."
# Set some variables used to filter down the returned bugs
ASSIGNEE='dustymabe@redhat.com'
STATUS='NEW,ASSIGNED'
PRODUCT='OpenShift Container Platform'
COMPONENT='RHCOS'
# Function that will detect bug IDs in text and
# convert them into terminal hyperlinks
# see https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#quick-example
addlinks() {
sed -E -e 's|#([0-9]+)|\\e]8;;https://bugzilla.redhat.com/show_bug.cgi?id=\1\\e\\\\#\1\\e]8;;\\e\\\\|g' -e 's|$|\\n|' | \
tr -d '\n'
}
# Go through and set 'UpcomingSprint' label on bugs that are
# in a known state (i.e., have the personal tags mentioned above).
# After adding the 'UpcomingSprint' label to any bugs then print
# out the remaining bugs, which represent what you're working on
# this sprint.
main() {
# Build up a common query command assigned to this user. Use an
# array since $PRODUCT has spaces in it. See
# http://mywiki.wooledge.org/BashFAQ/050#I.27m_constructing_a_command_based_on_information_that_is_only_known_at_run_time
common_query_cmd=(bugzilla --ensure-logged-in query --product "$PRODUCT" \
--component=$COMPONENT --assigned_to=$ASSIGNEE --status=$STATUS)
if [ "$1" == 'show' ]; then
echo -en $("${common_query_cmd[@]}" | addlinks)
exit 0
fi
if [ "$1" != 'update' ]; then
echo "Must provide 'show' or 'update' as an argument" 1>&2
exit 1
fi
# Build up a query url for bugs without the `UpcomingSprint` keyword.
# Here we need to use a custom query URL because the bugzilla CLI doesn't
# have the ability to do a negative search on a tag. The --from-url is a
# catchall for complicated queries.
no_upcomingsprint_keyword_query="https://bugzilla.redhat.com/buglist.cgi?"
no_upcomingsprint_keyword_query+="&bug_status=${STATUS//,/&bug_status=}"
no_upcomingsprint_keyword_query+="&component=${COMPONENT}"
no_upcomingsprint_keyword_query+="&email1=${ASSIGNEE//@/%40}&emailassigned_to1=1&emailtype1=substring"
no_upcomingsprint_keyword_query+='&f1=tag&keywords=UpcomingSprint%2C%20&keywords_type=nowords&list_id=11131214&o1=nowords'
no_upcomingsprint_keyword_query+="&product=${PRODUCT// /%20}"
# Grab the list of bugs to operate on
declare -A bugs
for bug in $(bugzilla --ensure-logged-in query --from-url "${no_upcomingsprint_keyword_query}" --ids); do
bugs[$bug]=1
done
# Query for my bugs that are waiting on info and add comment/keyword
for bug in $("${common_query_cmd[@]}" --ids --tag='waiting_needinfo'); do
# Only act if the bug doesn't have the UpcomingSprint keyword already
if [ "${bugs[$bug]}" == "1" ]; then
echo -en $(echo "Updating bug #${bug}" | addlinks)
bugzilla --ensure-logged-in modify --keywords=UpcomingSprint \
--comment "${WAITING_NEEDINFO_COMMENT}" $bug
fi
done
# Query for my bugs that are waiting on me and add comment/keyword
for bug in $("${common_query_cmd[@]}" --ids --tag='waiting_assignee'); do
# Only act if the bug doesn't have the UpcomingSprint keyword already
if [ "${bugs[$bug]}" == "1" ]; then
echo -en $(echo "Updating bug #${bug}" | addlinks)
bugzilla --ensure-logged-in modify --keywords=UpcomingSprint \
--comment "${WAITING_ASSIGNEE_COMMENT}" $bug
fi
done
# Query for my bugs that are in progress but need info and add comment/keyword
for bug in $("${common_query_cmd[@]}" --ids --tag='waiting_workinfo'); do
# Only act if the bug doesn't have the UpcomingSprint keyword already
if [ "${bugs[$bug]}" == "1" ]; then
echo -en $(echo "Updating bug #${bug}" | addlinks)
bugzilla --ensure-logged-in modify --keywords=UpcomingSprint \
--comment "${WAITING_WORKINFO_COMMENT}" $bug
fi
done
# Print out what bugs are left so the user can analyze them
remaining_bugs="$(bugzilla --ensure-logged-in query --from-url ${no_upcomingsprint_keyword_query})"
if [ -z "${remaining_bugs}" ]; then
echo "All bugs now have the UpcomingSprint keyword."
else
output=$(cat <