Use a Google Form To Create JIRA Issues With The REST API

Use a Google Form To Create JIRA Issues With The REST API

Abstract

In this post, I'll describe how to use Google Forms, associated Google Sheet, and ultimately a Google Script to create issues in Atlassian JIRA Software using the very powerful JIRA REST API.

TL;DR

Jump to the Guide
Jump to the Google Script

Why?

This is a slightly off topic post for the intention of this blog, but it is something that interests me nonetheless. This is essentially my first real production chance to develop something using APIs to go into production use!

In my use case, the JIRA instance is hosted in the cloud, but is only used internally. Since this is the case, we require all users to be authenticated to be able to use JIRA. Across the organisation, few users have accounts in the JIRA instance, so a simple method is required to allow them to raise requests. Google forms fits the bill for us to be able to provide this functionality.

Prerequisites

Somewhat obviously, there are 2 main components you'll need access to use this guide completely; JIRA and Google Forms. Nevertheless, there may be a certain amount of information that can be used to serve a more generic purpose, but full descriptions of the functionality of each of these components are out of scope of this blog post.

If you would like more content on JIRA, please get in touch via the comments, or follow the links to my social media profiles in the top right of the blog.

JIRA

If you are not familiar, JIRA1 is an issue tracking software, used across a variety of businesses and is designed to support agile software development methodologies.

JIRA

I have spent the last few years working with it (and other Atlassian products, notably Confluence and Bitbucket) in an administrative capacity, and have developed numerous workflows and developed a number of delivery processes that have JIRA at is core. In most cases, the use cases have been broader than Software Development. This is out of scope here, but suffice to say it can be used for most delivery teams that have a technical focus, and it does not necessarily need to follow Agile methodologies.

I am a site administrator of our cloud instance of JIRA Software. If you are running the server version, your mileage may vary with regards to the API calls; please refer to documentation for your version. The site administrator permissions allow me to create custom fields and workflows and manage users amongst other things. If you are not an admin of your instance, you may have additional problems to solve.

REST API

  1. The latest JIRA REST API2 is very well documented, at the time of writing, this is version 7.1.8.
  2. The JIRA developer documentation3 is a good resource for specific examples of how to perform certain functions with the API.

Google Forms

Anyone with a Google account should have access to access to Google Forms4.

Forms

It's a pretty simple tool, and very self explanatory for anyone who is likely to read this post! The guide section below will go into detail on how to create an associated Google Sheet and Script.

The only additional point to note here is that my company uses Google Apps for Work5. This is relevant as I run the production script from a team dedicated account (not my own). There are a number of reasons for this, mostly around authentication, but the point here is this may need to be a consideration for you. If you would like more information on this, please add a comment or reach out to me on my social networks.

Guide

So, the core of this post. Let's jump right into this with a high level list of items we need to cover:

  1. Select the JIRA User Account
  2. Create a Google Form
  3. Create an associated Google Sheet to store the Form responses
  4. Create a Google Script inside the Google Sheet

JIRA User Account

Rather the creating new issues in JIRA with my own account, I created a new account specifically for this purpose. As I mentioned earlier, we use Google Apps for work, and I have a Google Account with it's own mailbox that I use for this user account; this has it's own purpose and benefits which I will not go into in this post.

The significance of this account is to serve the purpose of basic authentication6, to enable the API POST method. As described in the link, the "username:password" string is Base64 encoded. I used the Base64 Decode and Encode7 website to help with this.

Google Form

A simple Google Form is constructed, with information relevant to your particular use case.
There is no real need to dwell on this; the design of this form will need to support your implementation.

Google Sheet

From the administration view of the Google Form, select the responses tab.

In the right hand corner, above the accepting responses switch, click the green sheets link to open up an associated Google Sheet that will then be populated with the responses submitted via the form.

As shown above, from the tools menu, you are now able to select "Script Editor". The Google Sheet is then used by the associated script when POSTing to the JIRA REST API.

Google Script

The Google Script I have created, and am using in production, is a single file - "Code.gs". The code is edited in with in the Script App:

From the Resources menu, selecting "Current Project's Triggers" will pop up the following dialogue:

You can see here, the configuration of the trigger I have used.

Code

I have published the latest version of the code on Github8, which will be the authoritative location following this publishing of this post. For reference however, the following code is in use at the time of writing.

It is important to keep in mind that the structure and naming conventions are relevant to my implementation; you'll need to adapt the code to suit your use case.

UPDATE 12 Feb 2018: Please see note below code block

