Skip to content
10 changes: 6 additions & 4 deletions config/config.prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -844,8 +844,9 @@
parameters:
jira_project_key: BZFFX
jira_components:
set_custom_components:
- "Firefox"
use_bug_component_with_product_prefix: true
use_bug_component: false
create_components: true
steps:
new:
- create_issue
Expand Down Expand Up @@ -885,8 +886,9 @@
parameters:
jira_project_key: BZFFX
jira_components:
set_custom_components:
- "Core"
use_bug_component_with_product_prefix: true
use_bug_component: false
create_components: true
steps:
new:
- create_issue
Expand Down
1 change: 1 addition & 0 deletions jbi/jira/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def raise_for_status(self, *args, **kwargs):

get_server_info = instrumented_method(Jira.get_server_info)
get_project_components = instrumented_method(Jira.get_project_components)
create_component = instrumented_method(Jira.create_component)
update_issue = instrumented_method(Jira.update_issue)
update_issue_field = instrumented_method(Jira.update_issue_field)
set_issue_status = instrumented_method(Jira.set_issue_status)
Expand Down
12 changes: 11 additions & 1 deletion jbi/jira/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ def update_issue_components(
self,
context: ActionContext,
components: Iterable[str],
create_components: bool = False,
) -> tuple[Optional[dict], set]:
"""Attempt to add components to the specified issue

Expand All @@ -374,7 +375,16 @@ def update_issue_components(
missing_components.remove(comp["name"])

if not jira_components:
return None, missing_components
if not create_components:
return None, missing_components

for comp_name in missing_components:
new_comp = self.client.create_component(
project_key=context.jira.project,
name=comp_name,
)
jira_components.append({"id": new_comp["id"]})
missing_components.clear()

resp = self.update_issue_field(
context, field="components", value=jira_components
Expand Down
1 change: 1 addition & 0 deletions jbi/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class JiraComponents(BaseModel, frozen=True):
use_bug_component: bool = True
use_bug_product: bool = False
use_bug_component_with_product_prefix: bool = False
create_components: bool = False
set_custom_components: list[str] = []


Expand Down
1 change: 1 addition & 0 deletions jbi/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ def maybe_update_components(
resp, missing_components = jira_service.update_issue_components(
context=context,
components=candidate_components,
create_components=parameters.jira_components.create_components,
)
except requests_exceptions.HTTPError as exc:
if getattr(exc.response, "status_code", None) != 400:
Expand Down
76 changes: 76 additions & 0 deletions tests/unit/test_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,82 @@ def test_maybe_update_components_failing(
]


def test_maybe_update_components_create_components_normal_component(
action_context_factory,
mocked_jira,
action_params_factory,
):
action_context = action_context_factory(
operation=Operation.CREATE,
current_step="maybe_update_components",
bug__component="NewComponent",
jira__issue="JBI-234",
)
action_params = action_params_factory(
jira_project_key=action_context.jira.project,
jira_components=JiraComponents(create_components=True),
)
mocked_jira.get_project_components.return_value = [
{"id": 1, "name": "ExistingComponent"},
]
mocked_jira.create_component.return_value = {"id": "42", "name": "NewComponent"}

steps.maybe_update_components(
action_context,
parameters=action_params,
jira_service=JiraService(mocked_jira),
)

mocked_jira.create_component.assert_called_once_with(
project_key=action_context.jira.project,
name="NewComponent",
)
mocked_jira.update_issue_field.assert_called_with(
key="JBI-234",
fields={"components": [{"id": "42"}]},
)


def test_maybe_update_components_create_components_prefix_component(
action_context_factory,
mocked_jira,
action_params_factory,
):
action_context = action_context_factory(
operation=Operation.CREATE,
current_step="maybe_update_components",
bug__product="Firefox",
bug__component="NewComponent",
jira__issue="JBI-234",
)
action_params = action_params_factory(
jira_project_key=action_context.jira.project,
jira_components=JiraComponents(
create_components=True,
use_bug_component_with_product_prefix=True,
use_bug_component=False
),
)
mocked_jira.get_project_components.return_value = [
{"id": 1, "name": "Firefox::ExistingComponent"},
]
mocked_jira.create_component.return_value = {"id": "42", "name": "Firefox::NewComponent"}

steps.maybe_update_components(
action_context,
parameters=action_params,
jira_service=JiraService(mocked_jira),
)

mocked_jira.create_component.assert_called_once_with(
project_key=action_context.jira.project,
name="Firefox::NewComponent",
)
mocked_jira.update_issue_field.assert_called_with(
key="JBI-234",
fields={"components": [{"id": "42"}]},
)

def test_sync_whiteboard_labels(
action_context_factory,
mocked_jira,
Expand Down
Loading