Skip to content

raid ¤

RAID is ManoMano's internal issue dispatcher.

It works with Slack and Jira to create, update and close issues.

It is currently not configurable.

admin ¤

client ¤

RaidJiraClient ¤

RaidJiraClient()

Bases: JiraClient

Source code in src/firefighter/jira_app/client.py
def __init__(self) -> None:
    self.url = RAID_JIRA_API_URL

add_attachments_to_issue staticmethod ¤

add_attachments_to_issue(issue_id: str | int, urls: list[str]) -> None

Add attachments to a Jira issue.

Parameters:

  • issue_id (str | int) –

    the Jira issue id

  • urls (list[str]) –

    list of urls to the attachments

Raises:

  • JiraAttachmentError

    if there is an error while adding any attachment

Source code in src/firefighter/raid/client.py
@staticmethod
def add_attachments_to_issue(issue_id: str | int, urls: list[str]) -> None:
    """Add attachments to a Jira issue.

    Args:
        issue_id (str | int): the Jira issue id
        urls (list[str]): list of urls to the attachments

    Raises:
        JiraAttachmentError: if there is an error while adding any attachment
    """
    http_client = HttpClient()
    for i, url in enumerate(urls):
        index = url.rfind(".")
        extension = url[index:]
        try:
            response = http_client.get(url)
            response.raise_for_status()  # Raises an exception if status code is not 2XX

            in_memory_file = io.BytesIO(response.content)

            client.jira.add_attachment(
                issue=issue_id,
                attachment=in_memory_file,
                filename=f"image{i}{extension}",
            )

        except (HTTPError, JIRAError) as err:
            msg = f"Error while adding attachment to issue: {err}"
            raise JiraAttachmentError(msg) from err

get_jira_user_from_jira_id ¤

get_jira_user_from_jira_id(jira_account_id: str) -> JiraUser

Look for a Jira User in DB, if not found, fetch it from Jira API.

Parameters:

  • jira_account_id (str) –

    Jira account id

Raises:

  • JiraUserNotFoundError

    User not found in Jira nor in DB

  • JiraUserDatabaseError

    Unable to create user in DB

  • ValueError

    Empty jira_account_id

Returns:

  • JiraUser ( JiraUser ) –

    Jira user object

Source code in src/firefighter/jira_app/client.py
def get_jira_user_from_jira_id(self, jira_account_id: str) -> JiraUser:
    """Look for a Jira User in DB, if not found, fetch it from Jira API.

    Args:
        jira_account_id (str): Jira account id

    Raises:
        JiraUserNotFoundError: User not found in Jira nor in DB
        JiraUserDatabaseError: Unable to create user in DB
        ValueError: Empty jira_account_id

    Returns:
        JiraUser: Jira user object
    """
    if jira_account_id is None or jira_account_id == "":
        err_msg = f"Jira account id is empty ('{jira_account_id}')"
        raise ValueError(err_msg)

    # Look in the DB
    try:
        return JiraUser.objects.get(id=jira_account_id)
    except JiraUser.DoesNotExist:
        logger.debug(
            f"Jira user {jira_account_id} not found in DB, fetching from Jira API"
        )
    logger.info("User %s not found in DB. Check sync user task.", jira_account_id)

    # Look on JIRA API
    jira_api_user, email = self._get_user_from_api(jira_account_id)

    username: str = email.split("@")[0]
    # Check if we have user with same email
    try:
        user: User = User.objects.select_related("jira_user").get(email=email)
        if (
            hasattr(user, "jira_user")
            and user.jira_user
            and isinstance(user.jira_user, JiraUser)
        ):
            return user.jira_user
        try:
            return JiraUser.objects.create(
                id=jira_account_id,
                user=user,
            )
        except db.IntegrityError as e:
            logger.exception("Error creating user %s", jira_account_id)
            raise JiraUserDatabaseError("Unable to create user") from e

    except User.DoesNotExist:
        logger.warning("User %s not found in DB. Creating it...", jira_account_id)
        user = self._create_user_from_jira_info(
            jira_account_id, jira_api_user, email, username
        )

    try:
        return JiraUser.objects.create(
            id=jira_account_id,
            user=user,
        )
    except db.IntegrityError as e:
        logger.exception("Error creating user %s", jira_account_id)
        raise JiraUserDatabaseError("Unable to create user") from e