//
// This script takes the user inputs from the Google Form, and will create a JIRA issue when the form is submitted via the REST API
// Takes user input info, and passes it into an event parameter "e"
//
function createIssue(e){  
//
// Assign variables to the form data submitted by the requestor from the spreasheet associated with the Google form.
// NOTE: Update the [n] to the cell value in your spreadsheet.
//
  var requesterEmail = e.values[1];
  var summary = e.values[2];
  var description = e.values[3];
//
// The dueDate variable requires a formating update in order that JIRA accepts it
// Date format becomes YYYY-MM-DD, and is called later in the data posted to the API
// 
  var dueDate = e.values[4];
  var formattedDate = Utilities.formatDate(new Date(dueDate), "GMT", "yyyy-MM-dd");
//
// Contact names
//
  var businessSponsor = e.values[5];
  var technicalContact = e.values[6];  
  var docLinks = e.values[7];
//
// Assign variable to your instance JIRA API URL
//
  var url = "https://<YOUR_JIRA_INSTANCE>.atlassian.net/rest/api/latest/issue";
//
// The POST data for the JIRA API call
//
  var data = 
{
    "fields": {
       "project":{ 
          "key": "<PROJECT_KEY>"
       },
       "priority": {
          "name": "Minor"
       },
      "duedate": formattedDate,
      "summary": summary,
      "description": description,
//
// The following custom fields are for the various strings and are simple text fields in JIRA
// You can find all the custom fields by looking here: https://<YOUR_JIRA_INSTANCE>.atlassian.net/rest/api/latest/field/
//    
      "customfield_14902": businessSponsor,
      "customfield_16100": technicalContact,
      "customfield_10216": requesterEmail,
      "customfield_14308": docLinks,
//
// All tickets are categorised as Tasks, and are not changed by the form submission.
//
      "issuetype":{
          "name": "Task"
       }
   }
};
//
// Turn all the post data into a JSON string to be send to the API
//
  var payload = JSON.stringify(data);
//
// POST header information, including authorization information.  
// This API call is linked to an account in JIRA, and follows the Basic Authentication method ("username:password" are Base64 encoded)
//
  var headers = 
      { 
        "content-type": "application/json",
        "Accept": "application/json",
        "authorization": "Basic <BASE64_ENCODED_USER:PASS>"
      };

//
// A final few options to complete the JSON string
//
  var options = 
      { 
        "content-type": "application/json",
        "method": "POST",
        "headers": headers,
        "payload": payload
      };  

//
// Make the HTTP call to the JIRA API
//
  var response = UrlFetchApp.fetch(url, options);
  Logger.log(response.getContentText());
//
// Parse the JSON response to use the Issue Key returned by the API in the email
//
  var dataAll = JSON.parse(response.getContentText());
  var issueKey = dataAll.key
  Logger.log(dataAll)
//
// Assign variables for the email reposnse
//
  var myMailbox = "noreply@nodomain.com"
  var emailSubject = "Your request no. " + issueKey + " has been created";
  var emailBody = "Thank you for your ticket submission." + "\n\n" +
    "Your request has been created, your reference is " + issueKey + " which can be accessed via the following link to the JIRA system:" + "\n\n" +
      "https://<YOUR_JIRA_INSTANCE>.atlassian.net/browse/"+ issueKey + "\n\n" +
       "We will be in touch soon to discuss your ticket submission.  " +
//
// Send an email to the requestor
//
  MailApp.sendEmail(requesterEmail, emailSubject, emailBody, {
    name: "<MAILBOX_NAME>"
  })
 }

Comments have been included in the code block, and provide in context information for the various sections. There are a few sections of the code that are worth adding a few more notes on, and I will do so below.

Please Note: An update to the JIRA API URL has been highlighted in the comments section by Bruce Kozuma, and should now read as follows:

//
// Assign variable to your instance JIRA API URL
//
var url = "https://<your_jira_instance>.atlassian.net/rest/api/2/issue";  
//

Date Format

Whilst specific to my use case, it's important to note formatting can sometimes be an issue between defaults in Google and JIRA. When POSTing to the JIRA API with the default Google format, there was an error response that meant a ticket was not created. It can be tricky to troubleshoot this from within these applications.

Email Response

Since we use Google Apps in the company, I have used the MailApp.sendEmail method, to allow me to send an automated response which adds some of the information from the REST API response. This is not a necessary part of the script.

Helpful Tips

If you are not familiar with coding, a text editing tool like Atom9 with syntax highlighting can help significantly.

I found testing and debugging a bit of an issue with the native tools. Also since the Google script requires that cells are filled with text which would be submitted via the form, I looked for an alternative to test small sections of the API POST to better analyse error responses. I use Chrome, and found the Advanced Rest Client10 Chrome App invaluable.

Links/References