Skip to content

Console

Nikita Teplov edited this page May 27, 2019 · 5 revisions

A great debugging tool for your scripts

You can run the script once and make sure that everything works as it was intended there are no errors. This saves a lot of time in comparison with debugging on workflow. Imagine that you need to automatically assign an issue to a project leader if no component manager is appointed. The console will allow you to test your script with one click, without endlessly editing and publishing workflow. To do this, simply define a specific task in the issue variable and start testing:

Code example

import com.atlassian.jira.component.ComponentAccessor;
def issue = ComponentAccessor.issueManager.getIssueObject('TEST-123')

The best tool for building custom reports

For example, let's create a report showing activity by tasks over a period of time by JQL filter

Code example

import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter

import com.atlassian.jira.component.ComponentAccessor

import groovy.transform.ToString 
import com.atlassian.jira.config.properties.APKeys


def days = 7
def jql = """reporter in (currentUser())""" //
def title = "Activity on tasks ${jql} for ${days} days"

def historyReportCreator = new HistoryActivityForDaysReportCreater()
return historyReportCreator.createHTMLReport(title, jql, days)

def class HistoryActivityForDaysReportCreater{
    def baseUrl = ComponentAccessor.getApplicationProperties().getString(APKeys.JIRA_BASEURL)

    def createHTMLReport(String title, String jql, Integer days){
        def issueHistoryItems = getHistoryDataForDays(jql, days)
        return createHTMLTable(title, issueHistoryItems)
    }

    def getHistoryDataForDays(String jql, Integer days){
        def issues = getIssuesByJQL(jql)
        def dateStart = addDays(new Date(), -days)
        def chm = ComponentAccessor.changeHistoryManager
        def cm = ComponentAccessor.commentManager

        def issueHistoryItems = [:]
        issues.each{issue->
            def items = []
            chm.getChangeHistoriesSince(issue, dateStart).each{ch->
                ch.getChangeItems().each{item->
                    if(item.field == 'Attachment'){
                        items << createAttachHistoryItem(ch, item)
                    }  else {
                        items << createHitoryItem(ch, item)
                    }
                }
            }
            
            cm.getComments(issue).findAll{
                it.getCreated() >= dateStart
            }.each{comment->
                items << createCommentHistoryItem(comment)
            }
            items = items.sort{it.time}
            issueHistoryItems.put(issue, items)
        }
        return issueHistoryItems
    }

    def createCommentHistoryItem(comment){
        return new HistoryItem(time: comment.getCreated().time,
                                     reporter: comment.getAuthorApplicationUser()?.displayName,
                                     field: "Сomment",
                                     oldvalue: '',
                                     newvalue: comment.getBody() 
                                     )
    }

    def createHitoryItem(changeHistory, item){
        return new HistoryItem(time: changeHistory.getTimePerformed().time,
                                         reporter: changeHistory.getAuthorUser()?.displayName,
                                         field: item.field,
                                         oldvalue: (item.oldstring == null)?'':item.oldstring,
                                         newvalue: item.newstring
                                         )
    }

    def createAttachHistoryItem(changeHistory, item){
        def idAttach
        try{
            idAttach = Long.valueOf(item.newvalue)
        } catch (Exception e){
            idAttach = null
            log.warn "${e} ${issue} ${item}"
        }
        return new HistoryItem(time: changeHistory.getTimePerformed().time,
                         reporter: changeHistory.getAuthorUser()?.displayName,
                         field: item.field,
                         oldvalue: (item.oldstring == null)?'':item.oldstring,
                         newvalue: (item.newstring == null)?'':item.newstring,
                         idAttach: idAttach
                         )
    }

    def addDays(d, days)
    {
        d.setTime( d.getTime() + (long)days*1000*60*60*24 - d.hours*60*60*1000 - d.minutes*60*1000 - d.seconds*1000 );
        return d
    }

    @ToString
    def class HistoryItem{
        def time
        def reporter
        def field
        def oldvalue
        def newvalue
        def idAttach    
    }

    def getIssuesByJQL(String jql){
        def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
        def searchProvider = ComponentAccessor.getComponent(SearchProvider)
        def issueManager = ComponentAccessor.getIssueManager()
        def user = getCurrentUser()

        def query = jqlQueryParser.parseQuery(jql)
        def result = searchProvider.search(query, user, PagerFilter.getUnlimitedFilter())
        def documentIssues = result.getIssues()

        return documentIssues.collect{ComponentAccessor.issueManager.getIssueObject(it.id)}
    } 

    def getCurrentUser(){
        ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
    }

    def createHTMLTable(title ,issueItems){
        def html = "<table class='aui' border='1'>"
        html += """<caption>${title}</caption>"""
        html += "<tr><th>Key</th><th>Summary</th><th>Status</th><th>Date</th><th>Author</th><th>Field</th><th>Old value</th><th>New value</th></tr>"//
        issueItems.each{issue, items->
            for(def i = 0; i < items.size();i++){
                def coldspan = (items[i].oldvalue == null || items[i].oldvalue == '')
                def isAttach = (items[i].field == 'Attachment')
                if(i == 0){
                    html += "<tr>"
                    html += "<td rowspan='${items.size()}'><a href='${baseUrl}/browse/${issue.key}'>${issue.key}</a></td>"
                    html += "<td rowspan='${items.size()}'><a href='${baseUrl}/browse/${issue.key}'>${issue.summary}</a></td>"
                    html += "<td rowspan='${items.size()}'>${issue.status.name}</td>"
                    html += "<td>${new Date(items[i].time)}</td>"
                    html += "<td>${items[i].reporter}</td>"
                    html += "<td>${items[i].field}</td>"
                    html += "<td>${items[i].oldvalue}</td>"
                    if(coldspan){
                        if(isAttach){
                            if(items[i].idAttach == null){
                                html += "<td>${items[i].newvalue}</td>"
                            } else {
                                try{
                                    def att = ComponentAccessor.attachmentManager.getAttachment(items[i].idAttach)
                                    html += "<td><a href='${baseUrl}/secure/attachment/${items[i].idAttach}/${att.getFilename()}'>${att.getFilename()}</a></td>"
                                } catch (Exception e) {
                                    log.warn "create link ${e} ${issue} ${items[i]}"
                                    html += "<td>${items[i].newvalue}</td>"
                                }
                            }
                        } else {
                            html += "<td>${items[i].newvalue}</td>"
                        }
                       // html += "<td coldspan='2'>${items[i].newvalue}</td>"
                        //html += "<td></td>"
                    } else {
                        //html += "<td>${items[i].oldvalue}</td>"
                        html += "<td>${items[i].newvalue}</td>"
                    }
                    html += "</tr>"
                } else {
                    html += "<tr>"
                    html += "<td>${new Date(items[i].time)}</td>"
                    html += "<td>${items[i].reporter}</td>"
                    html += "<td>${items[i].field}</td>"
                    html += "<td>${items[i].oldvalue}</td>"
                    if(coldspan){
                        if(isAttach){
                            if(items[i].idAttach == null){
                                html += "<td>${items[i].newvalue}</td>"
                            } else {
                                try{
                                    def att = ComponentAccessor.attachmentManager.getAttachment(items[i].idAttach)
                                    html += "<td><a href='${baseUrl}/secure/attachment/${items[i].idAttach}/${att.getFilename()}'>${att.getFilename()}</a></td>"
                                } catch (Exception e) {
                                    log.warn "create link ${e} ${issue} ${items[i]}"
                                    html += "<td>${items[i].newvalue}</td>"
                                }
                            }
                        } else {
                            html += "<td>${items[i].newvalue}</td>"
                        }
                        //html += "<td></td>"
                    } else {
                        //html += "<td>${items[i].oldvalue}</td>"
                        html += "<td>${items[i].newvalue}</td>"
                    }
                    html += "</tr>"
                }
            }
        }

        html += "</table>"
    }
}

Do not forget to tick the html rendering

One-time launch of service scripts.

You can make a request to the REST API, you can clear the issue history :), or you can re-index a couple of tasks after the recent failure of the Data Center

Issue reindex code example

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.index.IssueIndexingService

@WithParam(displayName='issueKey', type=ParamType.STRING)
String issueKey

reIndex(ComponentAccessor.issueManager.getIssueObject(issueKey))

def reIndex(issue){
  def issueIndexingService = ComponentAccessor.getComponent(IssueIndexingService)
  issueIndexingService.reIndex(issue)
  return 'Done'
}