This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-releases-client.git


The following commit(s) were added to refs/heads/main by this push:
     new 505bf24  Add a command to ignore specified check results
505bf24 is described below

commit 505bf24bc07c5731b5929e3b40eca2908cc8149e
Author: Sean B. Palmer <[email protected]>
AuthorDate: Tue Jul 29 20:45:15 2025 +0100

    Add a command to ignore specified check results
---
 pyproject.toml              |  4 ++--
 src/atrclient/client.py     | 51 +++++++++++++++++++++++++++++++++++++++++++++
 src/atrclient/models/api.py | 22 ++++++++++++++++++-
 src/atrclient/models/sql.py | 26 +++++++++++++++++++++++
 uv.lock                     | 10 ++++-----
 5 files changed, 105 insertions(+), 8 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index c41c93e..3307ef1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ build-backend = "hatchling.build"
 
 [project]
 name            = "apache-trusted-releases"
-version         = "0.20250729.1447"
+version         = "0.20250729.1943"
 description     = "ATR CLI and Python API"
 readme          = "README.md"
 requires-python = ">=3.13"
@@ -79,4 +79,4 @@ filterwarnings = [
 ]
 
 [tool.uv]
-exclude-newer = "2025-07-29T14:47:00Z"
+exclude-newer = "2025-07-29T19:43:00Z"
diff --git a/src/atrclient/client.py b/src/atrclient/client.py
index aa3849e..931aeea 100755
--- a/src/atrclient/client.py
+++ b/src/atrclient/client.py
@@ -156,6 +156,12 @@ def api_post(path: str) -> Callable[[Callable[[ApiPost, 
A], R]], Callable[[A], R
     return decorator
 
 
+@api_post("/checks/ignore/add")
+def api_checks_ignore_add(api: ApiPost, args: models.api.ChecksIgnoreAddArgs) 
-> models.api.ChecksIgnoreAddResults:
+    response = api.post(args)
+    return models.api.validate_checks_ignore_add(response)
+
+
 @api_get("/checks/list")
 def api_checks_list(api: ApiGet, project: str, version: str, revision: str) -> 
models.api.ChecksListResults:
     response = api.get(project, version, revision)
@@ -371,6 +377,51 @@ def app_checks_failures(
     checks_list = api_checks_list(project, version, revision)
     checks_display_status("failure", checks_list.checks, members=members)
 
+    # committee_name: str = schema.Field(..., **example("example"))
+    # release_glob: str | None = schema.Field(default=None, 
**example("example-0.0.*"))
+    # revision_number: str | None = schema.Field(default=None, 
**example("00001"))
+    # checker_glob: str | None = schema.Field(default=None, 
**example("atr.tasks.checks.license.files"))
+    # primary_rel_path_glob: str | None = schema.Field(default=None, 
**example("apache-example-0.0.1-*.tar.gz"))
+    # member_rel_path_glob: str | None = schema.Field(default=None, 
**example("apache-example-0.0.1/*.xml"))
+    # status: sql.CheckResultStatusIgnore | None = schema.Field(
+    #     default=None, **example(sql.CheckResultStatusIgnore.FAILURE)
+    # )
+    # message_glob: str | None = schema.Field(default=None, **example("sha512 
matches for apache-example-0.0.1/*.xml"))
+
+
+@APP_CHECKS.command(name="ignore", help="Ignore a check result.")
+def app_checks_ignore(
+    committee: str,
+    /,
+    release: str | None = None,
+    revision: str | None = None,
+    checker: str | None = None,
+    primary_rel_path: str | None = None,
+    member_rel_path: str | None = None,
+    status: models.sql.CheckResultStatusIgnore | None = None,
+    message: str | None = None,
+) -> None:
+    args = models.api.ChecksIgnoreAddArgs(
+        committee_name=committee,
+        release_glob=release,
+        revision_number=revision,
+        checker_glob=checker,
+        primary_rel_path_glob=primary_rel_path,
+        member_rel_path_glob=member_rel_path,
+        status=status,
+        message_glob=message,
+    )
+    api_checks_ignore_add(args)
+    print("Check result ignored for:")
+    print(f"  Committee: {committee}")
+    print(f"  Release (glob): {release}")
+    print(f"  Revision: {revision}")
+    print(f"  Checker (glob): {checker}")
+    print(f"  Primary rel path (glob): {primary_rel_path}")
+    print(f"  Member rel path (glob): {member_rel_path}")
+    print(f"  Status: {status}")
+    print(f"  Message (glob): {message}")
+
 
 @APP_CHECKS.command(name="status", help="Get check status for a release 
revision.")
 def app_checks_status(
diff --git a/src/atrclient/models/api.py b/src/atrclient/models/api.py
index 414a11d..009ae07 100644
--- a/src/atrclient/models/api.py
+++ b/src/atrclient/models/api.py
@@ -34,6 +34,24 @@ class ResultsTypeError(TypeError):
     pass
 
 
+class ChecksIgnoreAddArgs(schema.Strict):
+    committee_name: str = schema.Field(..., **example("example"))
+    release_glob: str | None = schema.Field(default=None, 
**example("example-0.0.*"))
+    revision_number: str | None = schema.Field(default=None, 
**example("00001"))
+    checker_glob: str | None = schema.Field(default=None, 
**example("atr.tasks.checks.license.files"))
+    primary_rel_path_glob: str | None = schema.Field(default=None, 
**example("apache-example-0.0.1-*.tar.gz"))
+    member_rel_path_glob: str | None = schema.Field(default=None, 
**example("apache-example-0.0.1/*.xml"))
+    status: sql.CheckResultStatusIgnore | None = schema.Field(
+        default=None, **example(sql.CheckResultStatusIgnore.FAILURE)
+    )
+    message_glob: str | None = schema.Field(default=None, **example("sha512 
matches for apache-example-0.0.1/*.xml"))
+
+
+class ChecksIgnoreAddResults(schema.Strict):
+    endpoint: Literal["/checks/ignore/add"] = schema.Field(alias="endpoint")
+    success: Literal[True] = schema.Field(..., **example(True))
+
+
 class ChecksListResults(schema.Strict):
     endpoint: Literal["/checks/list"] = schema.Field(alias="endpoint")
     checks: Sequence[sql.CheckResult]
@@ -381,7 +399,8 @@ class VoteTabulateResults(schema.Strict):
 # This is for *Results classes only
 # We do NOT put *Args classes here
 Results = Annotated[
-    ChecksListResults
+    ChecksIgnoreAddResults
+    | ChecksListResults
     | ChecksOngoingResults
     | CommitteeGetResults
     | CommitteeKeysResults
@@ -430,6 +449,7 @@ def validator[T](t: type[T]) -> Callable[[Any], T]:
     return validate
 
 
+validate_checks_ignore_add = validator(ChecksIgnoreAddResults)
 validate_checks_list = validator(ChecksListResults)
 validate_checks_ongoing = validator(ChecksOngoingResults)
 validate_committee_get = validator(CommitteeGetResults)
diff --git a/src/atrclient/models/sql.py b/src/atrclient/models/sql.py
index 4a1ccc8..d58121c 100644
--- a/src/atrclient/models/sql.py
+++ b/src/atrclient/models/sql.py
@@ -58,6 +58,12 @@ class CheckResultStatus(str, enum.Enum):
     WARNING = "warning"
 
 
+class CheckResultStatusIgnore(str, enum.Enum):
+    EXCEPTION = "exception"
+    FAILURE = "failure"
+    WARNING = "warning"
+
+
 class ProjectStatus(str, enum.Enum):
     ACTIVE = "active"
     DORMANT = "dormant"
@@ -712,6 +718,26 @@ class CheckResult(sqlmodel.SQLModel, table=True):
     )
 
 
+class CheckResultIgnore(sqlmodel.SQLModel, table=True):
+    id: int = sqlmodel.Field(default=None, primary_key=True, **example(123))
+    asf_uid: str = sqlmodel.Field(**example("user"))
+    created: datetime.datetime = sqlmodel.Field(
+        sa_column=sqlalchemy.Column(UTCDateTime),
+        **example(datetime.datetime(2025, 5, 1, 1, 2, 3, tzinfo=datetime.UTC)),
+    )
+    committee_name: str = sqlmodel.Field(**example("example"))
+    release_glob: str | None = sqlmodel.Field(**example("example-0.0.*"))
+    revision_number: str | None = sqlmodel.Field(**example("00001"))
+    checker_glob: str | None = 
sqlmodel.Field(**example("atr.tasks.checks.license.files"))
+    primary_rel_path_glob: str | None = 
sqlmodel.Field(**example("apache-example-0.0.1-*.tar.gz"))
+    member_rel_path_glob: str | None = 
sqlmodel.Field(**example("apache-example-0.0.1/*.xml"))
+    status: CheckResultStatusIgnore | None = sqlmodel.Field(
+        default=None,
+        **example(CheckResultStatusIgnore.FAILURE),
+    )
+    message_glob: str | None = sqlmodel.Field(**example("sha512 matches for 
apache-example-0.0.1/*.xml"))
+
+
 # DistributionChannel: Project
 class DistributionChannel(sqlmodel.SQLModel, table=True):
     id: int = sqlmodel.Field(default=None, primary_key=True)
diff --git a/uv.lock b/uv.lock
index 71123ac..3adf94c 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2,7 +2,7 @@ version = 1
 requires-python = ">=3.13"
 
 [options]
-exclude-newer = "2025-07-29T14:47:00Z"
+exclude-newer = "2025-07-29T19:43:00Z"
 
 [[package]]
 name = "aiohappyeyeballs"
@@ -83,7 +83,7 @@ wheels = [
 
 [[package]]
 name = "apache-trusted-releases"
-version = "0.20250729.1447"
+version = "0.20250729.1943"
 source = { editable = "." }
 dependencies = [
     { name = "aiohttp" },
@@ -251,11 +251,11 @@ wheels = [
 
 [[package]]
 name = "docutils"
-version = "0.21.2"
+version = "0.22"
 source = { registry = "https://pypi.org/simple"; }
-sdist = { url = 
"https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz";,
 hash = 
"sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size 
= 2204444 }
+sdist = { url = 
"https://files.pythonhosted.org/packages/e9/86/5b41c32ecedcfdb4c77b28b6cb14234f252075f8cdb254531727a35547dd/docutils-0.22.tar.gz";,
 hash = 
"sha256:ba9d57750e92331ebe7c08a1bbf7a7f8143b86c476acd51528b042216a6aad0f", size 
= 2277984 }
 wheels = [
-    { url = 
"https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl";,
 hash = 
"sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size 
= 587408 },
+    { url = 
"https://files.pythonhosted.org/packages/44/57/8db39bc5f98f042e0153b1de9fb88e1a409a33cda4dd7f723c2ed71e01f6/docutils-0.22-py3-none-any.whl";,
 hash = 
"sha256:4ed966a0e96a0477d852f7af31bdcb3adc049fbb35ccba358c2ea8a03287615e", size 
= 630709 },
 ]
 
 [[package]]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to