Configuring Jira for your needs:

Configuring Jira for your needs:Perfect flow and ideal ticketDmitry SemenihinBlockedUnblockFollowFollowingMar 26If you work in an IT company then the likelihood is that your processes are built around Atlassian’s well-known Jira.

There are numerous task-trackers available on the market for solving such tasks, including open-source solutions (Trac, Redmine, Bugzilla), but Jira is probably the most widely used.

My name is Dmitry Semenihin and I am a team lead at Badoo.

In this short series of articles, I will tell you about how we use Jira, how we have configured it for our processes, the good things we have ‘bolted’ onto it and how, in this way, we have effectively turned an issue tracker into a one-stop task communications centre thus making life somewhat easier for ourselves.

In this article you will see our flow from the inside, find out how to ‘upgrade’ your Jira and discover this tool’s additional capabilities which you might not know about yet.

The content here is primarily aimed at those who already use Jira, but who may be experiencing problems with embedding its standard capabilities into their company’s existing processes.

This article may also be useful for anyone using other task-trackers, who have encountered certain limitations and are thinking of moving to another solution.

The article is not structured in terms of problem-solution, but rather in the article I describe the set of established tools and features we have built up around Jira and also the techniques we use when implementing them.

Jira’s additional capabilitiesIn order for what follows to make more sense, let’s see what tools Jira has to offer with a view to implementing non-standard demands, i.


those which go beyond standard Jira functionality.

REST APIGenerally speaking, calling an API command represents an HTTP query to an API URL, specifying the method (GET, PUT, POST and DELETE), the command and the body of the query.

The body of the query and, also, the API response are in the JSON format.

Here is an example of a query which will return a JSON presentation of a ticket:GET /rest/api/latest/issue/{ticket_number}With the help of API, using scripts in any programming language, you can do the following:Create tickets;Modify any ticket properties (built-in or custom ones);Write comments;Obtain any lists of tickets, with the help of JQL (built-in query language);And much more.

Click this link for more detailed info on API.

We have written our own high-level Jira API client in PHP which implements all the commands we need.

Here is an example of commands for working with comments:public function addComment($issue_key, $comment){ return $this->_post("issue/{$issue_key}/comment", ['body' => $comment]);} public function updateComment($issue_key, $comment_id, $new_text){ return $this->_put("issue/{$issue_key}/comment/{$comment_id}", ['body' => $new_text]);} public function deleteComment($issue_key, $comment_id){ return $this->_delete("issue/{$issue_key}/comment/{$comment_id}");}WebhookUsing webhook you can configure calling the external callback function on your host for various events in Jira.

At the same time, you can configure as many rules as you like, so various unique URLs will be triggered for various events and for tickets which match the filter specified in webhook.

The webhook configuration interface is accessible to the Jira administrator.

As a result, you can create a rule like this:Name: “SRV — New Feature created/updated”URL: www.


com/webhookreceiverScope: Project = SRV AND type in (‘New Feature’)Events: Issue Updated, Issue CreatedIn this example the URL specified will be accessed for events that create and change tickets and meet the criteria of the Scope filter.

At the same time, the body of the query will contain all the necessary information on what exactly has changed and what event has occurred.

It is important to understand here that Jira does not guarantee delivery of your event.

If the external URL has not responded or has responded with an error, this will not be visible anywhere (apart from in logs, of course).

So, the webhook event handler needs to be as reliable as possible.

For example, events can be queued and repeated attempts made to handle them until a successful outcome is achieved.

This will help you resolve problems with services that are temporarily unavailable, for example an external database that is essential for the correct handling of an event.

Click this link for detailed documentation relating to webhook.

ScriptRunnerThis plug-in for Jira is a very powerful tool allowing you to customise a lot of things in Jira (it also capable of operating as a replacement for webhooks).

In order to take full advantage of plug-in, you need to know Groovy.

The main advantage of this tool from our point of view is that you can embed custom logic into the flow online.

The code for your script will run straightaway in the Jira environment in response to a given action.

For example, you can create your own button in the ticket interface which, when you click it, creates tickets relating to the current task or runs unit tests for a given task.

And, if something unexpectedly goes wrong, as a user you will see it straightaway.

