JIRA Integration
Atlassian provides a REST API which can be used to interact with Jira instances (both on-premise and cloud). This API can be utilized to automate ticket creation and updates directly from Connexion. This is a quick sample showing how a Jira ticket can be created when Connexion logs an event.
This feature leverages the Custom Alerting
feature, which lets you inject your own logic within Connexion’s alerting/eventing pipeline.
This sample uses the Atlassian.Jira
assembly (and dependencies) which wrap the JIRA REST API. The goal of this sample is to trap a specific event (error number 5440), check to see if there is an existing open ticket, and if not, create a new one. This is the test code:
using System;
using Connexion.Core;
using System.Threading.Tasks;
using System.Collections.Generic;
using Atlassian.Jira;
using System.Linq;
namespace Connexion.Device
{
public class CustomAlerting : BaseCustomAlerting
{
private readonly string _jiraUrl = "https://conevity.atlassian.net";
private readonly string _jiraUser = "youremail@yourdomain.com";
private readonly string _jiraToken = "Your_Token_Here";
private readonly string _jiraProject = "CNXN";
private readonly HashSet<int> _trackedEventIds = new HashSet<int>(new [] {5440}); // event ids to track
public override async Task OnAlertReceivedAsync(AlertReceivedEventArgs arg)
{
if(!arg.DeviceKey.HasValue && string.IsNullOrWhiteSpace(arg.ChannelName))
return;
if(!arg.Event.EventId.HasValue || !_trackedEventIds.Contains(arg.Event.EventId.Value))
return; // not tracking this event id
// uri which can be used to launch CXN and navigate to the correct channel
var uri = $"cxn://{Environment.MachineName}/{arg.DeviceKey:N}";
var summary = $"{arg.Event.EventId.Value}: {arg.GroupName} > {arg.TabName} > {arg.ChannelName}";
try
{
await CreateJiraIssueAsync(summary, arg.Event.Event, "Task", uri, arg.ChannelKey.Value.ToString("N")).ConfigureAwait(false);
}
catch(Exception ex)
{
MessageChannel.Logger.Write(EventSeverity.Error, $"Unexpected error in JIRA communication: {ex}");
}
}
private async Task CreateJiraIssueAsync(string summary, string description, string type, string uri, string channelKey)
{
try
{
var settings = new JiraRestClientSettings();
settings.EnableUserPrivacyMode = true;
var jira = Jira.CreateRestClient(_jiraUrl, _jiraUser, _jiraToken);
var existingIssue = jira.Issues.Queryable.FirstOrDefault(i => i.Project == new LiteralMatch(_jiraProject) && i.Summary == summary && (i.Status == "To Do" || i.Status == "In Progress"));
if(existingIssue != null)
{
MessageChannel.Logger.Write(EventSeverity.Info, $"JIRA issue {existingIssue.Key} already exists");
return;
}
var issue = jira.CreateIssue(_jiraProject);
issue.Type = type;
issue.Summary = summary;
issue.Description = description;
issue["ConnexionUri"] = uri; // custom field in jira
issue["ChannelKey"] = channelKey; // custom field in jira
await issue.SaveChangesAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
MessageChannel.Logger.Write(EventSeverity.Error, "Failed to create JIRA issue: {0}", ex);
}
}
}
}
The above code first searches JIRA for an existing ticket with a matching summary (and a non-closed status). If one is found, no new ticket is created; otherwise a new ticket is created. Two custom fields have been added to JIRA:
ConnexionUri
is a uri which can be clicked on within the JIRA web page to launch and/or navigate the Connexion UI to the channel associated with this ticket.
ChannelKey
is a GUID which identifies the target channel. This field can be used by other custom workflows (in JIRA and Connexion) to query and track tickets.