JIRA Webhook and Lambda (Automated ticketing system functions)

Discussion in 'Created Programs' started by Rushy, Feb 8, 2017.

Thread Status:
Not open for further replies.
  1. Rushy

    Rushy Administrator
    Staff Member

    Joined:
    Oct 1, 2016
    Messages:
    342
    Likes Received:
    80
    lambdacode.js



    Overview
    Each time an Issue is created or updated, a JSON is sent via the JIRA webhook to the specified URL in the webhook settings. In this case, it is sent to a lambda function in AWS, which processes the JSON and uses the JIRA cloud REST API to send information back.

    Bug and epic creations also activate the Webhook.



    [​IMG]

    [​IMG]

    Story points are used to create the approximate hours to complete a issue. Example a person inputs a Story points value of 13 into the issue, the program sets 30 hours automatically in the 'originalEstimate' field (Only the program has assess to the originalEstimate field)

    When an issue event is sent via the webhook, the code calculates the story points and sends it back via a PUSH into ‘customfield_10004’ which is the field used to store story points.

    It also calculates the original time in hours and uses a PUT into the ‘originalEstimate’ field. Even though the input is as follows for example: customfield_10004 = "60", JIRA will display those hours in the Xw Xd XXh format e.g. 1w 0d 4hr. Additionally, 8 hours amounts to 1 day within JIRA e.g. 15 hours is originalEstimate hours / 8 = days and with context it is simply 15 / 8 = 1 day and 7 hours.


    When a bug is created, the lambda uses a POST to automatically create a subtask for the bug which is named the ‘Technical Analysis task’.

    When an Epic is created, a Technical specification task is created for the epic.



    Code account and permissions
    This program uses the JIRA account ‘******'(special user for this function) as this user only has permissions to create issues and edit them in all projects.

    In order for the timetracking and story points to be modified, the user must be able to see these fields in their ‘view’ and to have permission to use them.



    Custom Fields
    Customfield_10004 - Story point field



    When creating a new Lambda Instance
    When using this code with a new Lambda instance, you must zip the script along with the ‘request’ module in a structure like so:



    [​IMG]

    [​IMG]



    *This is only needed for a new lambda instance. If you are editing the existing lambda, you can use the AWS code editor*



    Code in use
    Also attached at the top of the page

    *Sensitive information is masked out*

    Code:
    'use strict';
    
    exports.handler = (event, context, callback) => {
        var statusCode = 200;
        var request = require('request');
        var username1 = "";
        var password1 = "";
        var auth = "Basic " + new Buffer(username1 + ":" + password1).toString("base64");
    
        var id;
        var issue_score;
        var original_seconds;
        var $url = "https://******.atlassian.net/rest/api/2/issue/";
        var status_received = event.issue_event_type_name;
        var issue_type;
        var project_key;
        var parent_key;
        var com_self;
        var com_id;
        var com_name;
    
        if (status_received == "issue_updated" || "issue_created") {
    
            id = event.issue.id;
            //10004 is story points
            issue_score = parseFloat(event.issue.fields.customfield_10004);
    
            //seconds
            //original_seconds = event.issue.fields.timetracking.originalEstimateSeconds;
            $url = $url + id;
            issue_type = event.issue.fields.issuetype.name;
            issue_type = issue_type.toLowerCase();
     console.log("main area");
            /////////// if issue is a bug, make it create the subtask and end the loop///////////
            if (issue_type == "bug" && status_received == "issue_created") {
                //console.log("this bug is new");
                project_key = event.issue.fields.project.key;
                parent_key = event.issue.key;
                //com_self = event.issue.fields.components.self;
                //com_id = event.issue.fields.components.id;
                //com_name = event.issue.fields.components.name;
    
         // console.log(project_key);
          //console.log(parent_key);
          //console.log(com_self);
          //console.log(com_id);
          //console.log(com_name);
     
                request({
                    url: "https://******.atlassian.net/rest/api/2/issue",
                    headers: {
                        "Authorization": auth
                    },
                    method: 'POST',
                    json: {
                        "fields": {
                            "project": {
                                "key": project_key
                            },
                            "parent": {
                                "key": parent_key
                            },
                            "summary": "Analysis",
                            "description": "Provide Technical Analysis. Add the [Story Point Estimate|https://*****.atlassian.net/wiki/display/DEV/How+to+set+estimates+using+story+points] to the Parent",
                            "customfield_10004": 3,
                            "components": event.issue.fields.components,
                            "issuetype": {
                                "id": "5"
                            }
                        }
                    }
                }, function (error, resp, body) {
                    if (error) {
                        console.log(error);
                    }
                });
    
            } else if (issue_type == "bug" && status_received != "issue_created"){
                console.log("this bug is not new");
            }
       
            //if an epic is created, make a story for it
    
            if (issue_type == "epic" && status_received == "issue_created") {
                project_key = event.issue.fields.project.key;
                parent_key = event.issue.key;
           
                var epic_url = "[Click here to go to the Epic|";
                epic_url = epic_url + "https://*****.atlassian.net/browse/" + parent_key + "]";
           
                //console.log(epic_url);
     
     
                request({
                    url: "https://********.atlassian.net/rest/api/2/issue",
                    headers: {
                        "Authorization": auth
                    },
                    method: 'POST',
                    json: {
                        "fields": {
                            "project": {
                                "key": project_key
                            },
                            "summary": "Technical Specification",
                            "customfield_10008": parent_key,
                            "description": "# Create new Page [{color:#59afe1}here{color}|https://********.atlassian.net/wiki/display/DEV/Technical+Specifications] unless this is a very small change in which case the technical specification can be documented on this JIRA. \r\n# Create Stories linked to the same Epic as this JIRA and add the Story Point Estimate \r\n# Update the [{color:#59afe1}requirement specification{color}|https://*******.atlassian.net/wiki/display/DEV/Product+requirements] indicating what stories cover off what requirements.",
                            "customfield_10004": 8,
                            "components": event.issue.fields.components,
                            "issuetype": {
                                "id": "7"
                            }
                        }
                    }
                }, function (error, resp, body) {
                    if (error) {
                        console.log(error);
                    }
                });
           
           
            }
            else if (issue_type == "epic" && status_received != "issue_created"){
                console.log("this epic is not new");
            }
            //run rest of script to calculate old bugs hours if updated (like how tasks work), as well as the subtask
    
            //issue_score = issue_score.toString();
            //issue_score = parseInt(issue_score);
    
            issue_score = Math.round(issue_score);
    
    
            if (issue_score < 0) {
                issue_score = 0;
            }
    
            if (isNaN(issue_score)) {
                issue_score = null;
            }
    
            switch (issue_score) {
            case 4:
                issue_score = 5;
                break;
            case 6:
            case 7:
                issue_score = 8;
                break;
            case 9:
            case 10:
            case 11:
            case 12:
                issue_score = 13;
                break;
            case 14:
            case 15:
            case 16:
            case 17:
            case 18:
            case 19:
            case 20:
                issue_score = 21;
                break;
            default:
            }
    
            if (issue_score >= 22) {
                issue_score = 21;
            }
    
            switch (issue_score) {
            case null:
                original_seconds = "0h";
                break;
            case 0:
                original_seconds = "0h";
                break;
            case 1:
                original_seconds = "1h";
                break;
            case 2:
                original_seconds = "2h";
                break;
            case 3:
                original_seconds = "4h";
                break;
            case 5:
                original_seconds = "8h";
                break;
            case 8:
                original_seconds = "15h";
                break;
            case 13:
                original_seconds = "30h";
                break;
            case 21:
                original_seconds = "60h";
                break;
            default:
                //Just leaves the last set original estimate
            }
    
            //original_seconds is actually seen as hours
            //If integers are used instead, it is counted as minutes
    
            request({
                url: $url,
                headers: {
                    "Authorization": auth
                },
                method: 'PUT',
                json: {
                    "update": {
                        "timetracking": [{
                            "edit": {
                                "originalEstimate": original_seconds
                            }
                        }]
    
                    },
    
                    "fields": {
                        "customfield_10004": issue_score
                    }
    
                }
            }, function (error, resp, body) {
                if (error) {
                    console.log(error);
                }
            });
    
        } else {
            console.log("this is not an issue update");
        }
    
    };
     
Thread Status:
Not open for further replies.