If you are interested, you can read the documentation here.

Flow: what is hidden ‘under the hood’And now to look at how we apply Jira’s additional capabilities to our projects.

Let’s consider this in the context of the lifecycle of our typical ticket flow: from creation to closure.

As we proceed, you will also understand more about the flow itself.

Open/BacklogSo, to start off with, the ticket ends up in the backlog of new tickets and with an ‘Open’ status.

Then the component lead, seeing a new ticket appear on their dashboard, makes a decision either to assign the ticket to a developer immediately or to send it to the backlog of known tickets (‘Backlog’ status) from where it will be assigned later, i.


when a developer becomes available and higher priority tickets have been closed.

This may seem strange, as it might seem logical to do it the other way around, namely, to create tickets with the status set to ‘Backlog’ and then to change their status to ‘Open’.

But this is what has become an accepted practice in our company.

It allows us to configure filters easily, so that we can shorten the time required to make decisions in respect of new tickets.

Here is an example of a JQL filter which presents the lead with new tasks:Project = SRV AND assignee is EMPTY AND status in (Open)In ProgressTechnical idiosyncrasies of working with GitIt should be noted that, here at Badoo, work on each task is carried out on a separate Git branch.

In this regard we have a convention that the name of the branch must include the ticket number right from the start.

For example, SRV-123_new_super_feature.

Likewise, comments on each commit to the branch must contain the number of the ticket in the form [SRV-123]: {comment}.

This format is essential for us so that, for example, we can remove a ‘bad’ task from the build in the proper way.

These requirements are controlled by Git hooks.

For example, here is the content of a prepare-commit-msg, which prepares for the commit, obtaining the ticket number from the name of the current branch:#!/bin/bashb=`git symbolic-ref HEAD| sed -e 's|^refs/heads/||' | sed -e 's|_.

*||'`c=`cat $1`if [ -n "$b" ] && [[ "$c" != "[$b]:"* ]]then echo "[$b]: $c" > $1fiAttempt to push a commit with a ‘wrong’ comment and that push will be declined.

Likewise, any attempt to push a branch that has no ticket number at the start, will be declined.

When a ticket reaches the handler, the first thing that happens is that it decomposes.

As a result of the ticket decomposition the developer gets an idea of what means they should use to solve the issue and how much time is likely to be required.

Once all the main details have been clarified, the ticket status is changed to ‘In Progress’, and the developer starts to write code.

Our practice is to publish a due date for a task the moment its status is changed to ‘In Progress’.

Any developer failing to do this receives a reminder via the corporate messenger, HipChat.

Every two hours a special script does the following:Using REST API Jira, selects tickets with an ‘In Progress’ status and an empty due date field (project = SRV AND status = ‘In Progress’ AND duedate is EMPTY);Selects uncompleted tickets with a due date older than today’s date (project = SRV AND status = ‘In Progress’ AND duedate is not EMPTY AND duedate < now());Identifies the developer of each ticket — by reading the relevant field in the ticket — and also the developer’s lead;Groups tickets according to developers and leads and sends reminders via HipChat, using their API.

Having performed all the necessary commits, the developer pushes the branch to the shared repository.

In this case, the Git hook post-receive activates.

This does lots of interesting things:Checks the name of the Git branch and also the comments on the commits for compliance with our rules;Checks that the ticket associated with the branch is not closed (you cannot push new code to closed tickets);Checks the syntax of changed PHP files (PHP -l file_name.

php);Checks formatting;If a ticket, to which a branch is pushed, has an ‘Open’ status, it is automatically changed to an ‘In Progress’ status;The ticket gets connected to the branch and a relevant note is made in the ticket’s Commits custom field using Jira API.

This is what it looks like:(branchdiff refers to the diff of the branch with the head which the current branch originated from, in our code review tool, Codeisok);A comment is created in the ticket along with all the commits in the push in question.

(Aida is the name we have given our automated assistant that works with Jira, Git and more besides.

Automated comments in the ticket appear under this name.

)By clicking on the hash for the commit you open the diff with the previous branch revision (what this might look as shown below);Files on the branch are checked to see if any require translation into supported languages (for example templates for web pages), and, if any do, then the ticket’s custom field, Lexems, is assigned the value NewChanged.

