Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions .dagger/src/ci/fleet.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
from dataclasses import dataclass
from datetime import date

from ci.fleet_policy import PolicyFinding, RepositoryExpectation, validate_repository
from ci.github_fleet import GitHubHttpTransport, read_repository
from ci.fleet_coverage import coverage_results
from ci.fleet_policy import PolicyFinding, RepositoryExpectation, finding, validate_repository
from ci.github_fleet import FleetAccessError, GitHubHttpTransport, GitHubTransport, read_repository

OWNER = "hseshadr"


@dataclass(frozen=True)
Expand All @@ -21,6 +24,8 @@ class RepositoryResult:
def repository_expectations(include_central: bool) -> tuple[RepositoryExpectation, ...]:
"""Return the reviewed fleet contract for the current rollout phase."""
consumers = (
expectation("agentic-context-service"),
expectation("agentic-saga"),
expectation("almamesh", grandfathered_until=date(2026, 12, 15)),
expectation("aml-filter", grandfathered_until=date(2026, 12, 31)),
expectation("assay", linear_history=True, grandfathered_until=date(2026, 11, 30)),
Expand Down Expand Up @@ -57,15 +62,28 @@ def expectation_for(name: str) -> RepositoryExpectation:

def scan_fleet(token: str, include_central: bool) -> tuple[RepositoryResult, ...]:
"""Read and evaluate each repository from authoritative exact-main evidence."""
transport = GitHubHttpTransport(token)
return scan_fleet_with(GitHubHttpTransport(token), include_central)


def scan_fleet_with(
transport: GitHubTransport, include_central: bool
) -> tuple[RepositoryResult, ...]:
"""Prove coverage of every discovered consumer, then evaluate each reviewed one."""
reviewed = tuple(item.name for item in repository_expectations(True))
uncovered = coverage_results(transport, OWNER, reviewed)
coverage = tuple(RepositoryResult(item.name, "", item.findings) for item in uncovered)
expectations = repository_expectations(include_central)
return tuple(scan_repository(transport, item) for item in expectations)
return coverage + tuple(scan_repository(transport, item) for item in expectations)


def scan_repository(
transport: GitHubHttpTransport, expectation_: RepositoryExpectation
transport: GitHubTransport, expectation_: RepositoryExpectation
) -> RepositoryResult:
"""Evaluate one exact-main repository against its reviewed contract."""
snapshot = read_repository(transport, "hseshadr", expectation_.name)
"""Evaluate one repository, turning unreadable evidence into a failing finding."""
try:
snapshot = read_repository(transport, OWNER, expectation_.name)
except FleetAccessError as error:
unreadable = finding("evidence-unreadable", "github", str(error))
return RepositoryResult(expectation_.name, "", (unreadable,))
findings = validate_repository(snapshot, expectation_)
return RepositoryResult(snapshot.name, snapshot.sha, findings)
101 changes: 101 additions & 0 deletions .dagger/src/ci/fleet_coverage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""Discover every Dagger consumer of the central modules and prove fleet coverage.

The reviewed fleet contract (`repository_expectations`) is a hand-maintained list, so a
new consumer silently escapes every fleet check until someone remembers to add it. This
module closes that gap: it lists the owner's repositories, reads each default-branch
`dagger.json`, and fails the scan for any consumer the contract does not name.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Final

from pydantic.dataclasses import dataclass as validated_dataclass

from ci.fleet_policy import PolicyFinding, finding
from ci.github_fleet import (
BOUNDARY_CONFIG,
HTTP_NOT_FOUND,
GitHubTransport,
decode_source,
parse_content_response,
parse_dagger_config,
read_model,
)

UNCOVERED_CODE: Final = "uncovered-consumer"
CENTRAL_PREFIXES: Final = ("github.com/hseshadr/ci/", "github.com/hseshadr/ci@")
PAGE_SIZE: Final = 100


@validated_dataclass(config=BOUNDARY_CONFIG)
class OwnedRepositoryPayload:
"""One entry of the owner's public repository listing."""

name: str
archived: bool
default_branch: str


@dataclass(frozen=True)
class UncoveredConsumer:
"""One discovered consumer that the reviewed fleet contract does not name."""

name: str
findings: tuple[PolicyFinding, ...]


def discover_consumers(transport: GitHubTransport, owner: str) -> tuple[str, ...]:
"""Return every active repository whose default-branch dagger.json pins hseshadr/ci."""
return tuple(
repository.name
for repository in list_repositories(transport, owner)
if not repository.archived and consumes_central(transport, owner, repository)
)


def list_repositories(transport: GitHubTransport, owner: str) -> tuple[OwnedRepositoryPayload, ...]:
"""Read every page of the owner's repository listing, failing closed on any error."""
collected: list[OwnedRepositoryPayload] = []
page = 1
while True:
path = f"users/{owner}/repos?type=owner&per_page={PAGE_SIZE}&page={page}"
batch = read_model(transport, path, tuple[OwnedRepositoryPayload, ...])
collected.extend(batch)
if len(batch) < PAGE_SIZE:
return tuple(collected)
page += 1


def consumes_central(
transport: GitHubTransport, owner: str, repository: OwnedRepositoryPayload
) -> bool:
"""Return whether one default-branch dagger.json declares a central module."""
base = f"repos/{owner}/{repository.name}"
path = f"{base}/contents/dagger.json?ref={repository.default_branch}"
response = transport.get(path)
if response.status == HTTP_NOT_FOUND:
return False
source = decode_source(parse_content_response(response, path), "dagger.json", base)
config = parse_dagger_config(source)
return any(item.source.startswith(CENTRAL_PREFIXES) for item in config.dependencies)


def uncovered_consumers(discovered: tuple[str, ...], reviewed: tuple[str, ...]) -> tuple[str, ...]:
"""Return discovered consumers absent from the reviewed fleet contract."""
return tuple(name for name in discovered if name not in reviewed)


def coverage_results(
transport: GitHubTransport, owner: str, reviewed: tuple[str, ...]
) -> tuple[UncoveredConsumer, ...]:
"""Build one failing result per discovered consumer the fleet scan would skip."""
missing = uncovered_consumers(discover_consumers(transport, owner), reviewed)
return tuple(UncoveredConsumer(name, (uncovered_finding(name),)) for name in missing)


def uncovered_finding(name: str) -> PolicyFinding:
"""Name the exact fix for one consumer that escapes the fleet scan."""
message = f"{name} pins hseshadr/ci modules but is missing from repository_expectations"
return finding(UNCOVERED_CODE, "dagger.json", message)
Loading
Loading