Interlocking Issues – Creating Epics and Bugs From a Jira Cloud Listener

There’s nothing terribly complicated about what I’m posting today, but it’s been a while since I put out an update.
The challenge today was to create a sort of interlocking series of issues, using a listener. That is, the listener listens for an issue to be created. It creates a bug and an epic within the same project. It then sets the epic link of the original issue and bug to be the newly created epic. It was also an exercise in balancing efficiency with readability.  Certainly, there are much more efficient ways this script could have been written. But I think as an example, it’s fairly readable, and that has value too.   

//Example Listener for Jira Cloud - Create Bug and Epic Automatically
 
//Author: Ken McClean / kmcclean@daptavist.com
 
//Script functions:
// - Script runs as a listener
// - On issue create, script creates a new epic
// - It also creates a new bug
// - The script then sets the epic link of the original issue and the new bug to be the newly created epic
 
//References:
//https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-post
//https://library.adaptavist.com/entity/create-subtasks-when-issue-created
 
//BEGIN DECLARATIONS:
final bugTypeID = "10008"
final epicTypeID = "10000"
final epicNameField = "customfield_10011"
final epicLinkField = "customfield_10014"
//Set the constants that we'll use to refer to components within the system
//You'd have to find these values within your own Jira instance, and update the script accordingly
 
def issueKey = issue.key
//def issueKey = "ABC-8"
//Get the key of the newly created issue
//If we wanted to test against a specific issue, we'd convert to using something like "def issueKey = "ABC-8"
 
//*************************
 
//BEGIN MAIN SCRIPT FUNCTIONS:
 
//Fetch the new issue as an object
def issueResp = get("/rest/api/2/issue/${issueKey}").asObject(Map)
assert issueResp.status == 200
def issue = issueResp.body as Map
def fields = issue.fields as Map
//Get the issue fields
 
//Create a new epic under the same project as the new issue
logger.warn("Creating a new epic. Result:")
 
def createEpic = post('/rest/api/2/issue')
  .header('Content-Type', 'application/json')
  .body(
    fields: [
      "${epicNameField}": "Epic For ${issueKey}",
      project: [id: fields.project.id],
      issuetype: [
        id: "${epicTypeID}"
      ],
      summary: "Epic - Related to ${issueKey}"
    ])
  .asObject(Map)
 
//Get and validate the newly created epic
def newEpicIssue = createEpic.body
 
//If the epic was created successfully, return a success message
if (createEpic.status >= 200 && createEpic.status < 300 && newEpicIssue && newEpicIssue.key != null) {
  logger.info("Success - Epic Created with the key of ${createEpic.body.key}")
} else {
  logger.error("${createEpic.status}: ${createEpic.body}")
}
 
logger.warn("Creating a new bug. Result:")
//Create a new bug, and set the epic link of the bug to the previously created epic
def createBug = post('/rest/api/2/issue')
  .header('Content-Type', 'application/json')
  .body(
    fields: [
      "${epicLinkField}": "${createEpic.body.key}",
      project: [id: fields.project.id],
      issuetype: [
        id: bugTypeID
      ],
      summary: "Epic - Related to ${issueKey}"
    ])
  .asObject(Map)
 
//Get and validate the newly created bug
def newBugIssue = createBug.body
 
//If the bug was created successfully, return a success message
if (createBug.status >= 200 && createBug.status < 300 && newBugIssue && newBugIssue.key != null) {
  logger.info("Success - Bug Task Created with the key of ${createBug.body.key}")
} else {
  logger.error("${createBug.status}: ${createBug.body}")
}
 
//Set the epic link of the new issue to be the key of the newly created epic
logger.warn("Setting the epic link of the original issue to be the key of the new epic. Result:")
def setEpicLink = put("/rest/api/2/issue/${issueKey}")
  .header('Content-Type', 'application/json')
  .body(
    fields: [
      "${epicLinkField}": "${createEpic.body.key}",
    ])
  .asObject(Map)
 
//If the epic was created successfully, return a success message
if (setEpicLink.status >= 200 && setEpicLink.status < 300 && setEpicLink.body && setEpicLink.body.key != null) {
  logger.info('Success - Epic Link created for ${issueKey}')
} else {
  logger.error("${setEpicLink.status}: ${setEpicLink.body}")
}

Leave a Reply

Your email address will not be published. Required fields are marked *