Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion frontend/public/jira.svg

This file was deleted.

4 changes: 0 additions & 4 deletions frontend/src/routes/$incidentId/components/LinksList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ const linkConfigs = {
label: 'Datadog notebook',
icon: '/datadog.svg',
},
jira: {
label: 'Jira',
icon: '/jira.svg',
},
linear: {
label: 'Linear',
icon: '/linear.svg',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const ParticipantSchema = z.object({

const ExternalLinksSchema = z.object({
slack: z.string().optional(),
jira: z.string().optional(),
datadog: z.string().optional(),
pagerduty: z.string().optional(),
statuspage: z.string().optional(),
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ dependencies = [
"django-kubernetes>=1.1.0",
"djangorestframework>=3.15.2",
"google-auth>=2.37.0",
"jira>=3.5.0",
"psycopg[binary]>=3.2.11",
"pyserde[toml]>=0.28.0",
"slack-bolt>=1.27.0",
Expand Down
6 changes: 0 additions & 6 deletions src/firetower/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ class DatadogConfig:
@deserialize
class JIRAConfig:
domain: str
account: str
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config files have stale fields removed from JIRAConfig

Medium Severity

The JIRAConfig class had account, api_key, and severity_field removed, but config.ci.toml (used by CI via CONFIG_FILE_PATH) and config.example.toml still define those fields under [jira]. If pyserde's from_toml raises on unknown fields, backend test CI would break. Even if pyserde silently ignores them, the config files now contain stale fields that don't match JIRAConfig and could confuse developers setting up the project.

Fix in Cursor Fix in Web

api_key: str
severity_field: str


@deserialize
Expand Down Expand Up @@ -108,9 +105,6 @@ def __init__(self) -> None:
)
self.jira = JIRAConfig(
domain="",
account="",
api_key="",
severity_field="",
)
self.slack = SlackConfig(
bot_token="",
Expand Down
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think there are any of these, but for the sake of completeness may as well

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from django.db import migrations, models


def delete_jira_links(apps, schema_editor):
ExternalLink = apps.get_model("incidents", "ExternalLink")
ExternalLink.objects.filter(type="JIRA").delete()


class Migration(migrations.Migration):
dependencies = [
("incidents", "0014_add_total_downtime"),
]

operations = [
migrations.RunPython(delete_jira_links, migrations.RunPython.noop),
migrations.AlterField(
model_name="externallink",
name="type",
field=models.CharField(
choices=[
("SLACK", "Slack"),
("DATADOG", "Datadog"),
("PAGERDUTY", "PagerDuty"),
("STATUSPAGE", "Statuspage"),
("NOTION", "Notion"),
("LINEAR", "Linear"),
],
max_length=20,
),
),
]
1 change: 0 additions & 1 deletion src/firetower/incidents/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ class TagType(models.TextChoices):

class ExternalLinkType(models.TextChoices):
SLACK = "SLACK", "Slack"
JIRA = "JIRA", "Jira"
DATADOG = "DATADOG", "Datadog"
PAGERDUTY = "PAGERDUTY", "PagerDuty"
STATUSPAGE = "STATUSPAGE", "Statuspage"
Expand Down
2 changes: 1 addition & 1 deletion src/firetower/incidents/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ class IncidentWriteSerializer(serializers.ModelSerializer):
root_cause_tags, impact_type_tags

captain/reporter: Email address of the user
external_links format: {"slack": "url", "jira": "url", ...}
external_links format: {"slack": "url", "linear": "url", ...}
- Merges with existing links (only updates provided links)
- Use null to delete a specific link: {"slack": null}
- Omit external_links field to leave existing links unchanged
Expand Down
6 changes: 3 additions & 3 deletions src/firetower/incidents/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,13 +394,13 @@ def test_external_link_multiple_types(self):
incident=incident, type=ExternalLinkType.SLACK, url="https://slack.com"
)

jira = ExternalLink.objects.create(
incident=incident, type=ExternalLinkType.JIRA, url="https://jira.com"
linear = ExternalLink.objects.create(
incident=incident, type=ExternalLinkType.LINEAR, url="https://linear.app"
)

assert incident.external_links.count() == 2
assert slack in incident.external_links.all()
assert jira in incident.external_links.all()
assert linear in incident.external_links.all()

def test_external_link_str(self):
"""Test external link string representation"""
Expand Down
2 changes: 1 addition & 1 deletion src/firetower/incidents/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,5 @@ def test_incident_detail_serialization(self):
assert (
data["external_links"]["slack"] == "https://slack.com/channels/incident-123"
)
assert "jira" not in data["external_links"] # Not set, so not included
assert "linear" not in data["external_links"] # Not set, so not included
assert len(data["external_links"]) == 1
24 changes: 12 additions & 12 deletions src/firetower/incidents/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ def test_create_incident_with_external_links(self):
"reporter": self.reporter.email,
"external_links": {
"slack": "https://slack.com/channel/123",
"jira": "https://jira.company.com/browse/INC-1",
"linear": "https://linear.app/team/issue/ENG-1",
},
}

Expand All @@ -843,7 +843,7 @@ def test_create_incident_with_external_links(self):
data = response.json()

assert data["external_links"]["slack"] == "https://slack.com/channel/123"
assert data["external_links"]["jira"] == "https://jira.company.com/browse/INC-1"
assert data["external_links"]["linear"] == "https://linear.app/team/issue/ENG-1"
assert "datadog" not in data["external_links"]

def test_create_incident_with_tags(self):
Expand Down Expand Up @@ -896,8 +896,8 @@ def test_add_external_link_via_patch(self):

self.client.force_authenticate(user=self.captain)

# Add jira link, should keep slack
payload = {"external_links": {"jira": "https://jira.com/new"}}
# Add linear link, should keep slack
payload = {"external_links": {"linear": "https://linear.app/new"}}
response = self.client.patch(
f"/api/incidents/{incident.incident_number}/", payload, format="json"
)
Expand All @@ -909,7 +909,7 @@ def test_add_external_link_via_patch(self):
data = response.json()

assert data["external_links"]["slack"] == "https://slack.com/original"
assert data["external_links"]["jira"] == "https://jira.com/new"
assert data["external_links"]["linear"] == "https://linear.app/new"

def test_update_existing_external_link(self):
"""Test updating an existing external link via PATCH"""
Expand Down Expand Up @@ -958,26 +958,26 @@ def test_delete_external_link_with_null(self):
)
ExternalLink.objects.create(
incident=incident,
type=ExternalLinkType.JIRA,
url="https://jira.com/test",
type=ExternalLinkType.LINEAR,
url="https://linear.app/test",
)

self.client.force_authenticate(user=self.captain)

# Delete slack link, keep jira
# Delete slack link, keep linear
payload = {"external_links": {"slack": None}}
response = self.client.patch(
f"/api/incidents/{incident.incident_number}/", payload, format="json"
)

assert response.status_code == 200

# Verify slack deleted, jira remains
# Verify slack deleted, linear remains
response = self.client.get(f"/api/incidents/{incident.incident_number}/")
data = response.json()

assert "slack" not in data["external_links"]
assert data["external_links"]["jira"] == "https://jira.com/test"
assert data["external_links"]["linear"] == "https://linear.app/test"

def test_invalid_external_link_type(self):
"""Test that invalid link types are rejected"""
Expand Down Expand Up @@ -1047,7 +1047,7 @@ def test_patch_without_external_links_preserves_existing(self):
"reporter": self.reporter.email,
"external_links": {
"slack": "https://slack.com/channel",
"jira": "https://jira.example.com/issue",
"linear": "https://linear.app/issue",
},
}
response = self.client.post("/api/incidents/", payload, format="json")
Expand All @@ -1070,7 +1070,7 @@ def test_patch_without_external_links_preserves_existing(self):
data = response.json()
assert len(data["external_links"]) == 2
assert data["external_links"]["slack"] == "https://slack.com/channel"
assert data["external_links"]["jira"] == "https://jira.example.com/issue"
assert data["external_links"]["linear"] == "https://linear.app/issue"

def test_update_affected_service_tags_via_patch(self):
"""Test setting affected_service_tags via PATCH"""
Expand Down
3 changes: 1 addition & 2 deletions src/firetower/integrations/services/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Services package for external integrations."""

from .jira import JiraService
from .slack import SlackService

__all__ = ["JiraService", "SlackService"]
__all__ = ["SlackService"]
140 changes: 0 additions & 140 deletions src/firetower/integrations/services/jira.py

This file was deleted.

Loading
Loading