Skip to content

Commit 10dcecf

Browse files
committed
feat: Add conditional "when" field for Jira issues and subtasks
Allow Jira issue prerequisites and their subtasks to be conditionally included based on a Jinja2 expression. Issues are skipped when the condition evaluates to false. Defaults to "true" (always created). Assisted-by: Claude Opus 4.6 (Anthropic)
1 parent 693e2ba commit 10dcecf

4 files changed

Lines changed: 118 additions & 2 deletions

File tree

examples/rules/rules.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
subtasks:
1313
- jira_issue: add_beta_repos
1414
template: "add_beta_repos.yaml.j2"
15+
when: "major >= 10"
1516
- jira_issue: notify_team
1617
fields:
1718
project:

src/retasc/models/prerequisites/jira_issue.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,20 @@ class JiraIssueTemplate(PrerequisiteBase):
264264
" current status are skipped automatically."
265265
),
266266
)
267+
when: str = Field(
268+
default="true",
269+
description=(
270+
"Condition expression. The issue is only created/updated"
271+
" when it evaluates to true. Defaults to 'true' (always created)."
272+
),
273+
)
274+
275+
def _want_update(self, context):
276+
if context.template.evaluate(self.when):
277+
return True
278+
279+
context.report.set("skipped", True)
280+
return False
267281

268282
def _update_issue_data(
269283
self,
@@ -388,6 +402,10 @@ def update_state(self, context) -> ReleaseRuleState:
388402
context.template.params["jira_template_file"] = self.template
389403
jira_issue_id = context.template.render(self.jira_issue)
390404
context.report.set("jira_issue", jira_issue_id)
405+
406+
if not self._want_update(context):
407+
return ReleaseRuleState.Completed
408+
391409
issue = self._update_issue(jira_issue_id, context=context)
392410
if issue is None:
393411
return ReleaseRuleState.InProgress
@@ -400,6 +418,8 @@ def update_state(self, context) -> ReleaseRuleState:
400418
subtask_id = context.template.render(subtask.jira_issue)
401419
with context.report.section("subtasks", type="Subtask", name=subtask_id):
402420
context.report.set("jira_issue", subtask_id)
421+
if not subtask._want_update(context):
422+
continue
403423
subtask._update_issue(
404424
subtask_id,
405425
context,

tests/factory.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ def new_jira_template_file(self, jira_issue: str, template: str) -> str:
4747

4848
return str(tmp)
4949

50-
def new_jira_subtask(self, template: str) -> JiraIssueTemplate:
50+
def new_jira_subtask(
51+
self, template: str, *, when: str = "true"
52+
) -> JiraIssueTemplate:
5153
jira_issue = self.new_jira_issue_id()
5254
file = self.new_jira_template_file(jira_issue, template)
53-
return JiraIssueTemplate(jira_issue=jira_issue, template=file)
55+
return JiraIssueTemplate(jira_issue=jira_issue, template=file, when=when)
5456

5557
def new_jira_issue_prerequisite(
5658
self,
@@ -59,6 +61,7 @@ def new_jira_issue_prerequisite(
5961
fields: dict[str, Any] | None = None,
6062
jira_issue: str = "",
6163
subtasks=[],
64+
when: str = "true",
6265
):
6366
jira_issue_ = jira_issue or self.new_jira_issue_id()
6467

@@ -72,4 +75,5 @@ def new_jira_issue_prerequisite(
7275
template=file,
7376
fields=fields or {},
7477
subtasks=subtasks,
78+
when=when,
7579
)

tests/test_run.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,97 @@ def test_run_rule_jira_issue_create_subtasks(factory):
401401
}
402402

403403

404+
def test_run_rule_jira_issue_when_false(factory, mock_jira):
405+
jira_issue_prereq = factory.new_jira_issue_prerequisite(DUMMY_ISSUE, when="false")
406+
rule = factory.new_rule(prerequisites=[jira_issue_prereq])
407+
report = call_run()
408+
assert report.data == {
409+
"inputs": [
410+
{
411+
"type": "ProductPagesReleases",
412+
"release": "rhel-10.0",
413+
"rules": [
414+
{
415+
"rule": rule.name,
416+
"prerequisites": [
417+
{
418+
"type": "JiraIssue",
419+
"jira_issue": "test_jira_template_1",
420+
"skipped": True,
421+
}
422+
],
423+
"state": "Completed",
424+
}
425+
],
426+
}
427+
]
428+
}
429+
mock_jira.create_issue.assert_not_called()
430+
mock_jira.search_issues.assert_not_called()
431+
432+
433+
def test_run_rule_jira_issue_subtask_when_false(factory, mock_jira):
434+
subtasks = [
435+
factory.new_jira_subtask(DUMMY_ISSUE, when="false"),
436+
factory.new_jira_subtask(DUMMY_ISSUE),
437+
]
438+
jira_issue_prereq = factory.new_jira_issue_prerequisite(
439+
DUMMY_ISSUE, subtasks=subtasks
440+
)
441+
rule = factory.new_rule(prerequisites=[jira_issue_prereq])
442+
report = call_run()
443+
assert report.data == {
444+
"inputs": [
445+
{
446+
"type": "ProductPagesReleases",
447+
"release": "rhel-10.0",
448+
"rules": [
449+
{
450+
"rule": rule.name,
451+
"prerequisites": [
452+
{
453+
"type": "JiraIssue",
454+
"jira_issue": "test_jira_template_3",
455+
"issue_data": {
456+
"summary": "test",
457+
"labels": [
458+
"retasc-id-test_jira_template_3-rhel-10.0"
459+
],
460+
},
461+
"issue_status": "created",
462+
"issue_id": "TEST-1",
463+
"state": "InProgress",
464+
"subtasks": [
465+
{
466+
"type": "Subtask",
467+
"jira_issue": "test_jira_template_1",
468+
"skipped": True,
469+
},
470+
{
471+
"type": "Subtask",
472+
"jira_issue": "test_jira_template_2",
473+
"issue_data": {
474+
"summary": "test",
475+
"labels": [
476+
"retasc-id-test_jira_template_2-rhel-10.0"
477+
],
478+
"parent": {"key": "TEST-1"},
479+
},
480+
"issue_status": "created",
481+
"issue_id": "TEST-2",
482+
},
483+
],
484+
},
485+
],
486+
"state": "InProgress",
487+
}
488+
],
489+
}
490+
]
491+
}
492+
assert mock_jira.create_issue.call_count == 2
493+
494+
404495
def test_run_rule_jira_issue_in_progress(factory, mock_jira):
405496
jira_issue_prereq = factory.new_jira_issue_prerequisite(DUMMY_ISSUE)
406497
rule = factory.new_rule(prerequisites=[jira_issue_prereq])

0 commit comments

Comments
 (0)