get_jira_user_from_user ¤

get_jira_user_from_user(user: User) -> JiraUser

Fetches a Jira user from the Jira API.

Parameters:

  • user (User) –

    User object

Raises:

  • JiraUserNotFoundError

    User not found in Jira

Returns:

  • JiraAPIUser ( JiraUser ) –

    Jira API user object

Source code in src/firefighter/jira_app/client.py
def get_jira_user_from_user(self, user: User) -> JiraUser:
    """Fetches a Jira user from the Jira API.

    Args:
        user (User): User object

    Raises:
        JiraUserNotFoundError: User not found in Jira

    Returns:
        JiraAPIUser: Jira API user object
    """
    # Check if user has a Jira user
    if hasattr(user, "jira_user") and user.jira_user:
        return user.jira_user

    username = user.email.split("@")[0]
    jira_user = self._fetch_jira_user(username)

    return JiraUser.objects.update_or_create(
        id=jira_user.raw.get("accountId"), defaults={"user": user}
    )[0]

get_watchers_from_jira_ticket ¤

get_watchers_from_jira_ticket(jira_issue_id: int | str) -> list[JiraAPIUser]

Fetch watchers for a specific Jira ticket from Jira API.

Parameters:

  • jira_issue_id (str | int) –

    Jira issue id

Raises:

Returns:

  • list ( User ) –

    List of Jira users object

Source code in src/firefighter/jira_app/client.py
def get_watchers_from_jira_ticket(
    self, jira_issue_id: int | str
) -> list[JiraAPIUser]:
    """Fetch watchers for a specific Jira ticket from Jira API.

    Args:
        jira_issue_id (str | int): Jira issue id

    Raises:
        ValueError: Empty issue id

    Returns:
        list(JiraAPIUser): List of Jira users object
    """
    watchers = self.jira.watchers(jira_issue_id).raw.get("watchers")
    if len(watchers) == 0:
        logger.warning(
            "Watchers not found for jira_account_id '%s'.", jira_issue_id
        )
    return watchers

transition_issue_auto ¤

transition_issue_auto(issue_id: str | int, target_status_name: str, workflow_name: str) -> None

Attempts to close an issue by applying transitions to it.

Parameters:

  • issue_id (str | int) –

    Jira issue id

  • target_status_name (str) –

    target status name

  • workflow_name (str) –

    workflow name

Source code in src/firefighter/jira_app/client.py
def transition_issue_auto(
    self, issue_id: str | int, target_status_name: str, workflow_name: str
) -> None:
    """Attempts to close an issue by applying transitions to it.

    Args:
        issue_id (str | int): Jira issue id
        target_status_name (str): target status name
        workflow_name (str): workflow name
    """
    issue_id = str(issue_id)
    transitions_info = self._get_transitions(
        self._get_project_config_workflow_from_builder_base(workflow_name)
    )
    if len(transitions_info) == 0:
        logger.error(
            f"Could not find transitions for issue id={issue_id}! Not closing issue."
        )

    # Get closed state id
    # XXX Use a list of closed states to support multiple workflows, or better
    closed_state_id = get_status_id_from_name(transitions_info, target_status_name)
    if closed_state_id is None:
        logger.warning(
            f"Could not find target status '{target_status_name}' id for issue {issue_id}! Not closing issue."
        )
        return

    # Get current issue status
    issue = self.jira.issue(issue_id)
    current_status_id = int(issue.fields.status.id)

    # Get transitions to apply
    transitions_to_apply = get_transitions_to_apply(
        current_status_id, transitions_info, closed_state_id
    )

    if len(transitions_to_apply) == 0:
        logger.info(f"Issue {issue_id} is already closed. Not closing again.")

    # Apply transitions
    # XXX Better error handling
    for transition in transitions_to_apply:
        logger.debug(f"Running transition: {transition}")
        self.jira.transition_issue(
            issue=issue_id,
            transition=transition,
            fields={},
        )

forms ¤

messages ¤

models ¤

JiraTicket ¤

Bases: JiraIssue

Jira ticket model.

Qualifier ¤

Bases: Model

Model to store users that can be incidents qualifiers.

QualifierRotation ¤

Bases: Model

Model to store the rotation of the incident qualifiers.

serializers ¤

validate_no_spaces ¤

validate_no_spaces(value: str) -> None

Ensure the string does not contain spaces.

Source code in src/firefighter/raid/serializers.py
def validate_no_spaces(value: str) -> None:
    """Ensure the string does not contain spaces."""
    if " " in value:
        raise serializers.ValidationError("The string cannot contain spaces.")

service ¤

create_issue_customer ¤

create_issue_customer(
    title: str,
    description: str,
    reporter: str,
    priority: int | None,
    labels: list[str] | None,
    platform: str,
    business_impact: str | None,
    team_to_be_routed: str | None,
    area: str | None,
    zendesk_ticket_id: str | None,
) -> JiraObject

Creates a Jira Incident issue of type Customer.

Parameters:

  • title (str) –

    Summary of the issue

  • description (str) –

    Description of the issue

  • reporter (str) –

    Jira account id of the reporter

  • priority (int) –

    Priority of the issue

  • labels (list[str]) –

    Labels to add to the issue

  • platform (str) –

    Platform of the issue

  • business_impact (str) –

    Business impact of the issue

  • team_to_be_routed (str) –

    Team to be routed

  • area (str) –

    Area of the issue

  • zendesk_ticket_id (str) –

    Zendesk ticket id

Source code in src/firefighter/raid/service.py
def create_issue_customer(
    title: str,
    description: str,
    reporter: str,
    priority: int | None,
    labels: list[str] | None,
    platform: str,
    business_impact: str | None,
    team_to_be_routed: str | None,
    area: str | None,
    zendesk_ticket_id: str | None,
) -> JiraObject:
    """Creates a Jira Incident issue of type Customer.

    Args:
        title (str): Summary of the issue
        description (str): Description of the issue
        reporter (str): Jira account id of the reporter
        priority (int): Priority of the issue
        labels (list[str]): Labels to add to the issue
        platform (str): Platform of the issue
        business_impact (str): Business impact of the issue
        team_to_be_routed (str): Team to be routed
        area (str): Area of the issue
        zendesk_ticket_id (str): Zendesk ticket id
    """
    issue = jira_client.create_issue(
        issuetype="Incident",
        summary=title,
        description=description,
        assignee=get_current_qualifier().id,
        reporter=reporter,
        qualifier=get_current_qualifier().id,
        priority=priority,
        labels=labels,
        platform=platform,
        business_impact=business_impact,
        suggested_team_routing=team_to_be_routed,
        area=area,
        zendesk_ticket_id=zendesk_ticket_id,
    )
    check_issue_id(issue, title=title, reporter=reporter)
    return issue

create_issue_documentation_request ¤

create_issue_documentation_request(
    title: str, description: str, reporter: str, priority: int | None, labels: list[str] | None, platform: str
) -> JiraObject

Creates a Jira issue of type Documentation/Process Request.

Parameters:

  • title (str) –

    Summary of the issue

  • description (str) –

    Description of the issue

  • reporter (str) –

    Jira account id of the reporter

  • priority (int) –

    Priority of the issue

  • labels (list[str]) –

    Labels to add to the issue

  • platform (str) –

    Platform of the issue

Source code in src/firefighter/raid/service.py
def create_issue_documentation_request(
    title: str,
    description: str,
    reporter: str,
    priority: int | None,
    labels: list[str] | None,
    platform: str,
) -> JiraObject:
    """Creates a Jira issue of type Documentation/Process Request.

    Args:
        title (str): Summary of the issue
        description (str): Description of the issue
        reporter (str): Jira account id of the reporter
        priority (int): Priority of the issue
        labels (list[str]): Labels to add to the issue
        platform (str): Platform of the issue
    """
    if labels is None:
        labels = [""]
    if "documentation-request" not in labels:
        labels.append("documentation-request")
    issue = jira_client.create_issue(
        issuetype="Documentation/Process Request",
        summary=title,
        description=description,
        assignee=get_current_qualifier().id,
        reporter=reporter,
        qualifier=get_current_qualifier().id,
        priority=priority,
        labels=labels,
        platform=platform,
    )
    check_issue_id(issue, title=title, reporter=reporter)
    return issue

create_issue_feature_request ¤

create_issue_feature_request(
    title: str, description: str, reporter: str, priority: int | None, labels: list[str] | None, platform: str
) -> JiraObject

Creates a Jira issue of type Feature Request.

