fix: verify fetched source revisions from lock
Some checks failed
Build and publish policy-nexus image / build-and-push (push) Failing after 54s
Some checks failed
Build and publish policy-nexus image / build-and-push (push) Failing after 54s
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663
This commit is contained in:
parent
641eda8a37
commit
a0e4964b46
4 changed files with 74 additions and 4 deletions
|
|
@ -87,7 +87,6 @@ jobs:
|
||||||
--policy-revision "${REF}" \
|
--policy-revision "${REF}" \
|
||||||
--token-env FORGEJO_SOURCE_TOKEN \
|
--token-env FORGEJO_SOURCE_TOKEN \
|
||||||
--token-origin "${FORGEJO_ORIGIN}"
|
--token-origin "${FORGEJO_ORIGIN}"
|
||||||
NETKINGDOM_REVISION="$(docker exec "${PYTHON_CONTAINER}" python3 -c 'import json; print(json.load(open("/workspace/_sources/source-lock.json"))["repositories"]["net-kingdom"]["revision"])')"
|
|
||||||
SOURCE_SET_DIGEST="$(docker exec "${PYTHON_CONTAINER}" python3 -c 'import json; print(json.load(open("/workspace/_sources/source-lock.json"))["source_set_digest"])')"
|
SOURCE_SET_DIGEST="$(docker exec "${PYTHON_CONTAINER}" python3 -c 'import json; print(json.load(open("/workspace/_sources/source-lock.json"))["source_set_digest"])')"
|
||||||
docker cp "${PYTHON_CONTAINER}:/workspace/_sources" "${BUILD_CONTEXT}/"
|
docker cp "${PYTHON_CONTAINER}:/workspace/_sources" "${BUILD_CONTEXT}/"
|
||||||
docker rm -f "${PYTHON_CONTAINER}"
|
docker rm -f "${PYTHON_CONTAINER}"
|
||||||
|
|
@ -102,7 +101,6 @@ jobs:
|
||||||
docker build \
|
docker build \
|
||||||
--file "${BUILD_CONTEXT}/Containerfile" \
|
--file "${BUILD_CONTEXT}/Containerfile" \
|
||||||
--build-arg "VCS_REVISION=${REF}" \
|
--build-arg "VCS_REVISION=${REF}" \
|
||||||
--build-arg "NETKINGDOM_REVISION=${NETKINGDOM_REVISION}" \
|
|
||||||
--build-arg "SOURCE_SET_DIGEST=${SOURCE_SET_DIGEST}" \
|
--build-arg "SOURCE_SET_DIGEST=${SOURCE_SET_DIGEST}" \
|
||||||
--tag "${IMAGE}:${SOURCE_TAG}" \
|
--tag "${IMAGE}:${SOURCE_TAG}" \
|
||||||
--tag "${IMAGE}:${REVISION_TAG}" \
|
--tag "${IMAGE}:${REVISION_TAG}" \
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,7 @@ FROM runtime-base AS local-artifact
|
||||||
COPY --chown=101:101 build/ /usr/share/nginx/html/
|
COPY --chown=101:101 build/ /usr/share/nginx/html/
|
||||||
|
|
||||||
FROM docker.io/library/python@sha256:d09d15e60962ca365d1cd544a48773bac9d33f2fb1b00f2aa0deec78ade7dc31 AS release-builder
|
FROM docker.io/library/python@sha256:d09d15e60962ca365d1cd544a48773bac9d33f2fb1b00f2aa0deec78ade7dc31 AS release-builder
|
||||||
ARG NETKINGDOM_REVISION
|
|
||||||
ARG SOURCE_SET_DIGEST
|
ARG SOURCE_SET_DIGEST
|
||||||
ENV POLICY_NEXUS_SOURCE_REVISION_NET_KINGDOM=$NETKINGDOM_REVISION
|
|
||||||
ENV POLICY_NEXUS_SOURCE_ROOT=/workspace/_sources
|
ENV POLICY_NEXUS_SOURCE_ROOT=/workspace/_sources
|
||||||
WORKDIR /workspace/policy-nexus
|
WORKDIR /workspace/policy-nexus
|
||||||
COPY . /workspace/policy-nexus
|
COPY . /workspace/policy-nexus
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,56 @@ class PublicationTest(unittest.TestCase):
|
||||||
with self.assertRaisesRegex(ValueError, "clean 40-hex Git commit"):
|
with self.assertRaisesRegex(ValueError, "clean 40-hex Git commit"):
|
||||||
build_site._source_revision(repo, source)
|
build_site._source_revision(repo, source)
|
||||||
|
|
||||||
|
def test_archive_build_uses_fetched_source_lock_revision(self) -> None:
|
||||||
|
with tempfile.TemporaryDirectory() as directory:
|
||||||
|
root = Path(directory)
|
||||||
|
repo = root / "the-custodian"
|
||||||
|
source = repo / "canon/example.md"
|
||||||
|
source.parent.mkdir(parents=True)
|
||||||
|
source.write_text("example", encoding="utf-8")
|
||||||
|
revision = "b" * 40
|
||||||
|
(root / "source-lock.json").write_text(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"repositories": {
|
||||||
|
"the-custodian": {"revision": revision}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
with mock.patch.dict(
|
||||||
|
os.environ, {"POLICY_NEXUS_SOURCE_ROOT": str(root)}, clear=False
|
||||||
|
):
|
||||||
|
self.assertEqual(revision, build_site._source_revision(repo, source))
|
||||||
|
|
||||||
|
def test_archive_build_rejects_invalid_fetched_source_lock_revision(self) -> None:
|
||||||
|
with tempfile.TemporaryDirectory() as directory:
|
||||||
|
root = Path(directory)
|
||||||
|
repo = root / "the-custodian"
|
||||||
|
source = repo / "canon/example.md"
|
||||||
|
source.parent.mkdir(parents=True)
|
||||||
|
source.write_text("example", encoding="utf-8")
|
||||||
|
(root / "source-lock.json").write_text(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"repositories": {
|
||||||
|
"the-custodian": {"revision": "sha256:" + "b" * 64}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
with mock.patch.dict(
|
||||||
|
os.environ, {"POLICY_NEXUS_SOURCE_ROOT": str(root)}, clear=False
|
||||||
|
):
|
||||||
|
with self.assertRaisesRegex(ValueError, "clean 40-hex Git commit"):
|
||||||
|
build_site._source_revision(repo, source)
|
||||||
|
|
||||||
def test_manifest_builds_index_current_revision_and_legacy_alias(self) -> None:
|
def test_manifest_builds_index_current_revision_and_legacy_alias(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as directory:
|
with tempfile.TemporaryDirectory() as directory:
|
||||||
root = Path(directory)
|
root = Path(directory)
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,30 @@ def _source_revision(repo: Path, source: Path) -> str:
|
||||||
f"{revision_env} must be a clean 40-hex Git commit, got {supplied_revision!r}"
|
f"{revision_env} must be a clean 40-hex Git commit, got {supplied_revision!r}"
|
||||||
)
|
)
|
||||||
return supplied_revision
|
return supplied_revision
|
||||||
|
source_root = os.environ.get("POLICY_NEXUS_SOURCE_ROOT", "")
|
||||||
|
if source_root:
|
||||||
|
root = Path(source_root).resolve()
|
||||||
|
try:
|
||||||
|
repo.relative_to(root)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
lock_path = root / "source-lock.json"
|
||||||
|
try:
|
||||||
|
lock = json.loads(lock_path.read_text(encoding="utf-8"))
|
||||||
|
locked_revision = lock["repositories"][repo.name]["revision"]
|
||||||
|
except (KeyError, OSError, TypeError, json.JSONDecodeError) as exc:
|
||||||
|
raise ValueError(
|
||||||
|
f"{repo.name}: source revision is missing from {lock_path}"
|
||||||
|
) from exc
|
||||||
|
if not isinstance(locked_revision, str) or not CLEAN_GIT_REVISION.fullmatch(
|
||||||
|
locked_revision
|
||||||
|
):
|
||||||
|
raise ValueError(
|
||||||
|
f"{repo.name}: locked source revision must be a clean 40-hex Git commit, "
|
||||||
|
f"got {locked_revision!r}"
|
||||||
|
)
|
||||||
|
return locked_revision
|
||||||
try:
|
try:
|
||||||
head = subprocess.run(
|
head = subprocess.run(
|
||||||
["git", "-C", str(repo), "rev-parse", "HEAD"],
|
["git", "-C", str(repo), "rev-parse", "HEAD"],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue