How to Automate Common Jira Tasks with Go Jira Custom Commands

in all but small teams I typically recommend separate people for the separate roles [of product managment and project management]. But in every case I believe that developing strong project management skills is a big advantage for product managers – at the least your product will get to market faster, and it could make the difference between getting your product shipped at all.

–Marty Cagan, “Ebay’s Secret Weapon”


Every morning, I get the following slack message reminder:

stay on top of products slack reminder

For me, this is challenging because I work for a platform startup that is supporting many products simultaneously and where the product team takes on some of the project management responsibilities. Jira helps with this challenge, but there are a few places where it falls short, and unfortunately, these days I don’t have time to code up some custom program that talks to its API. Luckily, I stumbled upon a neat CLI for Jira.

This post walks through how I’ve been able to leverage this tool to improve my productivity. It’s for busy technical PMs and programmers who are heavy Jira users.

Problems with Jira

Before we get into how to use this jira CLI, I want to say a little about the problems I was running into with Jira.

The first problem was that removing a large number from attachments from a ticket is extremely tedious. You have to click a trash icon and a confirmation message on each attachment.

The second problem was that there was no way for us to query for epics that were in a To Do state that had child stories that were in an In Progress state. We have a board of epics that’s supposed to reflect what’s being worked on at a high-level, and not being able to easily find epics whose state needed to be updated makes it hard to see what’s actually being worked on.1

An introduction to go-jira

Installation

There’s a few jira-clis out there. go-jira is the best one I’ve found. I’ve seen the npm and python modules for jira CLIs. They don’t appear to be as well supported. It looks this go-based CLI came out of a skunkworks group at Netflix, and it’s got over 1.5k stars on github.

You can install a pre-built binary if you’re running linux or windows. If you’re on mac, you’ll have to use the go package manager:

go get gopkg.in/Netflix-Skunkworks/go-jira.v1/cmd/jira

Custom Commands

The killer feature of jira go is the ability to add custom commands for doing common Jira tasks that aren’t well-supported via the web interface. These custom commands are what allow you to solve problems like the ones I discussed above.

The commands are specified in a config.yaml file. Mine looks like this:

custom-commands:
  - name: remove-attachments
    help: removes all attachments from a given issue
    args:
      - name: ticket
        required: true
    script: ...
  - name: list-active-untracked-work
    help: lists tickets whose parent epic is still in the backlog
    script: ...
  - name: label-active-untracked-work
    script: ...

The remove-attachments command is a nice demonstration of how you can take in arguments in your custom commands. This yaml tells go jira that the user should pass in the ticket key for the ticket whose attachments they want remove all at once. go jira automatically takes care of generating sane usage output when you try to misuse the command:

○ → jira remove-attachments
usage: jira remove-attachments <ticket>

removes all attachments from a given issue
...
Args:
  <ticket>

ERROR Invalid Usage: required argument 'ticket' not provided

You can actually reference the passed argument using templating in the string passed into the script property:

custom-commands:
  - name: remove-attachments
    help: removes all attachments from a given issue
    args:
      - name: ticket
        required: true
    script: jira attach list {{args.ticket}} ...

Command templates

Another killer feature that I’ve used in conjunction with custom commands is the ability to tell jira-go how you want it do display output from a particular command using go templates. You can see which templates are being used for a particular command by passing -t -debug:

jira view GOJIRA-321 -t debug

You can edit the default templates after you export them (to ~/jira.d/templates) with this command:

jira export-templates

Some Useful Bashisms for Custom Jira Commands

(If you’re already familiar with bash commands like cut, sed, and xargs, you won’t gain anything from reading this section.)

I want to briefly go over some bash commands that were helpful in building these commands. To do this, let’s walk through the script property of the remove-attachments custom command:

jira attach list {{args.ticket}} \
  | cut -sf 2 -d \| \
  | sed -n '1!p' \
  | sed 's/ //g' \
  | xargs -L 1 -I % jira attach rm %

At a high-level, what we’re doing here is taking the output of one jira-go command and massaging it so that it can serve as the input to another jira-go command.

jira attach list

This is a standard go-jira command. Nothing to see here really.

{{args.ticket}}

This is where we read ticket key as a go template item as discussed here.

cut -sf 2 -d \|

Cut allows you cut out portions of lines from text.

-d allows you to specify a delimiter for splitting up lines. For example, if “,” is a delimiter, the line “1,2,3” will be split into an array like [1, 2, 3]

-f allows you to pick out which element in the above (1-indexed) array you want to cut from the line. So, -f 2 would pick out “2”.

-s means skip lines that are missing the delimiter

sed -n ‘2s/ //gp’

-n By default, each line of input is echoed to the standard output after all of the commands have been applied to it. The -n option suppresses this behavior.

2

grab the second line of the input passed to you

s/ //g

replace “ ” with “” globally

p

then print the result

xargs -L 1 -I % jira attach rm %

xargs executes a command for each -L number of lines of of some input. -I lets you specify the replacement string. The last argument is the command you want to execute, so here we’re saying:

“execute jira attach rm % for each line of the input and replace % with a line of the input”

Because of the work we’d done with the previous bash commands % will be replaced with the identifier of an attachment we want to remove.


Notes


  1. I know there’s a jira plugin that could be used to help with this, but it’s not free. [return]