Parameters:

  • title (str) –

    Summary of the issue

  • description (str) –

    Description of the issue

  • reporter (str) –

    Jira account id of the reporter

  • priority (int) –

    Priority of the issue

  • labels (list[str]) –

    Labels to add to the issue

  • platform (str) –

    Platform of the issue

Source code in src/firefighter/raid/service.py
def create_issue_feature_request(
    title: str,
    description: str,
    reporter: str,
    priority: int | None,
    labels: list[str] | None,
    platform: str,
) -> JiraObject:
    """Creates a Jira issue of type Feature Request.

    Args:
        title (str): Summary of the issue
        description (str): Description of the issue
        reporter (str): Jira account id of the reporter
        priority (int): Priority of the issue
        labels (list[str]): Labels to add to the issue
        platform (str): Platform of the issue
    """
    if labels is None:
        labels = [""]
    if "feature-request" not in labels:
        labels.append("feature-request")
    issue = jira_client.create_issue(
        issuetype="Feature Request",
        summary=title,
        description=description,
        assignee=get_current_qualifier().id,
        reporter=reporter,
        qualifier=get_current_qualifier().id,
        priority=priority,
        labels=labels,
        platform=platform,
    )
    check_issue_id(issue, title=title, reporter=reporter)
    return issue

create_issue_internal ¤

create_issue_internal(
    title: str,
    description: str,
    reporter: str,
    priority: int | None,
    labels: list[str] | None,
    platform: str,
    business_impact: str | None,
    team_to_be_routed: str | None,
    area: str | None,
) -> JiraObject

Creates a Jira Incident Issue of type Internal.

Parameters:

  • title (str) –

    Summary of the issue

  • description (str) –

    Description of the issue

  • reporter (str) –

    Jira account id of the reporter

  • priority (int) –

    Priority of the issue

  • labels (list[str]) –

    Labels to add to the issue

  • platform (str) –

    Platform of the issue

  • business_impact (str) –

    Business impact of the issue

  • team_to_be_routed (str) –

    Team to be routed

  • area (str) –

    Area of the issue

Source code in src/firefighter/raid/service.py
def create_issue_internal(
    title: str,
    description: str,
    reporter: str,
    priority: int | None,
    labels: list[str] | None,
    platform: str,
    business_impact: str | None,
    team_to_be_routed: str | None,
    area: str | None,
) -> JiraObject:
    """Creates a Jira Incident Issue of type Internal.

    Args:
        title (str): Summary of the issue
        description (str): Description of the issue
        reporter (str): Jira account id of the reporter
        priority (int): Priority of the issue
        labels (list[str]): Labels to add to the issue
        platform (str): Platform of the issue
        business_impact (str): Business impact of the issue
        team_to_be_routed (str): Team to be routed
        area (str): Area of the issue
    """
    issue = jira_client.create_issue(
        issuetype="Incident",
        summary=title,
        description=description,
        assignee=get_current_qualifier().id,
        reporter=reporter,
        qualifier=get_current_qualifier().id,
        priority=priority,
        labels=labels,
        platform=platform,
        business_impact=business_impact,
        suggested_team_routing=team_to_be_routed,
        area=area,
    )
    check_issue_id(issue, title=title, reporter=reporter)
    return issue

create_issue_seller ¤

create_issue_seller(
    title: str,
    description: str,
    reporter: str,
    priority: int | None,
    labels: list[str] | None,
    platform: str,
    business_impact: str | None,
    team_to_be_routed: str | None,
    area: str | None,
    seller_contract_id: str | None,
    is_key_account: bool | None,
    is_seller_in_golden_list: bool | None,
    zoho_desk_ticket_id: str | None,
) -> JiraObject

Creates a Jira Incident issue of type Seller.

Parameters:

  • title (str) –

    Summary of the issue

  • description (str) –

    Description of the issue

  • reporter (str) –

    Jira account id of the reporter

  • priority (int) –

    Priority of the issue

  • labels (list[str]) –

    Labels to add to the issue

  • platform (str) –

    Platform of the issue

  • business_impact (str) –

    Business impact of the issue

  • team_to_be_routed (str) –

    Team to be routed

  • area (str) –

    Area of the issue

  • seller_contract_id (str) –

    Seller contract id

  • is_key_account (bool) –

    Is key account

  • is_seller_in_golden_list (bool) –

    Is seller in golden list

  • zoho_desk_ticket_id (str) –

    Zoho desk ticket id

