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]


Reply via email to