So macht Groovy Scripting in JIRA mehr SpaßIn JIRA Projekten verwende ich in vielen Fällen den Jira Script Runner, um kunden-individuelle Anforderungen zu realisieren. Ob in Form von Validators, Conditions, Postfunctions, Services und Listeners, der Script Runner ermöglicht es relativ schnell, die Wünsche des Kunden umzusetzen. Anbei ein paar Beispiele: Postfunction
import com.avono.jira.plugins.groovyutils.categories.*
use ( Issues, Users ) {
updateIssueInWorkflow(transientVars) { issue ->
issue.setVertreter(currentUser())
// alternativ auch: issue['Vertreter'] = currentUser()
issue['assignee'] = issue['reporter']
issue['Kundenanfrage'] = 'ja' // Auswahllist
issue['Standorte'] = [ 'S', 'HH', 'DO' ] // Mehrfachauswahlliste
issue['resolution'] = null
}
}Listener
import com.avono.jira.plugins.groovyutils.categories.*
use ( Issues ) {
issue.updateAndSaveInListener { issue ->
issue[ 'Verantwortliche Entwickler']
= [ issue['assignee'], issue['Vertreter'] ]
}
} Service
use (Issues,Users) {
'technical_user'.asUser().call {
jqlquery = 'project = "myproject" AND status = "Freigegeben" order by id'
jqlquey.search().each{ issue -> issue.transition('Ausführen') }
}
}Manch JIRA und Groovy erfahrener Entwickler wird an dieser Stelle etwas verwundert sein. Die oben vorgestellten Beispiele sehen so einfach und elegant aus im Vergleich zu gewohnten JIRA Groovy Scripten. Hier noch einmal eine Version des letzen Service Scriptes in der herkömmliche Version:
import ...
String jql = 'project = "myproject" AND status = "Freigegeben" order by id'
String daemonUserName = "technical_user"
int actionId = 14242
def componentManager = ComponentManager.getInstance()
JiraAuthenticationContext ctx = componentManager.getJiraAuthenticationContext()
UserManager userManager = componentManager.getComponentInstanceOfType(UserManager.class)
User daemon = userManager.getUserObject(daemonUserName)
User callingUser = ctx.getLoggedInUser()
try {
ctx.setLoggedInUser(daemon)
SearchService.ParseResult parseResult =
componentManager.getSearchService().parseQuery(ctx.getLoggedInUser(), jql)
if (!parseResult.isValid()) {
// error handling
}
SearchResults results = componentManager.getSearchProvider().search(
parseResult.getQuery(),
ctx.getLoggedInUser(),
PagerFilter.getUnlimitedFilter() )
for ( Issue issue : results.getIssues() ) {
MutableIssue mutableIssue = omponentManager.getIssueManager()
.getIssueObject(issue.getId())
boolean wasIndexing = ImportUtils.isIndexIssues()
try {
ImportUtils.setIndexIssues(true)
WorkflowTransitionUtil workflowTransitionUtil = (WorkflowTransitionUtil)
JiraUtils.loadComponent(WorkflowTransitionUtilImpl.class)
workflowTransitionUtil.setIssue(mutableIssue)
workflowTransitionUtil.setUsername(daemonUserName)
workflowTransitionUtil.setAction(actionId)
ErrorCollection errors = workflowTransitionUtil.validate()
if (errors.hasAnyErrors()) {
// error handling
}
errors = workflowTransitionUtil.progress()
if (errors.hasAnyErrors()) {
// error handling
}
} finally {
ImportUtils.setIndexIssues(wasIndexing)
}
}
} finally {
ctx.setLoggedInUser(callingUser);
}
Wenn man die ersten einfachen Beispiel betrachtet, dann stellen sich die folgenden Fragen:
Die Antwort zu all den Fragen ist: Es wird eine eigene Java-Bibliothek verwendet, die die manchmal etwas umständliche Java-API von JIRA kapselt. Diese Java Bibliothek nutzt Groovy Meta-Programmierung in Form von Catgeories (http://groovy.codehaus.org/Groovy+Categories), um die sonst übliche Komplexität von JIRA Groovy Scripten zu reduzieren. Groovy erlaubt es, Klassen zur Laufzeit für eigene Erweiterungen zu öffnen und neue Methoden hinzuzufügen. Und hiervon wird in den Beispielen oben intensiv Gebrauch gemacht, so bekommt die Issue Klasse neue Methoden zum Lesen und Schreiben von benutzerdefinierten Feldern. java.lang.String Objekte können in User Objekte oder JQL Queries transformiert werden und auf Issues können direkt Transitionen angestoßen werden. Um diesen Groovy-Mechanismus zu nutzen, muss man nur eine Java/Groovy Klasse (Category) mit einer Reihe von statischen Methoden breitstellen. Per Konvention muss der erste Parameter dem Objekttypen entsprechen, den man öffnen möchte. Aktiviert wird ein Category durch die Verwendung des Schlüsselwortes use. Ein oder mehrere Categories sind dann innerhalb einer an use übergebenen Closure verwendbar. Mein persönliches Fazit: Lange Importsequenzen entfallen, fehleranfällige Konstrukte wie die korrekte Handhabung der Änderungshistorie werden weggekapselt, gängige Script-Aufgaben, wie das Ausführen von Aufgaben im Kontext eines anderen Benutzers, die Suche nach Vorgängen und die Transition von Vorgängen gehen leicht von der Hand. Die Groovy-Scripte werden einfach, elegant, kurz, verständlich und nachvollziehbar. Groovy Scripting für JIRA macht mit der Bibliothek wieder Spaß.
| Willkommen auf dem avono BlogHier auf dem avono Blog finden Sie in regelmäßigen Abständen sowohl technische Neuigkeiten aus unserer Partnerproduktwelt als auch nützliche Entwicklertipps.Und jetzt kommt der obligatorische Disclaimer: Die Ausführungen der Blogeinträge spiegeln nicht die Meinung der avono AG sondern nur die Sicht der einzelnen Autoren wider. Weitere Blogbeiträge JIRA5 – Statusprüfung abgegebener Aufgaben
am 30. April 2012 FishEye als Git Repository Manager
am 12. April 2012 Unite - Erste europäische Atlassian Anwenderkonferenz
am 11. April 2012 So macht Groovy Scripting in JIRA mehr Spaß
am 22. Dezember 2011 Mens sana in corpore sano
am 15. August 2011 |
