diff --git a/README.md b/README.md index 901440a..db81d51 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,20 @@ them. An address with picks replaces the release tags of a `--jira` report; pick a tag that a later run no longer lists, are skipped with a warning. Clearing every pick empties the address, so a reload starts from the release tags again. +**Issues**, at the top of the Release column when the report has Jira issues, picks tags from issues instead. It lists +every issue of the report, Done first and then the rest, by Jira's status category, and filters them by key or +summary or shows only the chosen ones. Under each issue are the services it touches: the tag that ships it, `no tag +yet`, `in prod or not merged` when it links to a merge request or commit outside the range, `not in this report`, or +`failed to collect`. Ticking an issue picks, in every service it touches, the tag a `--jira` run would make its +release tag: the nearest tag at or above the newest row the issue links to or names. When several chosen issues touch +a service, the newest of their tags wins; when one of them has no tag yet, the service gets no pick and its line +links to create the next tag. Each touched service line names the chosen issues it is picked for and the other Jira +keys its picked tag also ships; in the list those issues are marked `ships anyway`. 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`. + **Release**, in a column next to the services that stays in view while they scroll, or below them on a narrow screen, turns the picked tags into three lists and a release post. While a service is open, the column folds into a strip with the number of picked tags and tasks, so the rows get the full width; clicking the strip closes the service. Each has a tab of its own, with a copy button and a text box diff --git a/release_scope/_static/index.html b/release_scope/_static/index.html index 60649d4..ec7a86c 100644 --- a/release_scope/_static/index.html +++ b/release_scope/_static/index.html @@ -95,6 +95,35 @@ .status-indeterminate { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); } .status-done { color: var(--good); background: color-mix(in srgb, var(--good) 12%, transparent); } button.picked { border-color: var(--accent); color: var(--accent); } + .service.involved { border-color: var(--accent); } + .service.idle { opacity: 0.45; } + .service.unlisted { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 8px 12px; border-style: dashed; } + .plan-line { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: center; padding-left: 14px; } + .plan-line > span { display: inline-flex; flex-wrap: wrap; gap: 4px; align-items: center; } + .key { padding: 0 8px; border: 1px solid var(--accent); border-radius: 999px; font-size: 12px; background: var(--accent); color: var(--bg); } + .key.rider { border-style: dashed; border-color: var(--warn); background: transparent; color: var(--warn); } + .cell { padding: 0 6px; border-radius: 4px; font-size: 12px; white-space: nowrap; } + .cell-tag { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent); } + .cell-untagged { background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--warn); } + .cell-elsewhere { background: color-mix(in srgb, var(--good) 14%, transparent); color: var(--good); } + .cell-outside, .cell-failed { background: color-mix(in srgb, var(--bad) 12%, transparent); color: var(--bad); } + .issue-tools { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0; } + .issue-tools input { flex: 1; min-width: 140px; font: inherit; padding: 2px 8px; border: 1px solid var(--border); border-radius: 6px; + background: var(--bg); color: var(--fg); } + .issue-scroll { max-height: 46vh; overflow-y: auto; border: 1px solid var(--border); border-radius: 6px; } + .issue-group { position: sticky; top: 0; z-index: 1; padding: 2px 8px; border-bottom: 1px solid var(--border); background: var(--panel); + color: var(--muted); font-size: 12px; font-weight: 600; } + .issue-row { display: grid; grid-template-columns: 16px 8px 76px minmax(0, 1fr) auto; grid-template-rows: 20px 20px; column-gap: 6px; + align-items: center; height: 48px; padding: 4px 8px; border-bottom: 1px solid var(--border); cursor: pointer; } + .issue-row:hover { background: color-mix(in srgb, var(--accent) 5%, transparent); } + .issue-row.chosen { background: color-mix(in srgb, var(--accent) 10%, transparent); } + .issue-row code { font-weight: 600; } + .issue-row .summary { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + .issue-row .reach { grid-column: 3 / -1; display: flex; gap: 4px; overflow: hidden; white-space: nowrap; } + .rider-mark { padding: 0 6px; border: 1px dashed var(--warn); border-radius: 999px; color: var(--warn); font-size: 11px; white-space: nowrap; } + .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); } + .dot-indeterminate { background: var(--accent); } + .dot-done { background: var(--good); }
@@ -142,7 +171,8 @@ - + +