77
88from typing import Any
99import json
10+ import logging
1011
1112import requests
1213from requests .auth import HTTPBasicAuth
1314
15+ from sqlalchemy .orm import Session
16+
1417from pydantic import Field , SecretStr , AnyHttpUrl
1518
1619from jinja2 import Template
2023from dispatch .decorators import apply , counter , timer
2124from dispatch .enums import DispatchEnum
2225from dispatch .plugins import dispatch_jira as jira_plugin
26+ from dispatch .case import service as case_service
27+ from dispatch .incident import service as incident_service
2328from dispatch .plugins .bases import TicketPlugin
29+ from dispatch .project .models import Project
2430
2531from .templates import (
2632 CASE_ISSUE_SUMMARY_TEMPLATE ,
2733 INCIDENT_ISSUE_SUMMARY_NO_RESOURCES_TEMPLATE ,
2834 INCIDENT_ISSUE_SUMMARY_TEMPLATE ,
2935)
3036
37+ from dispatch .config import DISPATCH_UI_URL
38+
39+ log = logging .getLogger (__name__ )
40+
3141
3242class HostingType (DispatchEnum ):
3343 """Type of Jira deployment."""
@@ -261,6 +271,16 @@ def update(
261271 return data
262272
263273
274+ def create_fallback_ticket (id : int , project : Project , db_session : Session ):
275+ resource_id = f"dispatch-{ project .organization .slug } -{ project .slug } -{ id } "
276+
277+ return {
278+ "resource_id" : resource_id ,
279+ "weblink" : f"{ DISPATCH_UI_URL } /{ project .organization .name } /incidents/{ resource_id } ?project={ project .name } " ,
280+ "resource_type" : "jira-error-ticket" ,
281+ }
282+
283+
264284@apply (counter , exclude = ["__init__" ])
265285@apply (timer , exclude = ["__init__" ])
266286class JiraTicketPlugin (TicketPlugin ):
@@ -285,38 +305,51 @@ def create(
285305 db_session = None ,
286306 ):
287307 """Creates an incident Jira issue."""
288- client = create_client (self .configuration )
308+ try :
309+ client = create_client (self .configuration )
289310
290- assignee = get_user_field (client , self .configuration , commander_email )
311+ assignee = get_user_field (client , self .configuration , commander_email )
291312
292- reporter = assignee
293- if reporter_email != commander_email :
294- reporter = get_user_field (client , self .configuration , reporter_email )
313+ reporter = assignee
314+ if reporter_email != commander_email :
315+ reporter = get_user_field (client , self .configuration , reporter_email )
295316
296- project_id , issue_type_name = process_plugin_metadata (incident_type_plugin_metadata )
317+ project_id , issue_type_name = process_plugin_metadata (incident_type_plugin_metadata )
297318
298- if not project_id :
299- project_id = self .configuration .default_project_id
319+ if not project_id :
320+ project_id = self .configuration .default_project_id
300321
301- # NOTE: to support issue creation by project id or key
302- project = {"id" : project_id }
303- if not project_id .isdigit ():
304- project = {"key" : project_id }
322+ # NOTE: to support issue creation by project id or key
323+ project = {"id" : project_id }
324+ if not project_id .isdigit ():
325+ project = {"key" : project_id }
305326
306- if not issue_type_name :
307- issue_type_name = self .configuration .default_issue_type_name
327+ if not issue_type_name :
328+ issue_type_name = self .configuration .default_issue_type_name
308329
309- issuetype = {"name" : issue_type_name }
330+ issuetype = {"name" : issue_type_name }
310331
311- issue_fields = {
312- "project" : project ,
313- "issuetype" : issuetype ,
314- "assignee" : assignee ,
315- "reporter" : reporter ,
316- "summary" : title ,
317- }
332+ issue_fields = {
333+ "project" : project ,
334+ "issuetype" : issuetype ,
335+ "assignee" : assignee ,
336+ "reporter" : reporter ,
337+ "summary" : title ,
338+ }
339+
340+ ticket = create (self .configuration , client , issue_fields )
341+ except Exception as e :
342+ log .exception (
343+ f"Failed to create Jira ticket for incident_id: { incident_id } . "
344+ f"Creating incident ticket with core plugin instead. Error: { e } "
345+ )
346+ # fall back to creating a ticket without the plugin
347+ incident = incident_service .get (db_session = db_session , incident_id = incident_id )
348+ ticket = create_fallback_ticket (
349+ id = incident .id , project = incident .project , db_session = db_session
350+ )
318351
319- return create ( self . configuration , client , issue_fields )
352+ return ticket
320353
321354 def update (
322355 self ,
@@ -378,36 +411,49 @@ def create_case_ticket(
378411 db_session = None ,
379412 ):
380413 """Creates a case Jira issue."""
381- client = create_client (self .configuration )
414+ try :
415+ client = create_client (self .configuration )
382416
383- assignee = get_user_field (client , self .configuration , assignee_email )
384- # TODO(mvilanova): enable reporter email and replace assignee email
385- # reporter = get_user_field(client, self.configuration, reporter_email)
386- reporter = assignee
417+ assignee = get_user_field (client , self .configuration , assignee_email )
418+ # TODO(mvilanova): enable reporter email and replace assignee email
419+ # reporter = get_user_field(client, self.configuration, reporter_email)
420+ reporter = assignee
387421
388- project_id , issue_type_name = process_plugin_metadata (case_type_plugin_metadata )
422+ project_id , issue_type_name = process_plugin_metadata (case_type_plugin_metadata )
389423
390- if not project_id :
391- project_id = self .configuration .default_project_id
424+ if not project_id :
425+ project_id = self .configuration .default_project_id
392426
393- project = {"id" : project_id }
394- if not project_id .isdigit ():
395- project = {"key" : project_id }
427+ project = {"id" : project_id }
428+ if not project_id .isdigit ():
429+ project = {"key" : project_id }
396430
397- if not issue_type_name :
398- issue_type_name = self .configuration .default_issue_type_name
431+ if not issue_type_name :
432+ issue_type_name = self .configuration .default_issue_type_name
399433
400- issuetype = {"name" : issue_type_name }
434+ issuetype = {"name" : issue_type_name }
401435
402- issue_fields = {
403- "project" : project ,
404- "issuetype" : issuetype ,
405- "assignee" : assignee ,
406- "reporter" : reporter ,
407- "summary" : title ,
408- }
436+ issue_fields = {
437+ "project" : project ,
438+ "issuetype" : issuetype ,
439+ "assignee" : assignee ,
440+ "reporter" : reporter ,
441+ "summary" : title ,
442+ }
409443
410- return create (self .configuration , client , issue_fields )
444+ ticket = create (self .configuration , client , issue_fields )
445+ except Exception as e :
446+ log .exception (
447+ (
448+ f"Failed to create Jira ticket for case_id: { case_id } . "
449+ f"Creating case ticket with core plugin instead. Error: { e } "
450+ )
451+ )
452+ # fall back to creating a ticket without the plugin
453+ case = case_service .get (db_session = db_session , case_id = case_id )
454+ ticket = create_fallback_ticket (id = case .id , project = case .project , db_session = db_session )
455+
456+ return ticket
411457
412458 def create_task_ticket (
413459 self ,
0 commit comments