29.8.18
Development

Systeme an Jira anbinden

In diesem Artikel wird beschrieben, wie man Anwendungen über die REST-API an Jira anbinden kann, um neue Vorgänge zu erstellen.

Über Jira

Ein in der agilen Softwareentwicklung weit verbreitetes Tool ist „Jira Software“ aus dem Hause Atlassian. Primär dient es zur Verwaltung von Aufgaben („Vorgänge“ oder „9“ genannt), die auf verschiedenen Boards eingeplant und verfolgt werden können.

Einer der großen Vorteile ist der hohe Grad an Anpassbarkeit. Standardmäßig verfügt ein Jira-Vorgang beispielsweise über eine Kurzbeschreibung, eine Priorität und einen Vorgangstyp (User-Story, Fehler, Task, …). Je nach Anwendungsfall können Vorgänge aber auch um weitere, eigene Felder („custom fields“) ergänzt werden. Auch die Prozessschritte, die ein Vorgang durchlaufen muss, lassen sich an die eigenen Bedürfnisse anpassen.

Zudem bietet Jira Schnittstellen an, um mit anderen Systemen kommunizieren zu können: Über eine REST-API lassen sich beispielsweise automatisiert Vorgänge anlegen, während über konfigurierbare Webhooks wiederum andere Systeme über Änderungen an einem Vorgang benachrichtigt werden können. In den folgenden Abschnitten untersuchen wir, wie eine solche Anbindung an Jira aussehen kann.

Der Anwendungsfall

In unserem Beispiel gehen wir von einer Callcenter-Software aus, mit der die Kundenberater die Anliegen der Kunden erfassen. Jeder Anruf eines Kunden wird dabei vom Kundenberater anhand verschiedener Merkmale kategorisiert und mit allen notwendigen Informationen gepflegt. Bei dem so erfassten Anliegen handelt es sich um unser ins Jira zu übertragende Geschäftsprojekt, welches wir schlicht CallCenterTicket nennen.

Allerdings muss berücksichtigt werden, dass die Kundenberater in verschiedenen Bereichen arbeiten und für jeden Bereich die Jira-Prozesse anders definiert sind. In der Callcenter-Software sind alle Kundenanliegen identisch aufgebaut, doch die daraus abgeleiteten Jira-Vorgänge können ganz andere Strukturen aufweisen. Eine Information, die Bereich A in einem bestimmten Jira-Feld benötigt, kann für Bereich B irrelevant sein. Unsere Anbindung muss also je nach Kontext entscheiden können, welche Werte in welches Jira-Feld geschrieben werden sollen. Als erstes prüfen wir, in welcher Form wir die Daten an Jira übermitteln können.

Die Schnittstelle ansprechen

Wie schon erwähnt, bietet Jira eine REST-Schnittstelle an. Die aktuelle Version der API ist hier dokumentiert. Wenn man die notwendigen API-Calls nicht manuell implementieren möchte, kann man stattdessen das NuGet-Paket Atlassian.SDK verwenden, mit dem verschiedene Atlassian-Produkte angesteuert werden können. Ein neuer Jira-Vorgang lässt sich so recht einfach anlegen:

 var client = Jira.CreateRestClient("https://my-jira.url", "Jira-Username", "Jira-Password");  
 var issue = client.CreateIssue("PROJECTKEY");  
 issue.Summary = "Titel des Vorgangs";  
 issue.Description = "Beschreibung des Vorgangs";  
 issue.Type = "1";  
 issue.Priority = "3";  
 issue.CustomFields.AddById("customfield_10036", "Inhalt eines CustomFields");  
 issue.SaveChanges();  

Jira arbeitet hier tatsächlich größtenteils mit Strings als Schlüssel für Felder und ihre möglichen Werte. Diese Schlüssel sind jedoch nicht fix, sondern müssen abhängig von der Jira-Konfiguration ebenfalls angepasst werden. Dies muss bei der Entwicklung unserer Anbindung berücksichtigt werden.

Im ersten Schritt erstellen wir aber eine neue Komponente, in der alle API-Calls an das Jira-System stattfinden. Passenderweise nennen wir diese Komponente JiraService. Der JiraService ist nur für die Erstellung des Issues im Jira zuständig. Würden wir ihm direkt unser Geschäftsobjekt CallCenterTicket übergeben, hätten wir eine ungewollte Abhängigkeit zu unserer Geschäftslogik. Daher führen wir als Zwischenschicht eine neue Datenklasse JiraIssueData ein, die bereits alle Jira-relevanten Daten enthält. Unser JiraService muss diese Datenklasse dann lediglich noch auslesen und entsprechende API-Calls ausführen. Wie genau diese Datenklasse mit den richtigen Informationen befüllt wird betrachten wir später. Hier zunächst eine einfache Variante des JiraService:

 public class JiraService  
 {  
   public void CreateIssue(JiraIssueData issueData)  
   {  
     var client = Jira.CreateRestClient("https://my-jira.url", "Jira-Username", "Jira-Password");  
     var issue = client.CreateIssue(issueData.ProjectKey);  
     issue.Summary = issueData.Summary;       
     issue.Description = issueData.Description;  
     issue.Type = issueData.IssueType;  
     issue.Priority = issueData.Priority;  
     foreach (var customField in issueData.CustomFields)  
     {  
       issue.CustomFields.AddById(customField.Key, customField.Value);  
     }  
     issue.SaveChanges();  
   }  
 }  
 public class JiraIssueData  
 {  
   public string ProjectKey { get; set; }  
   public string Summary { get; set; }  
   public string Description { get; set; }  
   public string IssueType { get; set; }  
   public string Priority { get; set; }  
   public Dictionary<string, string> CustomFields { get; set; }  
 }  

