jbi/bugzilla/service.py (68 lines of code) (raw):

import logging from functools import lru_cache import requests from dockerflow import checks from statsd.defaults.env import statsd from jbi import environment from .client import BugzillaClient, BugzillaClientError from .models import Bug settings = environment.get_settings() logger = logging.getLogger(__name__) class BugzillaService: """Used by action workflows to perform action-specific Bugzilla tasks""" def __init__(self, client: BugzillaClient) -> None: self.client = client def add_link_to_see_also(self, bug: Bug, link: str): """Add link to Bugzilla ticket""" return self.client.update_bug(bug.id, see_also={"add": [link]}) def get_description(self, bug_id: int): """Fetch a bug's description A Bug's description does not appear in the payload of a bug. Instead, it is "comment 0" """ comment_list = self.client.get_comments(bug_id) comment_body = comment_list[0].text if comment_list else "" return str(comment_body) def refresh_bug_data(self, bug: Bug): """Re-fetch a bug to ensure we have the most up-to-date data""" refreshed_bug_data = self.client.get_bug(bug.id) # When bugs come in as webhook payloads, they have a "comment" # attribute, but this field isn't available when we get a bug by ID. # So, we make sure to add the comment back if it was present on the bug. updated_bug = refreshed_bug_data.model_copy(update={"comment": bug.comment}) return updated_bug def list_webhooks(self): """List the currently configured webhooks, including their status.""" return self.client.list_webhooks() def check_bugzilla_connection(self): if not self.client.logged_in(): return [checks.Error("Login fails or service down", id="bugzilla.login")] return [] def check_bugzilla_webhooks(self): # Do not bother executing the rest of checks if connection fails. if messages := self.check_bugzilla_connection(): return messages # Check that all JBI webhooks are enabled in Bugzilla, # and report disabled ones. try: jbi_webhooks = self.list_webhooks() except (BugzillaClientError, requests.HTTPError) as e: return [ checks.Error( f"Could not list webhooks ({e})", id="bugzilla.webhooks.fetch" ) ] results = [] if len(jbi_webhooks) == 0: results.append( checks.Warning("No webhooks enabled", id="bugzilla.webhooks.empty") ) for webhook in jbi_webhooks: # Report errors in each webhook statsd.gauge(f"jbi.bugzilla.webhooks.{webhook.slug}.errors", webhook.errors) # Warn developers when there are errors if webhook.errors > 0: results.append( checks.Warning( f"Webhook {webhook.name} has {webhook.errors} error(s)", id="bugzilla.webhooks.errors", ) ) if not webhook.enabled: results.append( checks.Error( f"Webhook {webhook.name} is disabled ({webhook.errors} errors)", id="bugzilla.webhooks.disabled", ) ) return results @lru_cache(maxsize=1) def get_service(): """Get bugzilla service""" client = BugzillaClient( settings.bugzilla_base_url, api_key=str(settings.bugzilla_api_key) ) return BugzillaService(client=client)