This guarantees that the ticket is not sent to production without having been translated;The name of the member of staff pushing the branch is added to the list of developers (ticket’s custom field, Developers).

On ReviewHaving written the code and independently verified that all the requirements have been fulfilled vis-à-vis the task, and that the tests have not failed, the developer assigns the ticket to a reviewer (‘On Review’ status).

Usually the developer themselves decides who will review their ticket.

More often, it will be another developer who is an expert on the relevant part of the code.

Review is carried out with the help of the Codeisok tool, which opens straightaway with the necessary diff by clicking on the branchdiff link in the Commits ticket field or on the link in the form of a commit hash in the comments.

The reviewer sees something along the lines of the following:Having completed their review, the reviewer presses the Finish button, and, apart from anything else, here is what happens at that moment:Using API Jira, a comment is created in the ticket with feedback from the reviewer in the context of the code.

This looks something like this:If feedback is received on the code and the reviewer decides to reopen the ticket, then the developer will receive notification of the same via HipChat (this is done using the webhook rules which activate when a ticket is reopened);The Reviewers ticket field is completed.

ResolvedFurthermore, if the review has been successful, the ticket is sent to the QA engineers’ backlog with the status ‘Resolved’.

However, along with this, automated tests on the branch code are run in the background using webhook.

These are activated by the ‘resolved’ event.

After several minutes a new comment will appear in the ticket, giving the results of the tests.

Thus, you can, at any time, manually initiate repetition of the tests by clicking on the special ‘Run unit tests’ button in the ticket menu.

Having successfully run the tests, a new comment, similar to the previous one, will appear in the ticket.

Essentially, this button is one of the additional task statuses in the Jira workflow.

Changing to this status initiates activation of the script in Groovy for the ScriptRunner plug-in.

The script accesses an external URL which initiates the running tests, and if the URL responds successfully the ticket returns to the previous status (in our case, ‘Resolved’).

In Shot / In Shot — OKFirst of all, the task is tested in a development environment.

If everything is fine, a shot is created on a dedicated server (for example, by clicking on the Create shot link in the Commits field).

Changes from the ticket, merged with the current master branch, are copied to this directory.

The server works with production data: the databases and services are the same as those which serve real users.

Thus, a tester can open a web-site or connect to the shot using a mobile client and can test the feature ‘in isolation’ in the production environment.

‘In isolation’ means that no other code/functionality is run apart from the new code made up of the branch and current master.

So, this stage of testing is, so to speak, basic, since it allows a QA engineer to find a problem directly in the task being tested with maximum reliability.

Access to the shot’s resources is via special URLs, which are generated in the script which creating the shot, and which, with the help of API Jira, are to be found in the ticket header.

As a result, we see links to the site, admin, logs and other tools which are run in the shot environment:Also, at the moment the shot is generated, a script is launched which analyses the content of changed files and creates requests for the translation of new lexems found.

Once the translation is completed, the value of the Lexems field is changed to ‘Done’ and the ticket may be added to the build.

If testing in the shot has been successful, the ticket status will be changed to ‘In Shot — OK’.

In Build / In Build — OKWe release new code twice a day: morning and evening.

For this purpose, a special build branch is created which, as a result, will be merged into the master and uploaded to a production.

At the moment the build branch is assembled a special script — with the help of a JQL query — receives a list of tickets with the status ‘In Shot — OK’ and attempts to merge them to the build branch, while meeting all the conditions set out below:Translation for ticket done or no need for translation (Lexems in (‘No’, ‘Done’));Developer present at their place of work (the automatic merging system checks the internal database to see whether the developer is on holiday or on sick leave, and, if so, then the ticket may only be merged manually by release engineers or by some other authorised developer, as specified in the special Vice Developer field; in this case the absent developer’s lead is notified that the ticket cannot be added automatically to the build);The ticket does not have the ‘Up in Build’ flag set to the ‘by Developer’ value (this is a special, custom field for the ticket which allows the developer to decide when a ticket will end up in the build);The ticket branch is not dependent on another branch not yet in the master or current build.

We try to avoid this situation in all sorts of ways, but sometimes it does happen that a developer creates their own branch not from the master, but from the branch of another ticket, or when it merges another branch into itself.

