Skip to content
Merged
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
7 changes: 4 additions & 3 deletions docs/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ issues are marked `ships anyway` in the list. A chosen issue that links only to
it has nothing to ship there, such as `SHOP-150 not merged`. Services no chosen issue touches are dimmed, and
projects the issues link to that are not in the report are listed under the services.

Unticking an issue clears the picks only it needed. A pick made by hand stays until the chosen issues change, and the
line says which chosen issues it does not ship. The address keeps the issues before the picks, as
`issues=SHOP-140,SHOP-141&team/api=2.5.0`.
Unticking an issue clears the picks only it needed. It works the other way too: clearing a pick, or picking an older
tag that does not ship a chosen issue, unticks that issue, and the picks only it needed in other services go with it.
An address whose picks miss a chosen issue loads with the issue unticked. The address keeps the issues before the
picks, as `issues=SHOP-140,SHOP-141&team/api=2.5.0`.

## Release

Expand Down
25 changes: 13 additions & 12 deletions release_scope/_static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,6 @@ <h2 x-text="t('services')"></h2>
<template x-if="planOf(service).elsewhere.length">
<span class="muted" x-text="outOfRangeText(planOf(service))"></span>
</template>
<template x-if="missedBy(service).length">
<span class="warn" x-text="t('planMissed', { tag: picks[service.project], keys: missedBy(service).join(', ') })"></span>
</template>
</div>
</template>
</summary>
Expand Down Expand Up @@ -548,7 +545,6 @@ <h2 x-text="t('release')"></h2>
planAlso: "also ships",
planNoTag: "{keys}: no tag yet.",
planElsewhere: "{items}, nothing to pick",
planMissed: "{tag} does not ship {keys}",
},
ru: {
language: "Язык",
Expand Down Expand Up @@ -649,7 +645,6 @@ <h2 x-text="t('release')"></h2>
planAlso: "также войдут",
planNoTag: "{keys}: тега ещё нет.",
planElsewhere: "{items}, выбирать нечего",
planMissed: "{tag} не содержит {keys}",
},
};

Expand Down Expand Up @@ -956,13 +951,6 @@ <h2 x-text="t('release')"></h2>
const candidate = this.pickOf(service);
return candidate ? candidate.jira_keys.map((item) => item.key).filter((key) => !this.chosen.includes(key)) : [];
},
missedBy(service) {
const tag = this.picks[service.project];
if (!tag || !this.planOf(service)) return [];
const picked = service.rows.findIndex((row) => row.tags.some((item) => item.name === tag));
return this.chosen.filter((key) =>
this.reach[key].some((item) => item.project === service.project && item.state === "tag" && picked > item.index));
},
shipsAnyway(key) {
return !this.chosen.includes(key) && this.picked.some(({ candidate }) => candidate.jira_keys.some((item) => item.key === key));
},
Expand Down Expand Up @@ -1011,9 +999,21 @@ <h2 x-text="t('release')"></h2>

pick(service, tag, element) {
this.picks[service.project] = tag;
this.untickMissed(service);
element.closest("details").open = false;
this.writeHash();
},
untickMissed(service) {
const tag = this.picks[service.project];
const picked = tag ? service.rows.findIndex((row) => row.tags.some((item) => item.name === tag)) : -1;
const missed = this.chosen.filter((key) =>
this.reach[key].some((item) => item.project === service.project && item.state === "tag" && (picked === -1 || picked > item.index)));
if (!missed.length) return;
this.chosen = this.chosen.filter((key) => !missed.includes(key));
this.applyIssues();
this.picks[service.project] = tag;
delete this.autoPicks[service.project];
},
closeServices() {
for (const item of document.querySelectorAll("details.service[open]")) item.open = false;
},
Expand All @@ -1040,6 +1040,7 @@ <h2 x-text="t('release')"></h2>
this.picks[service.project] = known ? tag : "";
if (known) wanted.delete(service.project);
}
for (const service of this.pickable) this.untickMissed(service);
}
this.ignored = [
...issues.filter((key) => !(key in this.reach)),
Expand Down
38 changes: 38 additions & 0 deletions tests/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,41 @@ def test_demo_screenshot_shows_an_issue_with_its_picks(
assert output.read_bytes().startswith(b"\x89PNG")
expect(page.locator("details.service .chip:visible > span")).to_have_text(["2.5.0", "1.9.0"])
assert errors == []


def test_clearing_an_issue_pick_unticks_the_issue_and_survives_a_reload(
page: Page, site: str, errors: list[str]
) -> None:
page.goto(site)
_issue(page, "SHOP-12").check()

page.locator("details.service .chip").get_by_role("button").click()

expect(_issue(page, "SHOP-12")).not_to_be_checked()
expect(page.locator("details.service .chip")).to_be_hidden()
expect(page).not_to_have_url(re.compile("#"))
page.reload()
expect(page.locator("details.service .chip")).to_be_hidden()
assert errors == []


def test_picking_an_older_tag_unticks_the_issues_it_misses(page: Page, site: str, errors: list[str]) -> None:
page.goto(site)
_issue(page, "SHOP-12").check()

page.locator("details.service summary").click()
page.locator(".tag", has_text="1.1.0").get_by_role("button").click()

expect(_issue(page, "SHOP-12")).not_to_be_checked()
expect(page.locator("details.service .chip > span")).to_have_text("1.1.0")
expect(page).to_have_url(re.compile(r"#team/svc=1\.1\.0$"))
assert errors == []


def test_an_address_with_an_older_pick_unticks_the_issues_it_misses(page: Page, site: str, errors: list[str]) -> None:
page.goto(f"{site}#issues=SHOP-12&team/svc=1.1.0")

expect(_issue(page, "SHOP-12")).not_to_be_checked()
expect(page.locator("details.service .chip > span")).to_have_text("1.1.0")
expect(page).to_have_url(re.compile(r"#team/svc=1\.1\.0$"))
assert errors == []
Loading