Source code in src/firefighter/raid/service.py
def create_issue_seller(  # noqa: PLR0913, PLR0917
    title: str,
    description: str,
    reporter: str,
    priority: int | None,
    labels: list[str] | None,
    platform: str,
    business_impact: str | None,
    team_to_be_routed: str | None,
    area: str | None,
    seller_contract_id: str | None,
    is_key_account: bool | None,  # noqa: FBT001
    is_seller_in_golden_list: bool | None,  # noqa: FBT001
    zoho_desk_ticket_id: str | None,
) -> JiraObject:
    """Creates a Jira Incident issue of type Seller.

    Args:
        title (str): Summary of the issue
        description (str): Description of the issue
        reporter (str): Jira account id of the reporter
        priority (int): Priority of the issue
        labels (list[str]): Labels to add to the issue
        platform (str): Platform of the issue
        business_impact (str): Business impact of the issue
        team_to_be_routed (str): Team to be routed
        area (str): Area of the issue
        seller_contract_id (str): Seller contract id
        is_key_account (bool): Is key account
        is_seller_in_golden_list (bool): Is seller in golden list
        zoho_desk_ticket_id (str): Zoho desk ticket id
    """
    issue = jira_client.create_issue(
        issuetype="Incident",
        summary=title,
        description=description,
        assignee=get_current_qualifier().id,
        reporter=reporter,
        qualifier=get_current_qualifier().id,
        priority=priority,
        labels=labels,
        platform=platform,
        business_impact=business_impact,
        suggested_team_routing=team_to_be_routed,
        area=area,
        seller_contract_id=seller_contract_id,
        is_key_account=is_key_account,
        is_seller_in_golden_list=is_seller_in_golden_list,
        zoho_desk_ticket_id=zoho_desk_ticket_id,
    )
    check_issue_id(issue, title=title, reporter=reporter)
    return issue

get_current_qualifier ¤

get_current_qualifier() -> JiraUser

Returns the qualifier Jira account id for today. On weekends use Qraft generic account.

Returns:

  • JiraUser ( JiraUser ) –

    JiraUser object

Source code in src/firefighter/raid/service.py
def get_current_qualifier() -> JiraUser:
    """Returns the qualifier Jira account id for today. On weekends use Qraft generic account.

    Returns:
        JiraUser: JiraUser object
    """
    if timezone.now().date().weekday() in {5, 6}:
        return jira_client.get_jira_user_from_jira_id(RAID_DEFAULT_JIRA_QRAFT_USER_ID)
    try:
        qualifier_rotation = QualifierRotation.objects.get(day=timezone.now().date())
    except QualifierRotation.DoesNotExist:
        logger.warning("Qualifier rotation not found for today.")
        return jira_client.get_jira_user_from_jira_id(RAID_DEFAULT_JIRA_QRAFT_USER_ID)
    return qualifier_rotation.jira_user

get_jira_user_from_user ¤

get_jira_user_from_user(user: User) -> JiraUser

Returns the JiraUser object for a given user, if it exists in DB or can be fetched on Jira API. Returns the default JiraUser if not found.

Source code in src/firefighter/raid/service.py
def get_jira_user_from_user(user: User) -> JiraUser:
    """Returns the JiraUser object for a given user, if it exists in DB or can be fetched on Jira API. Returns the default JiraUser if not found."""
    try:
        jira_user = jira_client.get_jira_user_from_user(user)
    except JiraAPIError:
        logger.exception(f"Could not find Jira user for {user.id}")

        logger.warning(f"User {user.id} has no Jira user")
        try:
            jira_user = jira_client.get_jira_user_from_jira_id(
                RAID_DEFAULT_JIRA_QRAFT_USER_ID
            )
        except JiraUserNotFoundError:
            logger.exception(
                f"Could not find Jira user with account id {RAID_DEFAULT_JIRA_QRAFT_USER_ID}"
            )
            jira_user = JiraUser.objects.get(id=RAID_DEFAULT_JIRA_QRAFT_USER_ID)
    return jira_user

signals ¤

incident_created ¤

incident_updated ¤

update_qualifiers_rotation ¤

tasks ¤

daily_qualifier ¤

send_daily_qualifier_message ¤

send_daily_qualifier_message() -> None

Send a message with the daily qualifier.

Ignore qualifiers that are not in the JiraUser table.

