This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch sbp
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
The following commit(s) were added to refs/heads/sbp by this push:
new 0f765ac Rename blocking to blocker and improve the user interface
0f765ac is described below
commit 0f765ac1eac7e98a9f190e67e98d4c057d0b8227
Author: Sean B. Palmer <[email protected]>
AuthorDate: Fri Feb 6 15:51:32 2026 +0000
Rename blocking to blocker and improve the user interface
---
atr/db/interaction.py | 2 +-
atr/models/sql.py | 2 +-
atr/shared/web.py | 7 ++-
atr/static/css/atr.css | 27 ++++++++++-
atr/static/js/src/report-results.js | 21 ++++++---
atr/storage/readers/checks.py | 4 +-
atr/storage/readers/releases.py | 19 +++++---
atr/storage/types.py | 2 +
atr/tasks/checks/__init__.py | 4 +-
atr/tasks/checks/hashing.py | 2 +-
atr/tasks/checks/license.py | 16 +++----
atr/tasks/checks/paths.py | 30 ++++++-------
atr/tasks/checks/rat.py | 4 +-
atr/tasks/checks/signature.py | 2 +-
atr/templates/report-selected-path.html | 52 ++++++++--------------
.../0048_2026.02.06_blocking_to_blocker.py | 25 +++++++++++
16 files changed, 138 insertions(+), 81 deletions(-)
diff --git a/atr/db/interaction.py b/atr/db/interaction.py
index 104a9ad..b254f82 100644
--- a/atr/db/interaction.py
+++ b/atr/db/interaction.py
@@ -181,7 +181,7 @@ async def has_failing_checks(release: sql.Release,
revision_number: str, caller_
sql.CheckResult.release_name == release.name,
sql.CheckResult.revision_number == revision_number,
sql.validate_instrumented_attribute(sql.CheckResult.status).in_(
- [sql.CheckResultStatus.BLOCKING,
sql.CheckResultStatus.FAILURE]
+ [sql.CheckResultStatus.BLOCKER,
sql.CheckResultStatus.FAILURE]
),
)
)
diff --git a/atr/models/sql.py b/atr/models/sql.py
index 293c011..a6e9aed 100644
--- a/atr/models/sql.py
+++ b/atr/models/sql.py
@@ -65,7 +65,7 @@ class DistributionPlatformValue:
class CheckResultStatus(enum.StrEnum):
- BLOCKING = "blocking"
+ BLOCKER = "blocker"
EXCEPTION = "exception"
FAILURE = "failure"
SUCCESS = "success"
diff --git a/atr/shared/web.py b/atr/shared/web.py
index a63190f..3030aed 100644
--- a/atr/shared/web.py
+++ b/atr/shared/web.py
@@ -192,20 +192,25 @@ def _render_checks_summary(info: types.PathInfo | None,
project_name: str, versi
summary_content.append(htpy.span(".badge.bg-warning.text-dark.me-2")[str(stat.warning_count)])
if stat.failure_count > 0:
summary_content.append(htpy.span(".badge.bg-danger.me-2")[str(stat.failure_count)])
+ if stat.blocker_count > 0:
+
summary_content.append(htpy.span(".badge.atr-bg-blocker.me-2")[str(stat.blocker_count)])
summary_content.append(htpy.strong[_checker_display_name(stat.checker)])
details.summary[*summary_content]
files_div = htm.Block(htm.div, classes=".mt-2.atr-checks-files")
- all_files = set(stat.failure_files.keys()) |
set(stat.warning_files.keys())
+ all_files = set(stat.failure_files.keys()) |
set(stat.warning_files.keys()) | set(stat.blocker_files.keys())
for file_path in sorted(all_files):
report_url = f"/report/{project_name}/{version_name}/{file_path}"
error_count = stat.failure_files.get(file_path, 0)
+ blocker_count = stat.blocker_files.get(file_path, 0)
warning_count = stat.warning_files.get(file_path, 0)
file_content: list[htm.Element | str] = []
if error_count > 0:
file_content.append(htpy.span(".badge.bg-danger.me-2")[util.plural(error_count,
"error")])
+ if blocker_count > 0:
+
file_content.append(htpy.span(".badge.atr-bg-blocker.me-2")[util.plural(blocker_count,
"blocker")])
if warning_count > 0:
file_content.append(
htpy.span(".badge.bg-warning.text-dark.me-2")[util.plural(warning_count,
"warning")]
diff --git a/atr/static/css/atr.css b/atr/static/css/atr.css
index cae5755..d3e121b 100644
--- a/atr/static/css/atr.css
+++ b/atr/static/css/atr.css
@@ -565,6 +565,31 @@ td.atr-shrink {
text-decoration: line-through;
}
-.atr-bg-blocking {
+.atr-bg-blocker {
background-color: rgb(111 0 193 / 75%);
+ color: #ffffff;
+}
+
+.btn.atr-btn-blocker {
+ background-color: rgb(111 0 193 / 75%);
+ border-color: rgb(111 0 193 / 75%);
+ color: #ffffff;
+}
+
+.btn.atr-btn-blocker:hover {
+ background-color: rgb(111 0 193 / 90%);
+ border-color: rgb(111 0 193 / 90%);
+ color: #ffffff;
+}
+
+.btn.atr-btn-outline-blocker {
+ background-color: transparent;
+ border-color: rgb(111 0 193 / 75%);
+ color: rgb(111 0 193);
+}
+
+.btn.atr-btn-outline-blocker:hover {
+ background-color: rgb(111 0 193 / 75%);
+ border-color: rgb(111 0 193 / 75%);
+ color: #ffffff;
}
diff --git a/atr/static/js/src/report-results.js
b/atr/static/js/src/report-results.js
index eb14437..f06f4f7 100644
--- a/atr/static/js/src/report-results.js
+++ b/atr/static/js/src/report-results.js
@@ -42,8 +42,17 @@ function toggleStatusVisibility(type, status) {
el.classList.add("atr-hide");
}
});
- const bsSt =
- status === "failure" || status === "exception" ? "danger" :
status;
+ let filledClass;
+ let outlineClass;
+ if (status === "blocker") {
+ filledClass = "atr-btn-blocker";
+ outlineClass = "atr-btn-outline-blocker";
+ } else {
+ const bsSt =
+ status === "failure" || status === "exception" ?
"danger" : status;
+ filledClass = `btn-${bsSt}`;
+ outlineClass = `btn-outline-${bsSt}`;
+ }
const cntMatch = btn.textContent.match(/\((\d+)\)/);
if (!cntMatch) {
console.error("Button text regex mismatch for:",
btn.textContent);
@@ -52,11 +61,11 @@ function toggleStatusVisibility(type, status) {
const newButtonAction = elementsCurrentlyHidden ? "Hide" : "Show";
btn.querySelector("span").textContent = newButtonAction;
if (newButtonAction === "Hide") {
- btn.classList.remove(`btn-outline-${bsSt}`);
- btn.classList.add(`btn-${bsSt}`);
+ btn.classList.remove(outlineClass);
+ btn.classList.add(filledClass);
} else {
- btn.classList.remove(`btn-${bsSt}`);
- btn.classList.add(`btn-outline-${bsSt}`);
+ btn.classList.remove(filledClass);
+ btn.classList.add(outlineClass);
}
if (type === "member") {
updateMemberStriping();
diff --git a/atr/storage/readers/checks.py b/atr/storage/readers/checks.py
index 80a4f02..b48daf3 100644
--- a/atr/storage/readers/checks.py
+++ b/atr/storage/readers/checks.py
@@ -113,8 +113,8 @@ class GeneralPublic:
if cr.status == sql.CheckResultStatus.SUCCESS:
# Successes are never ignored
return False
- if cr.status == sql.CheckResultStatus.BLOCKING:
- # Blocking results are never ignored
+ if cr.status == sql.CheckResultStatus.BLOCKER:
+ # Blockers are never ignored
return False
if cri.release_glob is not None:
if not self.__check_ignore_match_pattern(cri.release_glob,
cr.release_name):
diff --git a/atr/storage/readers/releases.py b/atr/storage/readers/releases.py
index b2fe5b2..9395f0c 100644
--- a/atr/storage/readers/releases.py
+++ b/atr/storage/readers/releases.py
@@ -34,8 +34,10 @@ class CheckerAccumulator:
success: int = 0
warning: int = 0
failure: int = 0
+ blocker: int = 0
warning_files: dict[str, int] = dataclasses.field(default_factory=dict)
failure_files: dict[str, int] = dataclasses.field(default_factory=dict)
+ blocker_files: dict[str, int] = dataclasses.field(default_factory=dict)
class GeneralPublic:
@@ -86,6 +88,9 @@ class GeneralPublic:
elif kind == "warning":
acc.warning += 1
acc.warning_files[path_str] =
acc.warning_files.get(path_str, 0) + 1
+ elif result.status == sql.CheckResultStatus.BLOCKER:
+ acc.blocker += 1
+ acc.blocker_files[path_str] =
acc.blocker_files.get(path_str, 0) + 1
else:
acc.failure += 1
acc.failure_files[path_str] =
acc.failure_files.get(path_str, 0) + 1
@@ -99,7 +104,7 @@ class GeneralPublic:
self.__accumulate_results(info.errors, paths_set, checker_data,
"failure")
for checker, acc in sorted(checker_data.items()):
- if (acc.warning == 0) and (acc.failure == 0):
+ if (acc.warning == 0) and (acc.failure == 0) and (acc.blocker ==
0):
continue
info.checker_stats.append(
types.CheckerStats(
@@ -107,8 +112,10 @@ class GeneralPublic:
success_count=acc.success,
warning_count=acc.warning,
failure_count=acc.failure,
+ blocker_count=acc.blocker,
warning_files=acc.warning_files,
failure_files=acc.failure_files,
+ blocker_files=acc.blocker_files,
)
)
@@ -126,16 +133,16 @@ class GeneralPublic:
await self.__successes(cs)
await self.__warnings(cs)
await self.__errors(cs)
- await self.__blocking(cs)
+ await self.__blocker(cs)
- async def __blocking(self, cs: types.ChecksSubset) -> None:
- blocking = await self.__data.check_result(
+ async def __blocker(self, cs: types.ChecksSubset) -> None:
+ blocker = await self.__data.check_result(
release_name=cs.release.name,
revision_number=cs.latest_revision_number,
member_rel_path=None,
- status=sql.CheckResultStatus.BLOCKING,
+ status=sql.CheckResultStatus.BLOCKER,
).all()
- for result in blocking:
+ for result in blocker:
if primary_rel_path := result.primary_rel_path:
cs.info.errors.setdefault(pathlib.Path(primary_rel_path),
[]).append(result)
diff --git a/atr/storage/types.py b/atr/storage/types.py
index 22c5bf7..c61c5a8 100644
--- a/atr/storage/types.py
+++ b/atr/storage/types.py
@@ -31,8 +31,10 @@ class CheckerStats:
success_count: int
warning_count: int
failure_count: int
+ blocker_count: int
warning_files: dict[str, int]
failure_files: dict[str, int]
+ blocker_files: dict[str, int]
@dataclasses.dataclass
diff --git a/atr/tasks/checks/__init__.py b/atr/tasks/checks/__init__.py
index 2126c21..08d2c4c 100644
--- a/atr/tasks/checks/__init__.py
+++ b/atr/tasks/checks/__init__.py
@@ -276,11 +276,11 @@ class Recorder:
def input_hash(self) -> str | None:
return self.__input_hash
- async def blocking(
+ async def blocker(
self, message: str, data: Any, primary_rel_path: str | None = None,
member_rel_path: str | None = None
) -> sql.CheckResult:
return await self._add(
- sql.CheckResultStatus.BLOCKING,
+ sql.CheckResultStatus.BLOCKER,
message,
data,
primary_rel_path=primary_rel_path,
diff --git a/atr/tasks/checks/hashing.py b/atr/tasks/checks/hashing.py
index 8007545..e8ae78f 100644
--- a/atr/tasks/checks/hashing.py
+++ b/atr/tasks/checks/hashing.py
@@ -75,7 +75,7 @@ async def check(args: checks.FunctionArguments) ->
results.Results | None:
{"computed_hash": computed_hash, "expected_hash":
expected_hash},
)
else:
- await recorder.blocking(
+ await recorder.blocker(
f"Hash ({algorithm}) mismatch",
{"computed_hash": computed_hash, "expected_hash":
expected_hash},
)
diff --git a/atr/tasks/checks/license.py b/atr/tasks/checks/license.py
index b715558..066fef3 100644
--- a/atr/tasks/checks/license.py
+++ b/atr/tasks/checks/license.py
@@ -255,7 +255,7 @@ def _files_check_core_logic(artifact_path: str, is_podling:
bool) -> Iterator[Re
yield from _notice_results(notice_results)
if is_podling and (not disclaimer_found):
yield ArtifactResult(
- status=sql.CheckResultStatus.BLOCKING,
+ status=sql.CheckResultStatus.BLOCKER,
message="No DISCLAIMER or DISCLAIMER-WIP file found",
data=None,
)
@@ -373,7 +373,7 @@ def _headers_check_core_logic(artifact_path: str,
ignore_lines: list[str], exclu
artifact_data.files_with_invalid_headers += 1
case sql.CheckResultStatus.FAILURE:
artifact_data.files_with_invalid_headers += 1
- case sql.CheckResultStatus.BLOCKING:
+ case sql.CheckResultStatus.BLOCKER:
artifact_data.files_with_invalid_headers += 1
case sql.CheckResultStatus.EXCEPTION:
artifact_data.files_with_invalid_headers += 1
@@ -505,7 +505,7 @@ def _license_results(
license_files_size = len(license_results)
if license_files_size == 0:
yield ArtifactResult(
- status=sql.CheckResultStatus.BLOCKING,
+ status=sql.CheckResultStatus.BLOCKER,
message="No LICENSE file found",
data=None,
)
@@ -551,7 +551,7 @@ def _notice_results(
notice_files_size = len(notice_results)
if notice_files_size == 0:
yield ArtifactResult(
- status=sql.CheckResultStatus.BLOCKING,
+ status=sql.CheckResultStatus.BLOCKER,
message="No NOTICE file found",
data=None,
)
@@ -589,8 +589,8 @@ async def _record_artifact(recorder: checks.Recorder,
result: ArtifactResult) ->
await recorder.warning(result.message, result.data)
case sql.CheckResultStatus.FAILURE:
await recorder.failure(result.message, result.data)
- case sql.CheckResultStatus.BLOCKING:
- await recorder.blocking(result.message, result.data)
+ case sql.CheckResultStatus.BLOCKER:
+ await recorder.blocker(result.message, result.data)
case sql.CheckResultStatus.EXCEPTION:
await recorder.exception(result.message, result.data)
@@ -603,7 +603,7 @@ async def _record_member(recorder: checks.Recorder, result:
MemberResult) -> Non
await recorder.warning(result.message, result.data,
member_rel_path=result.path)
case sql.CheckResultStatus.FAILURE:
await recorder.failure(result.message, result.data,
member_rel_path=result.path)
- case sql.CheckResultStatus.BLOCKING:
- await recorder.blocking(result.message, result.data,
member_rel_path=result.path)
+ case sql.CheckResultStatus.BLOCKER:
+ await recorder.blocker(result.message, result.data,
member_rel_path=result.path)
case sql.CheckResultStatus.EXCEPTION:
await recorder.exception(result.message, result.data,
member_rel_path=result.path)
diff --git a/atr/tasks/checks/paths.py b/atr/tasks/checks/paths.py
index b56f2e3..4f01dfa 100644
--- a/atr/tasks/checks/paths.py
+++ b/atr/tasks/checks/paths.py
@@ -106,7 +106,7 @@ async def _check_artifact_rules(
relative_path: pathlib.Path,
relative_paths: set[str],
errors: list[str],
- blocking: list[str],
+ blockers: list[str],
is_podling: bool,
) -> None:
"""Check rules specific to artifact files."""
@@ -115,7 +115,7 @@ async def _check_artifact_rules(
# RDP says that .asc is required
asc_path = full_path.with_suffix(full_path.suffix + ".asc")
if not await aiofiles.os.path.exists(asc_path):
- blocking.append(f"Missing corresponding signature file
({relative_path}.asc)")
+ blockers.append(f"Missing corresponding signature file
({relative_path}.asc)")
# RDP requires one of .sha256 or .sha512
relative_sha256_path = relative_path.with_suffix(relative_path.suffix +
".sha256")
@@ -123,13 +123,13 @@ async def _check_artifact_rules(
has_sha256 = str(relative_sha256_path) in relative_paths
has_sha512 = str(relative_sha512_path) in relative_paths
if not (has_sha256 or has_sha512):
- blocking.append(f"Missing corresponding checksum file
({relative_path}.sha256 or {relative_path}.sha512)")
+ blockers.append(f"Missing corresponding checksum file
({relative_path}.sha256 or {relative_path}.sha512)")
# IP requires "incubating" in the filename
if is_podling is True:
# TODO: Allow "incubator" too as #114 requests?
if "incubating" not in full_path.name:
- blocking.append("Podling artifact filenames must include
'incubating'")
+ blockers.append("Podling artifact filenames must include
'incubating'")
async def _check_metadata_rules(
@@ -138,7 +138,7 @@ async def _check_metadata_rules(
relative_paths: set[str],
ext_metadata: str,
errors: list[str],
- blocking: list[str],
+ blockers: list[str],
warnings: list[str],
) -> None:
"""Check rules specific to metadata files (.asc, .sha*, etc.)."""
@@ -146,7 +146,7 @@ async def _check_metadata_rules(
if ".md5" in suffixes:
# Forbidden by RCP, deprecated by RDP
- blocking.append("The use of .md5 is forbidden, please use .sha512")
+ blockers.append("The use of .md5 is forbidden, please use .sha512")
if ".sha1" in suffixes:
# Deprecated by RDP
errors.append("The use of .sha1 is deprecated, please use .sha512")
@@ -155,7 +155,7 @@ async def _check_metadata_rules(
errors.append("The use of .sha is discouraged, please use .sha512")
if ".sig" in suffixes:
# Forbidden by RCP, forbidden by RDP
- blocking.append("Binary signature files (.sig) are forbidden, please
use .asc")
+ blockers.append("Binary signature files (.sig) are forbidden, please
use .asc")
# "Signature and checksum files for verifying distributed artifacts should
# not be provided, unless named as indicated above." (RDP)
@@ -189,7 +189,7 @@ async def _check_path_process_single(
await asyncio.sleep(20)
errors: list[str] = []
- blocking: list[str] = []
+ blockers: list[str] = []
warnings: list[str] = []
# The Release Distribution Policy specifically allows README and CHANGES,
etc.
@@ -212,10 +212,10 @@ async def _check_path_process_single(
allowed_top_level = _ALLOWED_TOP_LEVEL
if ext_artifact:
log.info(f"Checking artifact rules for {full_path}")
- await _check_artifact_rules(base_path, relative_path, relative_paths,
errors, blocking, is_podling)
+ await _check_artifact_rules(base_path, relative_path, relative_paths,
errors, blockers, is_podling)
elif ext_metadata:
log.info(f"Checking metadata rules for {full_path}")
- await _check_metadata_rules(base_path, relative_path, relative_paths,
ext_metadata, errors, blocking, warnings)
+ await _check_metadata_rules(base_path, relative_path, relative_paths,
ext_metadata, errors, blockers, warnings)
else:
log.info(f"Checking general rules for {full_path}")
if (relative_path.parent == pathlib.Path(".")) and (relative_path.name
not in allowed_top_level):
@@ -227,7 +227,7 @@ async def _check_path_process_single(
recorder_success,
relative_path_str,
errors,
- blocking,
+ blockers,
warnings,
)
@@ -238,16 +238,16 @@ async def _record(
recorder_success: checks.Recorder,
relative_path_str: str,
errors: list[str],
- blocking: list[str],
+ blockers: list[str],
warnings: list[str],
) -> None:
for error in errors:
await recorder_errors.failure(error, {},
primary_rel_path=relative_path_str)
- for item in blocking:
- await recorder_errors.blocking(item, {},
primary_rel_path=relative_path_str)
+ for item in blockers:
+ await recorder_errors.blocker(item, {},
primary_rel_path=relative_path_str)
for warning in warnings:
await recorder_warnings.warning(warning, {},
primary_rel_path=relative_path_str)
- if not (errors or blocking or warnings):
+ if not (errors or blockers or warnings):
await recorder_success.success(
"Path structure and naming conventions conform to policy", {},
primary_rel_path=relative_path_str
)
diff --git a/atr/tasks/checks/rat.py b/atr/tasks/checks/rat.py
index 1929ae4..3812157 100644
--- a/atr/tasks/checks/rat.py
+++ b/atr/tasks/checks/rat.py
@@ -167,9 +167,9 @@ async def _check_core(
# Record individual file failures before the overall result
for file in result.unknown_license_files:
- await recorder.blocking("Unknown license", None,
member_rel_path=file.name)
+ await recorder.failure("Unknown license", None,
member_rel_path=file.name)
for file in result.unapproved_files:
- await recorder.blocking("Unapproved license", {"license":
file.license}, member_rel_path=file.name)
+ await recorder.failure("Unapproved license", {"license":
file.license}, member_rel_path=file.name)
# Convert to dict for storage, excluding the file lists, which are already
recorded
result_data = result.model_dump(exclude={"unapproved_files",
"unknown_license_files"})
diff --git a/atr/tasks/checks/signature.py b/atr/tasks/checks/signature.py
index ab247b5..5bbaf67 100644
--- a/atr/tasks/checks/signature.py
+++ b/atr/tasks/checks/signature.py
@@ -63,7 +63,7 @@ async def check(args: checks.FunctionArguments) ->
results.Results | None:
)
if result_data.get("error"):
# TODO: This should perhaps be a failure
- await recorder.blocking(result_data["error"], result_data)
+ await recorder.blocker(result_data["error"], result_data)
elif result_data.get("verified"):
await recorder.success("Signature verified successfully",
result_data)
else:
diff --git a/atr/templates/report-selected-path.html
b/atr/templates/report-selected-path.html
index bbd7b67..b0f7a8b 100644
--- a/atr/templates/report-selected-path.html
+++ b/atr/templates/report-selected-path.html
@@ -51,10 +51,10 @@
<code>{{ package.filename }}</code>
</div>
{% if primary_results %}
- {% set blocking_count = primary_results|selectattr("status.value",
"equalto", "blocking")|list|length %}
{% set status_counts = {
"success": primary_results|selectattr("status.value", "equalto",
"success")|list|length,
- "failure": (primary_results|selectattr("status.value", "equalto",
"failure")|list|length) + blocking_count,
+ "failure": primary_results|selectattr("status.value", "equalto",
"failure")|list|length,
+ "blocker": primary_results|selectattr("status.value", "equalto",
"blocker")|list|length,
"warning": primary_results|selectattr("status.value", "equalto",
"warning")|list|length,
"exception": primary_results|selectattr("status.value", "equalto",
"exception")|list|length
} %}
@@ -71,14 +71,14 @@
<h2>Report results</h2>
<div class="d-flex flex-wrap gap-3 mb-4">
- {% if primary_results and (status_counts.success > 0 or
status_counts.failure > 0 or status_counts.warning > 0 or
status_counts.exception > 0) %}
- {% set all_primary_are_success = status_counts.failure == 0 and
status_counts.warning == 0 and status_counts.exception == 0 %}
+ {% if primary_results and (status_counts.success > 0 or
status_counts.failure > 0 or status_counts.blocker > 0 or status_counts.warning
> 0 or status_counts.exception > 0) %}
+ {% set all_primary_are_success = status_counts.failure == 0 and
status_counts.blocker == 0 and status_counts.warning == 0 and
status_counts.exception == 0 %}
{% for status, count in status_counts.items() %}
{% if count > 0 %}
{% set bs_status = 'danger' if status == 'exception' or status ==
'failure' else status %}
<button id="btn-toggle-primary-{{ status }}"
type="button"
- class="btn page-toggle-status {% if status == 'success' and
not all_primary_are_success %}btn-outline-success{% elif status == 'success'
and all_primary_are_success %}btn-success{% else %}btn-{{ bs_status }}{% endif
%}"
+ class="btn page-toggle-status {% if status == 'success' and
not all_primary_are_success %}btn-outline-success{% elif status == 'success'
and all_primary_are_success %}btn-success{% elif status == 'blocker'
%}atr-btn-blocker{% else %}btn-{{ bs_status }}{% endif %}"
data-type="primary"
data-status="{{ status }}">
<span>
@@ -88,7 +88,7 @@
Hide
{% endif %}
</span>
- {{ status|title }} (<code>{{ count }}</code>)
+ {{ "Blocker" if status == "blocker" else status|title }} (<code>{{
count }}</code>)
</button>
{% endif %}
{% endfor %}
@@ -108,7 +108,7 @@
</thead>
<tbody>
{% for primary_result in primary_results %}
- <tr class="atr-result-primary atr-result-status-{{ 'failure' if
primary_result.status.value == 'blocking' else primary_result.status.value }}
{% if primary_result.status.value == 'success' and not all_primary_are_success
%}atr-hide{% endif %}">
+ <tr class="atr-result-primary atr-result-status-{{
primary_result.status.value }} {% if primary_result.status.value == 'success'
and not all_primary_are_success %}atr-hide{% endif %}">
<th scope="row" class="align-middle fw-bold">{{
function_name_from_key(primary_result.checker) }}</th>
<td class="align-middle text-break">
{% if primary_result.data is mapping and
primary_result.data.keys()|length > 0 %}
@@ -214,16 +214,9 @@
</td>
<td class="align-middle text-center atr-sans">
<div class="d-inline-flex flex-column align-items-center
gap-1">
- <span class="badge rounded-pill {% if
primary_result.status.value == "success" %}bg-success {% elif
primary_result.status.value == "failure" or primary_result.status.value ==
"blocking" %}bg-danger {% elif primary_result.status.value == "warning"
%}bg-warning {% elif primary_result.status.value == "exception" %}bg-danger {%
else %}bg-secondary{% endif %}">
- {{ "Failure" if primary_result.status.value == "blocking"
else primary_result.status.value|title }}
+ <span class="badge rounded-pill {% if
primary_result.status.value == "success" %}bg-success {% elif
primary_result.status.value == "failure" %}bg-danger {% elif
primary_result.status.value == "blocker" %}atr-bg-blocker {% elif
primary_result.status.value == "warning" %}bg-warning {% elif
primary_result.status.value == "exception" %}bg-danger {% else %}bg-secondary{%
endif %}">
+ {{ "Blocker" if primary_result.status.value == "blocker"
else primary_result.status.value|title }}
</span>
- {% if primary_result.status.value == "blocking" %}
- <span class="badge rounded-pill atr-bg-blocking border
small"
- title="You cannot release when there is a blocking
check result"
- aria-label="You cannot release when there is a
blocking check result">
- <i class="bi bi-shield-lock me-1"></i>Blocking
- </span>
- {% endif %}
{% if primary_result.cached %}
<span class="badge rounded-pill bg-secondary-subtle
text-secondary-emphasis border border-secondary-subtle small"
title="Cached result"
@@ -244,25 +237,23 @@
{% if member_results %}
<h2>Member results</h2>
<p>This file is an archive. We have extracted the contents of the
archive and checked each file individually.</p>
- {% set member_status_counts = {"success": 0, "failure": 0, "warning": 0,
"exception": 0} %}
+ {% set member_status_counts = {"success": 0, "failure": 0, "blocker": 0,
"warning": 0, "exception": 0} %}
{% for path, m_results in member_results.items() %}
{% for m_result in m_results %}
- {% if m_result.status.value == "blocking" %}
- {% set _ = member_status_counts.update({"failure":
member_status_counts.failure + 1}) %}
- {% elif m_result.status.value in member_status_counts %}
+ {% if m_result.status.value in member_status_counts %}
{% set _ = member_status_counts.update({m_result.status.value:
member_status_counts[m_result.status.value] + 1}) %}
{% endif %}
{% endfor %}
{% endfor %}
- {% if member_status_counts.success > 0 or member_status_counts.failure >
0 or member_status_counts.warning > 0 or member_status_counts.exception > 0 %}
- {% set all_member_are_success = member_status_counts.failure == 0 and
member_status_counts.warning == 0 and member_status_counts.exception == 0 %}
+ {% if member_status_counts.success > 0 or member_status_counts.failure >
0 or member_status_counts.blocker > 0 or member_status_counts.warning > 0 or
member_status_counts.exception > 0 %}
+ {% set all_member_are_success = member_status_counts.failure == 0 and
member_status_counts.blocker == 0 and member_status_counts.warning == 0 and
member_status_counts.exception == 0 %}
<div class="d-flex flex-wrap gap-2 mb-3 align-items-center">
{% for status, count in member_status_counts.items() %}
{% if count > 0 %}
{% set bs_status = 'danger' if status == 'exception' or status
== 'failure' else status %}
<button id="btn-toggle-member-{{ status }}"
type="button"
- class="btn page-toggle-status {% if status == 'success'
and not all_member_are_success %}btn-outline-success{% elif status == 'success'
and all_member_are_success %}btn-success{% else %}btn-{{ bs_status }}{% endif
%}"
+ class="btn page-toggle-status {% if status == 'success'
and not all_member_are_success %}btn-outline-success{% elif status == 'success'
and all_member_are_success %}btn-success{% elif status == 'blocker'
%}atr-btn-blocker{% else %}btn-{{ bs_status }}{% endif %}"
data-type="member"
data-status="{{ status }}">
<span>
@@ -272,7 +263,7 @@
Hide
{% endif %}
</span>
- {{ status|title }} (<code>{{ count }}</code>)
+ {{ "Blocker" if status == "blocker" else status|title }}
(<code>{{ count }}</code>)
</button>
{% endif %}
{% endfor %}
@@ -298,7 +289,7 @@
{% for member_result in member_results_list %}
{# The striping class here is now technically redundant because
of the JS striping #}
{# But we leave it here for clean initial page rendering #}
- <tr class="atr-result-member atr-result-status-{{ 'failure' if
member_result.status.value == 'blocking' else member_result.status.value }} {%
if member_result.status.value == 'success' and not all_member_are_success
%}atr-hide{% endif %} {% if loop.index is odd %}page-member-visible-odd{% endif
%} ">
+ <tr class="atr-result-member atr-result-status-{{
member_result.status.value }} {% if member_result.status.value == 'success' and
not all_member_are_success %}atr-hide{% endif %} {% if loop.index is odd
%}page-member-visible-odd{% endif %} ">
<td class="align-middle">{{ member_rel_path }}</td>
<th scope="row" class="align-middle fw-bold">{{
function_name_from_key(member_result.checker) }}</th>
<td class="align-middle text-break">
@@ -306,16 +297,9 @@
</td>
<td class="align-middle text-center atr-sans">
<div class="d-inline-flex flex-column align-items-center
gap-1">
- <span class="badge rounded-pill {% if
member_result.status.value == "success" %}bg-success {% elif
member_result.status.value == "failure" or member_result.status.value ==
"blocking" %}bg-danger {% elif member_result.status.value == "warning"
%}bg-warning {% elif member_result.status.value == "exception" %}bg-danger {%
else %}bg-secondary{% endif %}">
- {{ "Failure" if member_result.status.value == "blocking"
else member_result.status.value|title }}
+ <span class="badge rounded-pill {% if
member_result.status.value == "success" %}bg-success {% elif
member_result.status.value == "failure" %}bg-danger {% elif
member_result.status.value == "blocker" %}atr-bg-blocker {% elif
member_result.status.value == "warning" %}bg-warning {% elif
member_result.status.value == "exception" %}bg-danger {% else %}bg-secondary{%
endif %}">
+ {{ "Blocker" if member_result.status.value == "blocker"
else member_result.status.value|title }}
</span>
- {% if member_result.status.value == "blocking" %}
- <span class="badge rounded-pill atr-bg-blocking border
small"
- title="You cannot release when there is a blocking
check result"
- aria-label="You cannot release when there is a
blocking check result">
- <i class="bi bi-shield-lock me-1"></i>Blocking
- </span>
- {% endif %}
{% if member_result.cached %}
<span class="badge rounded-pill bg-secondary-subtle
text-secondary-emphasis border border-secondary-subtle small"
title="Cached result"
diff --git a/migrations/versions/0048_2026.02.06_blocking_to_blocker.py
b/migrations/versions/0048_2026.02.06_blocking_to_blocker.py
new file mode 100644
index 0000000..c67f29a
--- /dev/null
+++ b/migrations/versions/0048_2026.02.06_blocking_to_blocker.py
@@ -0,0 +1,25 @@
+"""Rename blocking check result status to blocker
+
+Revision ID: 0048_2026.02.06_blocking_to_blocker
+Revises: 0047_2026.02.03_525fe161
+Create Date: 2026-02-06 16:00:00.000000+00:00
+"""
+
+from collections.abc import Sequence
+
+from alembic import op
+
+revision: str = "0048_2026.02.06_blocking_to_blocker"
+down_revision: str | None = "0047_2026.02.03_525fe161"
+branch_labels: str | Sequence[str] | None = None
+depends_on: str | Sequence[str] | None = None
+
+
+def upgrade() -> None:
+ op.execute("UPDATE checkresult SET status = 'BLOCKER' WHERE status =
'BLOCKING'")
+ op.execute("UPDATE checkresult SET status = 'BLOCKER' WHERE status =
'blocking'")
+
+
+def downgrade() -> None:
+ op.execute("UPDATE checkresult SET status = 'BLOCKING' WHERE status =
'BLOCKER'")
+ op.execute("UPDATE checkresult SET status = 'BLOCKING' WHERE status =
'blocker'")
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]