This can also be done accidentally, so we decided that additional protection would not be superfluous.

It should be pointed out that automatic merging may not take place if there is a merge conflict.

In such cases, the status of the ticket automatically changes to ‘Reopen’ and it is assigned to a developer who immediately receives notification via HipChat, and the relevant message is added to the ticket commentary.

Once the conflict has been resolved, the ticket returns to the build.

If everything is fine and the ticket branch is merged to the build, the ticket status will automatically change to ‘In Build’, and the build name gets written to the ticket’s custom field, Build_Name.

Then, using this value, it is easy to obtain a list of tickets released with each build.

For example, when looking for who is to blame if something goes wrong.

At the next stage QA engineers additionally also check whether the task code is working properly along with other tasks in the build.

If everything is fine, the ticket is manually assigned the status ‘In Build — OK’.

On Production / On Production — OK / ClosedNext, our entire set of tests (Unit, integration, Selenium, etc.

) is run on the build.

If everything is fine, the build is merged into the master, and the code is uploaded to production.

The ticket status is changed to ‘On Production’.

Then the developer (or customer) makes sure that the feature is working properly on production and assigns the ticket the ‘On Production — OK’ status.

After two weeks have passed, tickets with the status ‘On Production — OK’ are automatically changed to the ‘Closed’ status, unless someone has already done so manually.

We should also mention the additional statuses a ticket may have:Requirements — if it hasn’t been possible to obtain necessary clarification from the reporter (or another person) in respect of the task, and if without such clarification no further work on the ticket is possible, then the ticket status is changed to this status and is assigned to the person who needs to provide the clarification in question;Suspended — if work on the ticket is suspended, for example, if the developer is being prevented by tasks being performed by an adjoining team or if the developer had to switch to work on a more urgent task;Reopened — a task may be reopened by a developer after review, after testing or after an unsuccessful attempt to merge the branch with the master.

As a result, a simplified diagram of our workflow looks like this:Ticket: task communications centreOnce a ticket has gone through the flow, this is what its header looks like:What else is there of interest here?.What did we configure for our own requirements?.What have I not mentioned yet?Component — this is used for ticket clustering as part of a large-scale department.

Various sub-groups are responsible for various components and, correspondingly, on their dashboards they only see those tasks which relate to their components.

For example, I can export a list of all open bugs relating to my team’s components using the following query:Project = SRV AND type = Bug AND status = Open AND component in componentsLeadByUser(d.

semenihin)Review — is code review required?.It is, by default.

If the field value is set to ‘No’, the ticket status gets set straight to ‘Resolved’.

QA — is testing by a tester required?.It is, by default.

If the field value is set to ‘No’, the ticket status gets set straight to ‘In Shot — OK’.

Sprint — in our case this is only relevant in the case of New Feature tasks, for which we make a plan a week in advance.

Due date — the developer sets a date when the ticket will be in production.

This is published before work begins on a given task.

Situation — this is essentially a brief log with a short description of the current status of the task.

For example, “20/08 Waiting for translations”, “21/08 Require clarification from client regarding problem Х”.

It’s in effect a brief summary report regarding the task within a list of other tasks.

Msg4QA — information for QA engineers, shared by the developer in order to simplify the testing process.

We try to ensure that controversial matters are discussed with the task-setter in the ticket comments area, so that important clarification is not scattered across email and messengers.

If discussion has taken place somewhere else, it is highly desirable for what has been agreed to be copied to the ticket.

Besides ‘human’ texts, as I have already mentioned above, there is also a lot of stuff in the comments which is written automatically using API:Commits;The results of review;Results of tests run.

Sometimes automated comments may get in the way, for example of product managers.

So, we have created a simple JS script that adds a button to the Jira interface and allows you to collapse all the automatic comments, leaving only the ‘human’ ones.

The resulting collapsed, automatic comments appear in compact form.

JS code of the script which we built into the ticket templatewindow.

