From 79ef84f8f4f6c2cc56a0678c205259d2248a7d7d Mon Sep 17 00:00:00 2001 From: danielporterda Date: Fri, 7 Aug 2026 13:12:34 -0400 Subject: [PATCH] Resolve immutable snippet sources Signed-off-by: danielporterda --- scripts/snippets/resolution.py | 39 ++++++++++++++++ ...est_immutable_snippet_source_resolution.py | 46 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 scripts/snippets/resolution.py create mode 100644 tests/test_immutable_snippet_source_resolution.py diff --git a/scripts/snippets/resolution.py b/scripts/snippets/resolution.py new file mode 100644 index 000000000..050f9f299 --- /dev/null +++ b/scripts/snippets/resolution.py @@ -0,0 +1,39 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import Protocol + +from .model import ImmutableSourceReference + +DEFAULT_MAX_SOURCE_BYTES = 1024 * 1024 + + +class SourceResolutionError(Exception): + """A snippet source could not be resolved safely.""" + + +@dataclass(frozen=True) +class ResolvedSource: + reference: ImmutableSourceReference + commit: str + content: bytes + + +class GitHubFileClient(Protocol): + def read_file(self, repository: str, commit: str, path: str) -> bytes: ... + + +def resolve_immutable_source( + reference: ImmutableSourceReference, + github: GitHubFileClient, + *, + max_source_bytes: int = DEFAULT_MAX_SOURCE_BYTES, +) -> ResolvedSource: + """Read an immutable source at the exact commit declared by the page.""" + + content = github.read_file(reference.repository, reference.commit, reference.path) + if len(content) > max_source_bytes: + raise SourceResolutionError( + f"Source exceeds the {max_source_bytes}-byte size limit" + ) + return ResolvedSource(reference, reference.commit, content) diff --git a/tests/test_immutable_snippet_source_resolution.py b/tests/test_immutable_snippet_source_resolution.py new file mode 100644 index 000000000..95b00be68 --- /dev/null +++ b/tests/test_immutable_snippet_source_resolution.py @@ -0,0 +1,46 @@ +from __future__ import annotations + +import pytest + +from scripts.snippets.model import ImmutableSourceReference +from scripts.snippets.resolution import ( + SourceResolutionError, + resolve_immutable_source, +) + +COMMIT = "2c941ea9e834d7602d388f3271c0f864025ea756" + + +class FakeGitHub: + def __init__(self, content: bytes = b"hello\n") -> None: + self.content = content + self.calls: list[tuple[str, str, str]] = [] + + def read_file(self, repository: str, commit: str, path: str) -> bytes: + self.calls.append((repository, commit, path)) + return self.content + + +def reference() -> ImmutableSourceReference: + return ImmutableSourceReference( + repository="canton-network/splice", + commit=COMMIT, + path="apps/example.yaml", + ) + + +def test_reads_the_exact_declared_commit() -> None: + github = FakeGitHub() + + resolved = resolve_immutable_source(reference(), github) + + assert resolved.commit == COMMIT + assert resolved.content == b"hello\n" + assert github.calls == [ + ("canton-network/splice", COMMIT, "apps/example.yaml") + ] + + +def test_rejects_source_larger_than_the_configured_limit() -> None: + with pytest.raises(SourceResolutionError, match="4-byte size limit"): + resolve_immutable_source(reference(), FakeGitHub(b"12345"), max_source_bytes=4)