feat(release): build verified full-registry catalog candidates
This commit is contained in:
@@ -19,10 +19,33 @@ from .git_state import (
|
||||
scoped_git_command,
|
||||
)
|
||||
from .repository_tag import RemoteTagResult, ref_commit, remote_tag_commit
|
||||
from .registry_reference import registry_entry_source
|
||||
from .version_alignment import repository_version_issues
|
||||
from .workspace import load_repository_specs, resolve_repo_path
|
||||
|
||||
|
||||
def registered_source_origin_issues(
|
||||
*, repo_versions: dict[str, str], workspace: Path, remote: str,
|
||||
) -> tuple[SourceTagProvenanceIssue, ...]:
|
||||
"""Bind registry candidate attestations to registered source endpoints."""
|
||||
specs = {spec.name: spec for spec in load_repository_specs(include_website=False)}
|
||||
issues = []
|
||||
for repo, version in sorted(repo_versions.items()):
|
||||
spec = specs.get(repo)
|
||||
if spec is None:
|
||||
issues.append(SourceTagProvenanceIssue(repo, f"v{version}", "source repository is not registered"))
|
||||
continue
|
||||
path = resolve_repo_path(spec, workspace)
|
||||
if path.absolute() != path.resolve() or not path.resolve().is_relative_to(workspace.resolve()):
|
||||
issues.append(SourceTagProvenanceIssue(repo, f"v{version}", "source checkout leaves the private workspace or traverses a symlink"))
|
||||
continue
|
||||
fetch = git_text(path, "remote", "get-url", "--all", remote).splitlines()
|
||||
push = git_text(path, "remote", "get-url", "--push", "--all", remote).splitlines()
|
||||
if fetch != [spec.remote] or push != [spec.remote]:
|
||||
issues.append(SourceTagProvenanceIssue(repo, f"v{version}", "source remote does not exactly match the registered origin"))
|
||||
return tuple(issues)
|
||||
|
||||
|
||||
_CATALOG_PYTHON_REF = re.compile(
|
||||
r"/(?P<repo>govoplan-[a-z0-9-]+)\.git@v(?P<version>[^\s;]+)$"
|
||||
)
|
||||
@@ -61,6 +84,8 @@ def catalog_source_selection(payload: object) -> CatalogSourceSelection:
|
||||
)
|
||||
|
||||
versions: dict[str, str] = {}
|
||||
registry_commits: dict[str, str] = {}
|
||||
registry_tag_objects: dict[str, str] = {}
|
||||
issues: list[SourceTagProvenanceIssue] = []
|
||||
entries: list[tuple[str, object]] = [("core_release", payload.get("core_release"))]
|
||||
modules = payload.get("modules")
|
||||
@@ -70,6 +95,21 @@ def catalog_source_selection(payload: object) -> CatalogSourceSelection:
|
||||
for source, raw_entry in entries:
|
||||
if not isinstance(raw_entry, dict):
|
||||
continue
|
||||
try:
|
||||
registry_source = registry_entry_source(raw_entry)
|
||||
except ValueError as exc:
|
||||
issues.append(SourceTagProvenanceIssue(source, "", str(exc)))
|
||||
continue
|
||||
if registry_source is not None:
|
||||
repo, version = registry_source.repository, registry_source.version
|
||||
previous = versions.setdefault(repo, version)
|
||||
previous_commit = registry_commits.setdefault(repo, registry_source.commit)
|
||||
previous_object = registry_tag_objects.setdefault(repo, registry_source.tag_object)
|
||||
if (previous, previous_commit, previous_object) != (
|
||||
version, registry_source.commit, registry_source.tag_object,
|
||||
):
|
||||
issues.append(SourceTagProvenanceIssue(repo, f"v{version}", "registry entries have conflicting immutable source identities"))
|
||||
continue
|
||||
python_ref = raw_entry.get("python_ref")
|
||||
match = _CATALOG_PYTHON_REF.search(python_ref) if isinstance(python_ref, str) else None
|
||||
if match is None:
|
||||
@@ -89,8 +129,8 @@ def catalog_source_selection(payload: object) -> CatalogSourceSelection:
|
||||
release = payload.get("release")
|
||||
selected_units = release.get("selected_units") if isinstance(release, dict) else None
|
||||
selected: dict[str, str] = {}
|
||||
selected_commits: dict[str, str] = {}
|
||||
selected_tag_objects: dict[str, str] = {}
|
||||
selected_commits: dict[str, str] = dict(registry_commits)
|
||||
selected_tag_objects: dict[str, str] = dict(registry_tag_objects)
|
||||
if not isinstance(selected_units, list) or not selected_units:
|
||||
issues.append(
|
||||
SourceTagProvenanceIssue(
|
||||
@@ -106,16 +146,22 @@ def catalog_source_selection(payload: object) -> CatalogSourceSelection:
|
||||
repo = unit.get("repo")
|
||||
version = unit.get("version")
|
||||
if isinstance(repo, str) and isinstance(version, str):
|
||||
if repo in selected:
|
||||
issues.append(SourceTagProvenanceIssue(repo, f"v{version}", "duplicate selected repository"))
|
||||
selected[repo] = version.removeprefix("v")
|
||||
commit = unit.get("commit_sha")
|
||||
tag_object = unit.get("tag_object_sha")
|
||||
if isinstance(commit, str) and re.fullmatch(r"[0-9a-fA-F]{40}|[0-9a-fA-F]{64}", commit):
|
||||
if repo in registry_commits and registry_commits[repo] != commit.lower():
|
||||
issues.append(SourceTagProvenanceIssue(repo, f"v{version}", "selected commit differs from registry artifact source"))
|
||||
selected_commits[repo] = commit.lower()
|
||||
else:
|
||||
issues.append(
|
||||
SourceTagProvenanceIssue(repo, f"v{version.removeprefix('v')}", "selected unit has no valid commit_sha provenance")
|
||||
)
|
||||
if isinstance(tag_object, str) and re.fullmatch(r"[0-9a-fA-F]{40}|[0-9a-fA-F]{64}", tag_object):
|
||||
if repo in registry_tag_objects and registry_tag_objects[repo] != tag_object.lower():
|
||||
issues.append(SourceTagProvenanceIssue(repo, f"v{version}", "selected tag object differs from registry artifact source"))
|
||||
selected_tag_objects[repo] = tag_object.lower()
|
||||
else:
|
||||
issues.append(
|
||||
|
||||
Reference in New Issue
Block a user