Source code in src/firefighter/raid/tasks/daily_qualifier.py
@shared_task(name="raid._daily_qualifier_message")
def send_daily_qualifier_message() -> None:
    """Send a message with the daily qualifier.

    Ignore qualifiers that are not in the JiraUser table.
    """
    _daily_qualifier_message()

weekly_qualifier ¤

send_weekly_qualifiers_message ¤

send_weekly_qualifiers_message() -> None

Send a message with the weekly qualifiers.

Ignore qualifiers that are not in the JiraUser table.

Source code in src/firefighter/raid/tasks/weekly_qualifier.py
@shared_task(name="raid._weekly_qualifiers_message")
def send_weekly_qualifiers_message() -> None:
    """Send a message with the weekly qualifiers.

    Ignore qualifiers that are not in the JiraUser table.
    """
    _weekly_qualifiers_message()

urls ¤

utils ¤

get_domain_from_email cached ¤

get_domain_from_email(email: str) -> str

Returns the domain from an email address.

Removes any subdomain(s) and the @, applies .lower().

Parameters:

  • email (str) –

    The email address to extract the domain from.

Returns:

  • str

    The domain part of the email address.

Raises:

Examples:

  • john.doe@example.com => example.com
  • alice.bob@test.example.ORG => example.org
  • webmaster@localhost => localhost
Source code in src/firefighter/raid/utils.py
@cache
def get_domain_from_email(email: str) -> str:
    """Returns the domain from an email address.

    Removes any subdomain(s) and the @, applies .lower().

    Args:
        email: The email address to extract the domain from.

    Returns:
        The domain part of the email address.

    Raises:
        ValueError: If the email is not well-formed.

    Examples:
      - `john.doe@example.com` => `example.com`
      - `alice.bob@test.example.ORG` => `example.org`
      - `webmaster@localhost` => `localhost`
    """
    # If there is not exactly one @, the email is invalid
    if email.count("@") != 1:
        msg = f"Invalid email: {email}"
        raise ValueError(msg)
    domain = email.split("@")[-1]
    if not domain:
        msg = f"Invalid email: {email}"
        raise ValueError(msg)
    domain_parts = domain.split(".")

    return (".".join(domain_parts[-2:]) if len(domain_parts) > 2 else domain).lower()

views ¤

CreateJiraBotView ¤

Bases: CreateModelMixin, GenericAPIView[JiraTicket]

post ¤

post(request: Request, *args: Never, **kwargs: Never) -> Response

Allow to create a Jira ticket through Landbot. Requires a valid Bearer token, that you can create in the back-office if you have the right permissions.

Source code in src/firefighter/raid/views/__init__.py
def post(self, request: Request, *args: Never, **kwargs: Never) -> Response:
    """Allow to create a Jira ticket through Landbot.
    Requires a valid Bearer token, that you can create in the back-office if you have the right permissions.
    """
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    headers = self.get_success_headers(serializer.data)
    return Response(
        serializer.data.get("key"), status=status.HTTP_201_CREATED, headers=headers
    )

JiraCommentAlertView ¤

Bases: CreateAPIView[Any]

post ¤

post(request: Request, *args: Never, **kwargs: Never) -> Response

Allow to send a message in Slack when a comment in a Jira ticket is created or modified. Requires a valid Bearer token, that you can create in the back-office if you have the right permissions.

Source code in src/firefighter/raid/views/__init__.py
def post(self, request: Request, *args: Never, **kwargs: Never) -> Response:
    """Allow to send a message in Slack when a comment in a Jira ticket is created or modified.
    Requires a valid Bearer token, that you can create in the back-office if you have the right permissions.
    """
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save()

    return Response()

JiraUpdateAlertView ¤

Bases: CreateAPIView[Any]

post ¤

post(request: Request, *args: Never, **kwargs: Never) -> Response

Allow to send a message in Slack when some fields ("Priority", "project", "description", "status") of a Jira ticket are updated. Requires a valid Bearer token, that you can create in the back-office if you have the right permissions.

Source code in src/firefighter/raid/views/__init__.py
def post(self, request: Request, *args: Never, **kwargs: Never) -> Response:
    """Allow to send a message in Slack when some fields ("Priority", "project", "description", "status") of a Jira ticket are updated.
    Requires a valid Bearer token, that you can create in the back-office if you have the right permissions.
    """
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save()

    return Response()

open_normal ¤