Die Verbindungsdaten zum Jira-System sollten natürlich keinesfalls fest im Code stehen, doch für unser Beispiel belassen wir es mal dabei. Hiermit könnte man schon Jira-Vorgänge anlegen. Doch wie gelangen wir vom Geschäftsobjekt CallCenterTicket nun zum erforderlichen JiraIssueData-Objekt?

Die Daten verpacken

Bei der Anlage des Jira-Vorgangs müssen wir folgende Datenquellen berücksichtigen:

  • Die Daten des CallCenterTicket selbst
  • Zusatzinformationen, die der Kundenberater erst bei der Anlage des Jira-Tickets angibt (wie beispielsweise das Jira-Projekt, dem der Vorgang zugeordnet werden soll)
  • Die Jira-Konfiguration, die für den Kundenberater gilt

Wir brauchen also eine Komponente, die diese Datenquellen entgegennimmt und daraus ein JiraIssueData-Objekt erzeugt. Das CallCenterTicket gibt es in unserer Geschäftslogik bereits (wird hier aber nicht weiter beschrieben). Legen wir nun noch Klassen für die beiden anderen Datenquellen an:

// Die für den aktuellen Kundenberater gültige Konfiguration
public class JiraConfiguration
{
    public string CustomerFieldKey { get; set; }
    public string OriginFieldKey { get; set; }
    public string IssueType { get; set; }
    public string IssuePriority { get; set; }
}

// Die vom Kundenberater manuell ausgewählten Optionen zum Jira-Vorgang
public class JiraIssueOptions
{
    public string JiraProject { get; set; }
    public JiraIssueTemplate Template { get; set; }
}

public enum JiraIssueTemplate
{
    Simple,
    Advanced
}

Der Kundenberater kann hier noch das Jira-Projekt auswählen, zu dem der Vorgang erstellt werden soll und auch ein Template, welches gleich noch eine Rolle spielt. Alle anderen Parameter werden über die JiraConfiguration festgelegt, die für jeden Kundenberater hinterlegt ist.

Führen wir diese Datenquellen nun über eine simple JiraIssueDataFactory zusammen:

public class JiraIssueDataFactory
{
    public static JiraIssueData Create(
        CallCenterTicket ticket, 
        JiraIssueOptions options, 
        JiraConfiguration configuration)
    {
        var issueData = new JiraIssueData
        {
            ProjectKey = options.JiraProject,
            Summary = ticket.Summary,
            IssueType = configuration.IssueType,
            Priority = configuration.IssuePriority
        };

        var issueDescription = ticket.ErrorDescription;
        if (options.Template == JiraIssueTemplate.Advanced)
        {
            issueDescription += $"{Environment.NewLine}- {ticket.Workaround}";
        }
        issueData.Description = issueDescription;

        if (!string.IsNullOrEmpty(configuration.CustomerFieldKey))
        {
            issueData.CustomFields.Add(configuration.CustomerFieldKey, ticket.CustomerDisplayText);
        }

        return issueData;
    }
}

Letztlich wird hier festgelegt, wie der zu erstellende Jira-Vorgang, unter Berücksichtigung der drei oben genannten Datenquellen aussehen soll. Hier wird beispielsweise die Issue-Beschreibung erweitert, wenn der Kundenberater als Template „Extended“ ausgewählt hat. Zudem wird der „CustomerDisplayText“ nur übernommen, wenn in der Konfiguration für den Kundenberater das entsprechende custom field gepflegt ist.

Wir erhalten durch die Factory eine Instanz von JiraIssueData, die wir an den zuvor erstellten JiraService weitergeben können.

Fazit

Das Erzeugen der Vorgänge im Jira selbst ist Dank der REST-API und des SDK-Packages recht einfach. Komplizierter ist das Zusammensuchen der relevanten Daten. Dieses Beispiel ist einfach gehalten. Wenn die Logik in der JiraIssueDataFactory komplexer wird und noch mehr Kriterien berücksichtigt werden müssen, empfiehlt es sich, die komplexen Teilbereiche wieder in eigene Komponenten auszulagern.

Unabhängig davon kann eine solche Factory nach demselben Muster auch für andere Geschäftsobjekte implementiert werden. Das Anpassen des JiraService ist nicht erforderlich, da die JiraIssueData-Instanz durch die Factory bereits mit allen notwendigen Informationen befüllt wird.

No items found.

Weitere Artikel

No items found.
Wie können wir Sie beraten?
Telefon
Online Beratung
Kontaktanfrage
Telefon
Wir freuen uns auf Ihren Anfruf
+49 (0) 721-619096-0
+49 (0) 721-619096-19
Für Sie erreichbar von
Mo bis Fr 8-16 Uhr
Online Beratung
Buchen Sie online einen für Sie passenden Termin
Wir freuen uns auf Ihre Nachricht
Wenn Du wissen möchtest, welche Daten wir ver­ar­beiten und wie lange wir diese speichern, findest du weiter­führende Infor­mationen in unserer Daten­schutz­erklärung.
Vielen Dank! Ihre Kontaktanfrage wurde von uns empfangen!
Oh nein! Irgendwas ist schiefgelaufen. Probieren Sie es bitte noch einmal!
Kontakt