Für JIRA-Vorgänge lassen sich standardmäßig jede Menge benutzerdefinierte Felder hinzufügen, die jedoch vom Bearbeiter dann manuell ausgefüllt werden müssen. Um in benutzerdefinierten Feldern automatisch Werte anzeigen zu lassen (read-only), die auf Berechnungen auf Werten aus der Datenbank basieren, können Scripted Custom Fields verwendet werden.
In folgendem Beispiel wird ein Feld zu einem JIRA-Vorgang hinzugefügt, in welchem angezeigt wird, wie lange sich ein JIRA-Ticket in einem bestimmten Workflow-Status befunden hat. Dies ist beispielsweise für die Ausgabe eines Berichts über die Bearbeitungsdauer der Tickets in einem Projekt interessant. Alle Felder können nämlich auch in Spalten eines Excel-Exports oder in Diagrammen auf dem Dashboard angezeigt und ausgewertet werden.
Hierzu muss zunächst das kostenlose Script-Runner-Plugin in der JIRA-Instanz installiert werden.
Als nächstes wird in der System-Administration von JIRA ein neues benutzerdefiniertes Feld angelegt. Um die Zeit des Vorgangs in dem Status „In Progress“ zu berechnen, erstellt man ein Feld „Time In Progress“ und benutzt dafür den durch das Plugin hinzugefügten neuen Typ „Scripted Field“.
Dieses Feld muss einem Screen zugeordnet werden, damit es sichtbar wird. Soll das Feld aber nur in der Suche und nicht in der Vorgangsansicht sichtbar sein, so kann man einen Screen „Secret Screen“ erstellen und das Feld nur diesem Screen zuweisen. Der Screen selbst taucht nirgendwo auf.
In der Administration von JIRA findet man unter Add-Ons nun einen neuen Menüblock für das Script Runner Plugin und dort den Punkt „Scripted Fields“. Das soeben angelegte Feld „Time in Status in Progress“ wird hier angezeigt. Diesem Feld kann nun ein ausführbares Script in der Programmiersprache Groovy hinzugefügt werden. Zu beachten ist hierbei noch, daß als Template-Typ des Scripted Fields „Text-Field (multi-line)“ ausgewählt wird und kein Searcher konfiguriert wird.
Der Code für das Script zum Anzeigen der Zeit des Vorgangs im Status „In Progress“ sieht folgendermaßen aus:
import com.atlassian.core.util.DateUtils import com.atlassian.jira.ComponentManager import com.atlassian.jira.issue.history.ChangeItemBean def componentManager = ComponentManager.getInstance() def changeHistoryManager = componentManager.getChangeHistoryManager() def inProgressName = "In Progress" def rt = [0] changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {ChangeItemBean item -> def timeDiff = System.currentTimeMillis() - item.created.getTime() if (item.fromString == inProgressName) { rt << -timeDiff } if (item.toString == inProgressName){ rt << timeDiff } } // NOTE: doesn't show anything if less than 60 seconds DateUtils.getDurationString(Math.round(rt.sum() / 1000))
Des weiteren wurde ein Feld hinzugefügt zum Anzeigen der Zeit im Status Open „Time in Status Open“. Alle Schritte wurden durchgeführt wie bei dem vorangegangen Feld, nur das Script sieht etwas anders aus:
import com.atlassian.core.util.DateUtils import com.atlassian.jira.ComponentManager import com.atlassian.jira.issue.history.ChangeItemBean import com.atlassian.jira.issue.Issue def componentManager = ComponentManager.getInstance() def changeHistoryManager = componentManager.getChangeHistoryManager() log.warn("+++++++++++++++++++++++") def rt = [0] def createTime=issue.getCreated().getTime() // getTime() tranfer to milliseconds log.warn("create time:"+issue.getCreated().toString()+"to millisecond:"+issue.getCreated().getTime()) def firstStart=changeHistoryManager.getChangeItemsForField(issue, "status").find{ it.fromString=="Open" && it.toString=="In Progress" }?.getCreated() if(firstStart){ //has Start Progress Duration=firstStart?.getTime()-createTime // NOTE: doesn't show anything if less than 60 seconds log.warn("Duration:"+Duration+"round:"+Math.round(Duration / 1000)+"timespent:"+DateUtils.getDurationString(Math.round(Duration / 1000))) def timeSpent=DateUtils.getDurationString(Math.round(Duration / 1000)) if(timeSpent){ return timeSpent }else{ //negative value or less than one minute return "less than one minute" } }else{ //there aren't workflow transitions executed yet. def timeSpent = System.currentTimeMillis() - createTime DateUtils.getDurationString(Math.round(timeSpent/1000)) }
Ruft man nun den Vorgangsnavigator auf und konfiguriert die anzuzeigenden Spalten so, daß auch die beiden neuen Felder angezeigt werden, so hat man für alle Vorgänge eines Filters die Zeit in den Status Open und In Progress vorliegen und kann das Ganze auch in einen Bericht oder eine Excel-Tabelle exportieren.
Hey very nice site!! Man .. Beautiful .. Amazing .. I will bookmark your blog and take the feeds alsoI am happy to find a lot of useful info here in the post, we need work out more techniques in this regard, thanks for sharing. . . . . . dgbeddkedebe