Skip to content

Commit d43f22d

Browse files
authored
List only blocking issues and subtasks as left behind, and fix the Russian wording (#55)
1 parent 029cd7d commit d43f22d

4 files changed

Lines changed: 49 additions & 17 deletions

File tree

‎demo/scenario.py‎

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ class DemoIssue:
6262
issue_type: str = "Story"
6363
links: tuple[str, ...] = ()
6464
blocked_by: tuple[str, ...] = ()
65+
blocks: tuple[str, ...] = ()
66+
parent: str | None = None
67+
subtasks: tuple[str, ...] = ()
6568

6669

6770
SERVICES: typing.Final = (
@@ -199,6 +202,7 @@ class DemoIssue:
199202
category="done",
200203
issue_type="Bug",
201204
links=(f"{ENDPOINT}/shop/worker/-/merge_requests/31",),
205+
blocks=("SHOP-40",),
202206
),
203207
DemoIssue(
204208
key="SHOP-36",
@@ -207,6 +211,7 @@ class DemoIssue:
207211
category="indeterminate",
208212
links=(f"{ENDPOINT}/shop/api/-/merge_requests/40",),
209213
blocked_by=("SHOP-45",),
214+
subtasks=("SHOP-46",),
210215
),
211216
DemoIssue(
212217
key="SHOP-38",
@@ -242,6 +247,7 @@ class DemoIssue:
242247
links=(f"{ENDPOINT}/shop/admin/-/merge_requests/15",),
243248
),
244249
DemoIssue(key="SHOP-45", summary="Pick the dark palette with design", status="To Do", category="new"),
250+
DemoIssue(key="SHOP-46", summary="Dark mode in emails", status="To Do", category="new", parent="SHOP-36"),
245251
)
246252

247253

@@ -392,6 +398,9 @@ def _mock_service(router: respx.Router, service: DemoService, now: dt.datetime)
392398
router.get(f"{api}/pipelines", params={"source": "push"}).respond(json=push)
393399

394400

401+
_BLOCKS: typing.Final = {"name": "Blocks", "inward": "is blocked by", "outward": "blocks"}
402+
403+
395404
def _issue(issue: DemoIssue) -> dict[str, typing.Any]:
396405
return {
397406
"key": issue.key,
@@ -400,12 +409,11 @@ def _issue(issue: DemoIssue) -> dict[str, typing.Any]:
400409
"status": {"name": issue.status, "statusCategory": {"key": issue.category}},
401410
"issuetype": {"name": issue.issue_type},
402411
"issuelinks": [
403-
{
404-
"type": {"name": "Blocks", "inward": "is blocked by", "outward": "blocks"},
405-
"inwardIssue": {"key": key},
406-
}
407-
for key in issue.blocked_by
412+
*({"type": _BLOCKS, "inwardIssue": {"key": key}} for key in issue.blocked_by),
413+
*({"type": _BLOCKS, "outwardIssue": {"key": key}} for key in issue.blocks),
408414
],
415+
"parent": {"key": issue.parent} if issue.parent else None,
416+
"subtasks": [{"key": key} for key in issue.subtasks],
409417
},
410418
}
411419

‎docs/page.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,15 @@ screen. While a service is open, the column folds into a strip with the number o
100100
get the full width. Clicking the strip closes the service.
101101

102102
Above the tabs, **Left behind by these picks** lists what the picked tags leave out for every Jira task they ship,
103-
and for every issue related to one:
103+
and for every issue a task depends on: one that blocks it through Jira's `Blocks` link type, and its subtasks.
104104

105-
- a service where the task or related issue has changes that no pick covers, with the tag it needs or why there is
106-
none: `no tag yet`, `not merged`, `merged into <branch>`, `in prod or not merged`, `not in this report`, or
105+
- a service where the task or an issue it depends on has changes that no pick covers, with the tag it needs or why
106+
there is none: `no tag yet`, `not merged`, `merged into <branch>`, `in prod or not merged`, `not in this report`, or
107107
`failed to collect`;
108-
- a related issue with no changes at all that is not done in Jira, with its status.
108+
- an issue the task depends on with no changes at all that is not done in Jira, with its status.
109109

110-
Changes already in production and closed merge requests are not listed.
110+
Changes already in production and closed merge requests are not listed. Other relations, such as `blocks`,
111+
`relates to`, or a parent, do not hold a release back; they show only when you hover over the issue's key.
111112

112113
It turns the picked tags into four tabs. Each has a copy button and a text box to copy from by hand, since browsers
113114
allow the copy button only over HTTPS.

