You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by ar...@apache.org on 2026/03/18 13:54:48 UTC
(tooling-trusted-releases) branch check_version_database created (now 905e9234)
This is an automated email from the ASF dual-hosted git repository.
arm pushed a change to branch check_version_database
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
at 905e9234 #892 - record check version in database (and fix a couple of type issues in tests)
This branch includes the following new commits:
new 905e9234 #892 - record check version in database (and fix a couple of type issues in tests)
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org
(tooling-trusted-releases) 01/01: #892 - record check version in database (and fix a couple of type issues in tests)
Posted by ar...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
arm pushed a commit to branch check_version_database
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
commit 905e9234c9de39ce8158ce608bae468cb1eeb344
Author: Alastair McFarlane <ar...@apache.org>
AuthorDate: Wed Mar 18 13:53:16 2026 +0000
#892 - record check version in database (and fix a couple of type issues in tests)
---
atr/models/sql.py | 2 ++
atr/tasks/checks/__init__.py | 11 ++++++++++
atr/tasks/checks/compare.py | 1 +
atr/tasks/checks/hashing.py | 1 +
atr/tasks/checks/license.py | 2 ++
atr/tasks/checks/paths.py | 4 ++++
atr/tasks/checks/rat.py | 1 +
atr/tasks/checks/signature.py | 1 +
atr/tasks/checks/targz.py | 1 +
atr/tasks/checks/zipformat.py | 1 +
migrations/versions/0061_2026.03.18_7838cfcc.py | 27 +++++++++++++++++++++++++
tests/unit/recorders.py | 11 ++++++----
tests/unit/test_checks_compare.py | 10 ++++++---
13 files changed, 66 insertions(+), 7 deletions(-)
diff --git a/atr/models/sql.py b/atr/models/sql.py
index 7f677449..d0a1a817 100644
--- a/atr/models/sql.py
+++ b/atr/models/sql.py
@@ -1015,6 +1015,8 @@ class CheckResult(sqlmodel.SQLModel, table=True):
# We don't call this latest_revision_number, because it might not be the latest
revision_number: str | None = sqlmodel.Field(default=None, index=True, **example("00005"))
checker: str = sqlmodel.Field(**example("atr.tasks.checks.license.files"))
+ checker_version: str | None = sqlmodel.Field(default=None, **example("2"))
+
primary_rel_path: str | None = sqlmodel.Field(
default=None, index=True, **example("apache-example-0.0.1-source.tar.gz")
)
diff --git a/atr/tasks/checks/__init__.py b/atr/tasks/checks/__init__.py
index 0b8beaff..acefedfa 100644
--- a/atr/tasks/checks/__init__.py
+++ b/atr/tasks/checks/__init__.py
@@ -61,6 +61,7 @@ class FunctionArguments:
class Recorder:
checker: str
+ checker_version: str | None
release_key: safe.ReleaseKey
project_key: safe.ProjectKey
version_key: safe.VersionKey
@@ -74,6 +75,7 @@ class Recorder:
def __init__(
self,
checker: str | Callable[..., Any],
+ checker_version: str | None,
inputs_hash: str | None,
project_key: safe.ProjectKey,
version_key: safe.VersionKey,
@@ -83,6 +85,7 @@ class Recorder:
afresh: bool = True,
) -> None:
self.checker = function_key(checker)
+ self.checker_version = checker_version
self.release_key = sql.release_key(project_key, version_key)
self.revision_number = revision_number
self.primary_rel_path = primary_rel_path
@@ -100,6 +103,7 @@ class Recorder:
async def create(
cls,
checker: str | Callable[..., Any],
+ checker_version: str | None,
inputs_hash: str,
project_key: safe.ProjectKey,
version_key: safe.VersionKey,
@@ -110,6 +114,7 @@ class Recorder:
) -> Recorder:
recorder = cls(
checker,
+ checker_version,
inputs_hash,
project_key,
version_key,
@@ -134,6 +139,8 @@ class Recorder:
) -> sql.CheckResult:
if self.constructed is False:
raise RuntimeError("Cannot add check result to a recorder that has not been constructed")
+ if self.checker_version is None:
+ raise RuntimeError("checker_version must be set before recording results")
if primary_rel_path is not None:
if self.primary_rel_path is not None:
raise ValueError("Cannot specify path twice")
@@ -149,6 +156,7 @@ class Recorder:
release_key=str(self.release_key),
revision_number=str(self.revision_number),
checker=self.checker,
+ checker_version=self.checker_version,
primary_rel_path=primary_rel_path or self.primary_rel_path,
member_rel_path=member_rel_path,
created=datetime.datetime.now(datetime.UTC),
@@ -243,6 +251,9 @@ class Recorder:
def input_hash(self) -> str | None:
return self.__input_hash
+ def set_checker_version(self, version: str) -> None:
+ self.checker_version = version
+
async def blocker(
self,
message: str,
diff --git a/atr/tasks/checks/compare.py b/atr/tasks/checks/compare.py
index 73264b64..1c6fe0c3 100644
--- a/atr/tasks/checks/compare.py
+++ b/atr/tasks/checks/compare.py
@@ -84,6 +84,7 @@ class TreeComparisonResult:
async def source_trees(args: checks.FunctionArguments) -> results.Results | None: # noqa: C901
recorder = await args.recorder()
+ recorder.set_checker_version(CHECK_VERSION)
is_source = await recorder.primary_path_is_source()
if not is_source:
log.info(
diff --git a/atr/tasks/checks/hashing.py b/atr/tasks/checks/hashing.py
index dd11a427..063f2422 100644
--- a/atr/tasks/checks/hashing.py
+++ b/atr/tasks/checks/hashing.py
@@ -34,6 +34,7 @@ CHECK_VERSION: Final[str] = "1"
async def check(args: checks.FunctionArguments) -> results.Results | None:
"""Check the hash of a file."""
recorder = await args.recorder()
+ recorder.set_checker_version(CHECK_VERSION)
if not (hash_abs_path := await recorder.abs_path()):
return None
diff --git a/atr/tasks/checks/license.py b/atr/tasks/checks/license.py
index 722e160f..a39a715b 100644
--- a/atr/tasks/checks/license.py
+++ b/atr/tasks/checks/license.py
@@ -132,6 +132,7 @@ type Result = ArtifactResult | MemberResult | MemberSkippedResult
async def files(args: checks.FunctionArguments) -> results.Results | None:
"""Check that the LICENSE and NOTICE files exist and are valid."""
recorder = await args.recorder()
+ recorder.set_checker_version(CHECK_VERSION_FILES)
if not (artifact_abs_path := await recorder.abs_path()):
return None
@@ -173,6 +174,7 @@ async def files(args: checks.FunctionArguments) -> results.Results | None:
async def headers(args: checks.FunctionArguments) -> results.Results | None:
"""Check that all source files have valid license headers."""
recorder = await args.recorder()
+ recorder.set_checker_version(CHECK_VERSION_HEADERS)
if not (artifact_abs_path := await recorder.abs_path()):
return None
diff --git a/atr/tasks/checks/paths.py b/atr/tasks/checks/paths.py
index d127403f..9c33abf6 100644
--- a/atr/tasks/checks/paths.py
+++ b/atr/tasks/checks/paths.py
@@ -53,9 +53,11 @@ async def check(args: checks.FunctionArguments) -> results.Results | None:
# - Incubation Policy (IP)
# https://incubator.apache.org/policy/incubation.html
base_recorder = await args.recorder()
+ base_recorder.set_checker_version(CHECK_VERSION)
recorder_errors = await checks.Recorder.create(
checker=checks.function_key(check) + "_errors",
+ checker_version=CHECK_VERSION,
inputs_hash=base_recorder.input_hash or "",
project_key=args.project_key,
version_key=args.version_key,
@@ -65,6 +67,7 @@ async def check(args: checks.FunctionArguments) -> results.Results | None:
)
recorder_warnings = await checks.Recorder.create(
checker=checks.function_key(check) + "_warnings",
+ checker_version=CHECK_VERSION,
inputs_hash=base_recorder.input_hash or "",
project_key=args.project_key,
version_key=args.version_key,
@@ -74,6 +77,7 @@ async def check(args: checks.FunctionArguments) -> results.Results | None:
)
recorder_success = await checks.Recorder.create(
checker=checks.function_key(check) + "_success",
+ checker_version=CHECK_VERSION,
inputs_hash=base_recorder.input_hash or "",
project_key=args.project_key,
version_key=args.version_key,
diff --git a/atr/tasks/checks/rat.py b/atr/tasks/checks/rat.py
index acb1d474..1ea8a6e0 100644
--- a/atr/tasks/checks/rat.py
+++ b/atr/tasks/checks/rat.py
@@ -78,6 +78,7 @@ class RatError(RuntimeError):
async def check(args: checks.FunctionArguments) -> results.Results | None:
"""Use Apache RAT to check the licenses of the files in the artifact."""
recorder = await args.recorder()
+ recorder.set_checker_version(CHECK_VERSION)
if not (artifact_abs_path := await recorder.abs_path()):
return None
if await recorder.primary_path_is_binary():
diff --git a/atr/tasks/checks/signature.py b/atr/tasks/checks/signature.py
index 050f5ae5..92af5b2a 100644
--- a/atr/tasks/checks/signature.py
+++ b/atr/tasks/checks/signature.py
@@ -39,6 +39,7 @@ CHECK_VERSION: Final[str] = "1"
async def check(args: checks.FunctionArguments) -> results.Results | None:
"""Check a signature file."""
recorder = await args.recorder()
+ recorder.set_checker_version(CHECK_VERSION)
if not (primary_abs_path := await recorder.abs_path()):
return None
diff --git a/atr/tasks/checks/targz.py b/atr/tasks/checks/targz.py
index dee2988d..61824592 100644
--- a/atr/tasks/checks/targz.py
+++ b/atr/tasks/checks/targz.py
@@ -76,6 +76,7 @@ def root_directory(archive_dir: pathlib.Path) -> tuple[str, bytes | None]:
async def structure(args: checks.FunctionArguments) -> results.Results | None: # noqa: C901
"""Check the structure of a .tar.gz file using the extracted tree."""
recorder = await args.recorder()
+ recorder.set_checker_version(CHECK_VERSION_STRUCTURE)
if not (artifact_abs_path := await recorder.abs_path()):
return None
if await recorder.primary_path_is_binary():
diff --git a/atr/tasks/checks/zipformat.py b/atr/tasks/checks/zipformat.py
index defe2dbc..fe029e27 100644
--- a/atr/tasks/checks/zipformat.py
+++ b/atr/tasks/checks/zipformat.py
@@ -39,6 +39,7 @@ async def structure(args: checks.FunctionArguments) -> results.Results | None:
# For simplicity, they've been updated separately for now
# (There are several small differences to resolve between the two)
recorder = await args.recorder()
+ recorder.set_checker_version(CHECK_VERSION_STRUCTURE)
if not (artifact_abs_path := await recorder.abs_path()):
return None
if await recorder.primary_path_is_binary():
diff --git a/migrations/versions/0061_2026.03.18_7838cfcc.py b/migrations/versions/0061_2026.03.18_7838cfcc.py
new file mode 100644
index 00000000..e05c5ff9
--- /dev/null
+++ b/migrations/versions/0061_2026.03.18_7838cfcc.py
@@ -0,0 +1,27 @@
+"""check version into database
+
+Revision ID: 0061_2026.03.18_7838cfcc
+Revises: 0060_2026.03.16_2c8e4716
+Create Date: 2026-03-18 13:51:12.776504+00:00
+"""
+
+from collections.abc import Sequence
+
+import sqlalchemy as sa
+from alembic import op
+
+# Revision identifiers, used by Alembic
+revision: str = "0061_2026.03.18_7838cfcc"
+down_revision: str | None = "0060_2026.03.16_2c8e4716"
+branch_labels: str | Sequence[str] | None = None
+depends_on: str | Sequence[str] | None = None
+
+
+def upgrade() -> None:
+ with op.batch_alter_table("checkresult", schema=None) as batch_op:
+ batch_op.add_column(sa.Column("checker_version", sa.String(), nullable=True))
+
+
+def downgrade() -> None:
+ with op.batch_alter_table("checkresult", schema=None) as batch_op:
+ batch_op.drop_column("checker_version")
diff --git a/tests/unit/recorders.py b/tests/unit/recorders.py
index 96b5c09b..2dcb67be 100644
--- a/tests/unit/recorders.py
+++ b/tests/unit/recorders.py
@@ -20,18 +20,20 @@ import pathlib
from collections.abc import Awaitable, Callable
from typing import Any
+import atr.models.safe as safe
import atr.models.sql as sql
import atr.tasks.checks as checks
class RecorderStub(checks.Recorder):
- def __init__(self, path: pathlib.Path, checker: str) -> None:
+ def __init__(self, path: pathlib.Path, checker: str, checker_version: str | None = None) -> None:
super().__init__(
checker=checker,
+ checker_version=checker_version,
inputs_hash=None,
- project_key="test",
- version_key="test",
- revision_number="00001",
+ project_key=safe.ProjectKey("test"),
+ version_key=safe.VersionKey("test"),
+ revision_number=safe.RevisionNumber("00001"),
primary_rel_path=None,
member_rel_path=None,
afresh=False,
@@ -59,6 +61,7 @@ class RecorderStub(checks.Recorder):
release_key=self.release_key,
revision_number=self.revision_number,
checker=self.checker,
+ checker_version=self.checker_version,
primary_rel_path=primary_rel_path,
member_rel_path=member_rel_path,
created=datetime.datetime.now(datetime.UTC),
diff --git a/tests/unit/test_checks_compare.py b/tests/unit/test_checks_compare.py
index 229f3928..f87984b8 100644
--- a/tests/unit/test_checks_compare.py
+++ b/tests/unit/test_checks_compare.py
@@ -27,6 +27,7 @@ import dulwich.refs
import pytest
import atr.models.github
+import atr.models.safe
import atr.models.sql
import atr.tasks.checks
import atr.tasks.checks.compare
@@ -201,10 +202,11 @@ class RecorderStub(atr.tasks.checks.Recorder):
def __init__(self, is_source: bool) -> None:
super().__init__(
checker="compare.source_trees",
+ checker_version="1",
inputs_hash=None,
- project_key="project",
- version_key="version",
- revision_number="00001",
+ project_key=atr.models.safe.ProjectKey("project"),
+ version_key=atr.models.safe.VersionKey("version"),
+ revision_number=atr.models.safe.RevisionNumber("00001"),
primary_rel_path="artifact.tar.gz",
member_rel_path=None,
afresh=False,
@@ -224,6 +226,7 @@ class RecorderStub(atr.tasks.checks.Recorder):
release_key=self.release_key,
revision_number=self.revision_number,
checker=self.checker,
+ checker_version=self.checker_version,
primary_rel_path=primary_rel_path or self.primary_rel_path,
member_rel_path=member_rel_path,
created=datetime.datetime.now(datetime.UTC),
@@ -241,6 +244,7 @@ class RecorderStub(atr.tasks.checks.Recorder):
release_key=None,
revision_number=None,
checker=self.checker,
+ checker_version=self.checker_version,
primary_rel_path=primary_rel_path or self.primary_rel_path,
member_rel_path=member_rel_path,
created=datetime.datetime.now(datetime.UTC),
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org