addEventListener('load', () => {const $ = window.

jQuery;const botsAttrMatch = [ 'aida', 'itops.

api' ].

map(bot => `[rel="${bot}"]`).

join(',');if (!$) { return; }const AIDA_COLLAPSE_KEY = 'aida-collapsed'; const COMMENT_SELECTOR = '.



twixi-block';const JiraImprovements = { init() { this.

addButtons(); this.

handleAidaCollapsing(); this.

handleCommentExpansion();// Handle toggle button and aida collapsing and put it on a loop // to handle unexpected JIRA behaviour const self = this; setInterval(function () { self.

addButtons(); self.

handleAidaCollapsing(); }, 2000);addCss(` #badoo-toggle-bots { background: #fff2c9; color: #594300; border-radius: 0 3px 0 0; margin-top: 3px; display: inline-block; } `); },addButtons() { // Do we already have the button?.if ($('#badoo-toggle-bots').

length > 0) { return; }// const headerOps = $('ul#opsbar-opsbar-operations'); const jiraHeader = $('#issue-tabs');// Only add it in ticket state if (jiraHeader.

length > 0) { const li = $('<a id="badoo-toggle-bots" class="aui-button aui-button-primary aui-style" href="/">Collapse Bots</a>');li.

on('click', this.



append(li); } },toggleAidaCollapsing(e) { e.

preventDefault();const isCollapsed = localStorage.

getItem(AIDA_COLLAPSE_KEY) === 'true';localStorage.

setItem(AIDA_COLLAPSE_KEY, !isCollapsed); this.

handleAidaCollapsing(); },handleAidaCollapsing() { const isCollapsed = localStorage.

getItem(AIDA_COLLAPSE_KEY) === 'true'; const aidaComments = $(COMMENT_SELECTOR).



manual-toggle');if (isCollapsed) { aidaComments.


addClass('collapsed'); $('#badoo-toggle-bots').

text('Show Bots'); } else { aidaComments.


addClass('expanded'); $('#badoo-toggle-bots').

text('Collapse Bots'); } },handleCommentExpansion() { $(document.



collapsed-comments', 'click', function () {const self = this; // eslint-disable-line no-invalid-this let triesLeft = 100;const interval = setInterval(() => { if (–triesLeft < 0 || self.

offsetHeight === 0) { clearInterval(interval); }// Element has been removed from DOM.



new jira comments have been added if (self.

offsetHeight === 0) { JiraImprovements.

handleAidaCollapsing(); } }, 100); });$(document.


delegate(COMMENT_SELECTOR, 'click', function () { $(this).

addClass('manual-toggle');// eslint-disable-line no-invalid-this }); } };JiraImprovements.

init();function addCss(cssText) { const style = document.


type = 'text/css'; if (style.

styleSheet) { style.


cssText = cssText; } else { style.


createTextNode(cssText)); }document.


appendChild(style); }});Anything else?Yes, with the help of API and Jira webhooks we also do the following:Send notification via HipChat if one of the staff members was mentioned in the comments (very helpful for solving issues promptly);Send notification via HipChat when a ticket is assigned for review and when it arrives at production (in a forthcoming article I will tell you how we actually implemented this);Using a special interface with just a couple of mouse-clicks system architects can create tickets for different teams (client and server teams) for implementing a project (immediatly the tickets are properly completed with the necessary fields and linked together; this helps us to synchronise the work being done by the teams);We automatically track the appearance of new client versions; then a special script creates a ticket for the server team, so that we can add changes to some configurations;For statistical purposes the script periodically takes cross-section samples relating to tasks with the ‘In progress’ status;The script identifies tasks with a given status which have got ‘held up’ (for example, ‘On Review’), and sends relevant messages to the members of staff responsible;If a given member of staff is out of the office on a given day and there is a note of this in the internal database, this information is appended to their name in Jira (for example, «d.

semenihin (Day off)»).

This is a very useful feature.

ConclusionsJira is a wonderful tool which, in the standard form that it comes in, allows you to resolve most problems related to project management organisation.

However, as is well known, every business has its idiosyncrasies.

And, for the purposes of adapting Jira to the specifics of our processes, this product has additional capabilities to offer which, in capable hands, enable us to find a practical resolution to any problem we encounter.

In the next article I plan to share our experience of using Jira to synchronise work by various teams.

I hope our experience will prove useful for you too.

Thanks for reading!.

. More details

Leave a Reply