‎release_scope/_static/index.html‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -675,10 +675,10 @@ <h2 x-text="t('release')"></h2>
675675
viaJira: "через Jira",
676676
viaJiraTitle: "{change} не упоминает задачу. {key} ссылается на это изменение в Jira.",
677677
taskFrom: "из {items}",
678-
gapsTitle: "Не войдёт с этими тегами:",
679-
gapNeeds: "нужен {tag}",
680-
relationParent: "родитель",
681-
relationSubtask: "подзадача",
678+
gapsTitle: "Не войдёт в релиз с выбранными тегами:",
679+
gapNeeds: "нужен тег {tag}",
680+
relationParent: "входит в",
681+
relationSubtask: "включает подзадачу",
682682
},
683683
};
684684

@@ -744,6 +744,9 @@ <h2 x-text="t('release')"></h2>
744744

745745
const byKey = (a, b) => a.localeCompare(b, undefined, { numeric: true });
746746

747+
const dependsOn = (relation) =>
748+
relation.kind === "subtask" || (relation.kind === "link" && relation.type === "Blocks" && relation.direction === "inward");
749+
747750
const OUT_OF_RANGE = new Set(["production", "older", "open", "branch", "closed", "elsewhere"]);
748751

749752
const outOfRange = (service, links) => {
@@ -937,7 +940,7 @@ <h2 x-text="t('release')"></h2>
937940
};
938941
for (const task of this.tasks) {
939942
check(task.key, null, task.key);
940-
for (const relation of task.issue ? task.issue.relations : []) check(task.key, relation, relation.key);
943+
for (const relation of task.issue ? task.issue.relations.filter(dependsOn) : []) check(task.key, relation, relation.key);
941944
}
942945
return [...gaps];
943946
},

‎tests/test_browser.py‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def test_demo_lists_its_services_and_picks_tags_for_an_issue(page: Page, demo_si
117117
names = page.locator("details.service .name")
118118
expect(names).to_have_text(["admin", "api", "web", "worker"])
119119
expect(names.first).to_have_attribute("title", "shop/admin")
120-
expect(page.locator(".issue-row code")).to_have_count(8)
120+
expect(page.locator(".issue-row code")).to_have_count(9)
121121
_issue(page, "SHOP-38").check()
122122
expect(page).to_have_url(re.compile(r"#issues=SHOP-38&shop/api=2\.5\.0&shop/web=1\.9\.0$"))
123123
assert errors == []
@@ -355,6 +355,7 @@ def test_demo_a_hand_pick_lists_the_changes_it_leaves_behind(page: Page, demo_si
355355
"SHOP-38 is blocked by SHOP-44 → admin: not merged",
356356
"SHOP-35 → worker: needs 0.15.0",
357357
"SHOP-36 is blocked by SHOP-45: To Do",
358+
"SHOP-36 has subtask SHOP-46: To Do",
358359
]
359360
)
360361
assert errors == []
@@ -378,6 +379,25 @@ def test_demo_related_issues_have_their_own_group_and_relations_show_on_hover(
378379
) -> None:
379380
page.goto(demo_site)
380381

381-
expect(page.locator(".issue-group")).to_have_text(["Done · 3", "Not done · 3", "Related · 2"])
382+
expect(page.locator(".issue-group")).to_have_text(["Done · 3", "Not done · 3", "Related · 3"])
382383
expect(page.locator(".issue-row code", has_text="SHOP-38")).to_have_attribute("title", "is blocked by SHOP-44")
383384
assert errors == []
385+
386+
387+
def test_demo_left_behind_list_reads_in_russian(page: Page, demo_site: str, errors: list[str]) -> None:
388+
page.goto(demo_site)
389+
for project, tag in (("shop/api", "2.5.0"), ("shop/web", "1.9.0")):
390+
service = _demo_service(page, project)
391+
service.locator("summary").click()
392+
service.locator(".tag", has_text=tag).get_by_role("button").click()
393+
394+
page.get_by_role("combobox").first.select_option("ru")
395+
396+
expect(page.locator(".gaps p")).to_have_text("Не войдёт в релиз с выбранными тегами:") # noqa: RUF001
397+
expect(page.locator(".gaps li")).to_contain_text(
398+
[
399+
"SHOP-35 → worker: нужен тег 0.15.0",
400+
"SHOP-36 включает подзадачу SHOP-46: To Do",
401+
]
402+
)
403+
assert errors == []

0 commit comments

Comments
 (0)