Publish curated Unraid-AppOps-Gateway source from ba66029223865607deddc234e283c11127324eb8
This commit is contained in:
1 parent
820244dbb3
commit
8dd4b40252
52 files changed
+11814
-288
No files matched your search
@@ -4,6 +4,7 @@ import hashlib
|
||||
import importlib
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import types
|
||||
@@ -64,6 +65,8 @@ def harness(modules, tmp_path, monkeypatch):
|
||||
state = types.SimpleNamespace(
|
||||
source=tmp_path / "releases" / revision,
|
||||
compose_marker="baseline",
|
||||
clock=now,
|
||||
ingestion_digest=None,
|
||||
images={},
|
||||
mutations=[],
|
||||
inspect_calls=[],
|
||||
@@ -119,9 +122,13 @@ def harness(modules, tmp_path, monkeypatch):
|
||||
"validate_commit",
|
||||
lambda _repo, branch, commit: commit if branch == "main" else "",
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
controller, "deployment_metadata", lambda *_args, **_kwargs: dict(metadata)
|
||||
)
|
||||
def deployment_metadata(_repo, _revision, _repository, *, built_at=None):
|
||||
result = dict(metadata)
|
||||
result["builtAt"] = built_at or state.clock
|
||||
datetime.fromisoformat(result["builtAt"].replace("Z", "+00:00"))
|
||||
return result
|
||||
|
||||
monkeypatch.setattr(controller, "deployment_metadata", deployment_metadata)
|
||||
monkeypatch.setattr(controller, "mcp_hub_source_date_epoch", lambda *_args: epoch)
|
||||
|
||||
def stage(_project, _repo, commit):
|
||||
@@ -144,11 +151,18 @@ def harness(modules, tmp_path, monkeypatch):
|
||||
for index, service in enumerate(controller.MCP_HUB_SERVICES, 1):
|
||||
if service in controller.MCP_HUB_OWNED_IMAGE_REPOSITORIES:
|
||||
local = controller.MCP_HUB_LOCAL_BUILD_IMAGE_REPOSITORIES.get(service)
|
||||
reference = (
|
||||
f"{local}:{revision[:12]}"
|
||||
if local
|
||||
else f"{controller.MCP_HUB_OWNED_IMAGE_REPOSITORIES[service]}@sha256:{index:064x}"
|
||||
)
|
||||
if service == "connector-ingestion":
|
||||
reference = (
|
||||
f"{controller.MCP_HUB_OWNED_IMAGE_REPOSITORIES[service]}@sha256:{state.ingestion_digest}"
|
||||
if state.ingestion_digest
|
||||
else ""
|
||||
)
|
||||
else:
|
||||
reference = (
|
||||
f"{local}:{revision[:12]}"
|
||||
if local
|
||||
else f"{controller.MCP_HUB_OWNED_IMAGE_REPOSITORIES[service]}@sha256:{index:064x}"
|
||||
)
|
||||
elif service == "contextforge":
|
||||
reference = f"itworx-mcp-hub/contextforge-schema:{revision}"
|
||||
elif service == "ingestion-clamd":
|
||||
@@ -174,6 +188,13 @@ def harness(modules, tmp_path, monkeypatch):
|
||||
)
|
||||
monkeypatch.setattr(utility, "_is_host_root", lambda: True)
|
||||
|
||||
utility.freeze_candidate(controller.MCP_HUB_REPOSITORY, revision)
|
||||
freeze_dir = tmp_path / "mcp-hub-source-freezes" / revision
|
||||
freeze_doc = json.loads((freeze_dir / "freeze.json").read_text())
|
||||
# Publication happens after freeze and advances the wall clock. The plan
|
||||
# uses the immutable timestamp and the now-available registry digest.
|
||||
state.clock = "2026-10-04T02:03:04.567Z"
|
||||
state.ingestion_digest = "f" * 64
|
||||
plan = utility.plan_candidate(controller.MCP_HUB_REPOSITORY, revision)
|
||||
candidate_dir = tmp_path / "mcp-hub-release-candidates" / revision
|
||||
plan_doc = json.loads((candidate_dir / "build.json").read_text())
|
||||
@@ -255,6 +276,8 @@ def harness(modules, tmp_path, monkeypatch):
|
||||
now=now,
|
||||
plan=plan,
|
||||
plan_doc=plan_doc,
|
||||
freeze_dir=freeze_dir,
|
||||
freeze_doc=freeze_doc,
|
||||
)
|
||||
|
||||
|
||||
@@ -265,13 +288,225 @@ def test_plan_freezes_protected_metadata_without_candidate_or_approval(harness):
|
||||
assert document["repository"] == h.controller.MCP_HUB_REPOSITORY
|
||||
assert document["revision"] == h.revision
|
||||
assert document["build"] == h.metadata
|
||||
assert document["build"]["builtAt"] == h.freeze_doc["build"]["builtAt"]
|
||||
assert document["build"]["builtAt"] != h.state.clock
|
||||
assert document["sourceDateEpoch"] == h.epoch
|
||||
assert len(document["composeSha256"]) == 64
|
||||
assert h.state.ingestion_digest in str(h.model)
|
||||
assert not (h.candidate_dir / "candidate.json").exists()
|
||||
assert not (h.candidate_dir / "approval.json").exists()
|
||||
assert h.state.mutations == []
|
||||
|
||||
|
||||
def _remove_candidate_and_freeze(h):
|
||||
shutil.rmtree(h.candidate_dir, ignore_errors=True)
|
||||
shutil.rmtree(h.freeze_dir.parent, ignore_errors=True)
|
||||
|
||||
|
||||
def _prepare_freeze_dir(h):
|
||||
h.freeze_dir.parent.mkdir(mode=0o700)
|
||||
h.freeze_dir.mkdir(mode=0o700)
|
||||
|
||||
|
||||
def test_plan_requires_existing_freeze_before_any_candidate_write(harness):
|
||||
h = harness
|
||||
_remove_candidate_and_freeze(h)
|
||||
with pytest.raises(
|
||||
h.controller.DeployError,
|
||||
match="run freeze, publish the fixed ingestion image, then run plan",
|
||||
):
|
||||
h.utility.plan_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.candidate_dir.exists()
|
||||
|
||||
|
||||
def test_freeze_is_non_replayable(harness):
|
||||
h = harness
|
||||
original = (h.freeze_dir / "freeze.json").read_bytes()
|
||||
with pytest.raises(h.controller.DeployError, match="never overwritten|already exists"):
|
||||
h.utility.freeze_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert (h.freeze_dir / "freeze.json").read_bytes() == original
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("mutation", "message"),
|
||||
[
|
||||
("revision", "freeze record.*source identity"),
|
||||
("tree", "freeze record.*source identity"),
|
||||
("calendar", "freeze record.*source identity"),
|
||||
("epoch", "freeze record.*source epoch"),
|
||||
("duplicate", "unavailable or invalid|duplicate"),
|
||||
("partial", "unavailable or invalid|partial"),
|
||||
],
|
||||
)
|
||||
def test_plan_rejects_invalid_freeze_records_without_candidate_writes(
|
||||
harness, mutation, message
|
||||
):
|
||||
h = harness
|
||||
_remove_candidate_and_freeze(h)
|
||||
_prepare_freeze_dir(h)
|
||||
record = dict(h.freeze_doc)
|
||||
if mutation == "revision":
|
||||
record["revision"] = "c" * 40
|
||||
payload = json.dumps(record).encode()
|
||||
elif mutation == "tree":
|
||||
record["build"] = dict(record["build"])
|
||||
record["build"]["tree"] = "d" * 40
|
||||
payload = json.dumps(record).encode()
|
||||
elif mutation == "calendar":
|
||||
record["build"] = dict(record["build"])
|
||||
record["build"]["builtAt"] = "2026-99-99T00:00:00.000Z"
|
||||
payload = json.dumps(record).encode()
|
||||
elif mutation == "epoch":
|
||||
record["sourceDateEpoch"] = "1790888864"
|
||||
payload = json.dumps(record).encode()
|
||||
elif mutation == "duplicate":
|
||||
payload = b'{"schema":"duplicate","schema":"duplicate"}'
|
||||
else:
|
||||
payload = b'{"schema":'
|
||||
(h.freeze_dir / "freeze.json").write_bytes(payload)
|
||||
(h.freeze_dir / "freeze.json").chmod(0o600)
|
||||
with pytest.raises(h.controller.DeployError, match=message):
|
||||
h.utility.plan_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.candidate_dir.exists()
|
||||
|
||||
|
||||
def test_plan_rejects_symlink_freeze_file_without_candidate_writes(harness, tmp_path):
|
||||
h = harness
|
||||
_remove_candidate_and_freeze(h)
|
||||
_prepare_freeze_dir(h)
|
||||
outside = tmp_path / "outside.json"
|
||||
outside.write_text(json.dumps(h.freeze_doc))
|
||||
try:
|
||||
(h.freeze_dir / "freeze.json").symlink_to(outside)
|
||||
except OSError:
|
||||
pytest.skip("symlink creation is unavailable on this filesystem")
|
||||
with pytest.raises(
|
||||
h.controller.DeployError,
|
||||
match="unavailable or invalid|unsafe|not a regular file",
|
||||
):
|
||||
h.utility.plan_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.candidate_dir.exists()
|
||||
|
||||
|
||||
def test_plan_rejects_fifo_freeze_record_without_blocking(harness):
|
||||
if os.name == "nt" or not hasattr(os, "mkfifo"):
|
||||
pytest.skip("FIFO files are a POSIX filesystem contract")
|
||||
h = harness
|
||||
_remove_candidate_and_freeze(h)
|
||||
_prepare_freeze_dir(h)
|
||||
os.mkfifo(h.freeze_dir / "freeze.json", 0o600)
|
||||
with pytest.raises(h.controller.DeployError, match="not a regular file"):
|
||||
h.utility.plan_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.candidate_dir.exists()
|
||||
|
||||
|
||||
def test_plan_rejects_unsafe_freeze_directory_mode_without_candidate_writes(harness):
|
||||
h = harness
|
||||
if os.name == "nt":
|
||||
pytest.skip("POSIX private-mode enforcement is a Linux controller contract")
|
||||
_remove_candidate_and_freeze(h)
|
||||
_prepare_freeze_dir(h)
|
||||
(h.freeze_dir / "freeze.json").write_text(json.dumps(h.freeze_doc))
|
||||
(h.freeze_dir / "freeze.json").chmod(0o600)
|
||||
h.freeze_dir.chmod(0o755)
|
||||
with pytest.raises(h.controller.DeployError, match="private|root-owned|ACL"):
|
||||
h.utility.plan_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.candidate_dir.exists()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fault", ["file_mode", "owner", "dir_owner", "acl", "dir_acl"]
|
||||
)
|
||||
def test_plan_rejects_unsafe_freeze_file_metadata_without_candidate_writes(
|
||||
harness, monkeypatch, fault
|
||||
):
|
||||
h = harness
|
||||
if fault == "file_mode" and os.name == "nt":
|
||||
pytest.skip("POSIX private-mode enforcement is a Linux controller contract")
|
||||
_remove_candidate_and_freeze(h)
|
||||
_prepare_freeze_dir(h)
|
||||
freeze_file = h.freeze_dir / "freeze.json"
|
||||
freeze_file.write_text(json.dumps(h.freeze_doc))
|
||||
freeze_file.chmod(0o600)
|
||||
if fault == "file_mode":
|
||||
freeze_file.chmod(0o644)
|
||||
match = "unsafe"
|
||||
elif fault in {"owner", "dir_owner"}:
|
||||
original = h.controller._root_owned
|
||||
denied_path = h.freeze_dir if fault == "dir_owner" else freeze_file
|
||||
monkeypatch.setattr(
|
||||
h.controller,
|
||||
"_root_owned",
|
||||
lambda path: False if Path(path) == denied_path else original(path),
|
||||
)
|
||||
match = "root-owned|unsafe|owner"
|
||||
else:
|
||||
original = h.controller._mcp_hub_require_no_posix_acl
|
||||
|
||||
def reject_freeze_acl(path):
|
||||
if Path(path) == (h.freeze_dir if fault == "dir_acl" else freeze_file):
|
||||
raise h.controller.DeployError("freeze ACL denied")
|
||||
original(path)
|
||||
|
||||
monkeypatch.setattr(h.controller, "_mcp_hub_require_no_posix_acl", reject_freeze_acl)
|
||||
match = "ACL"
|
||||
with pytest.raises(h.controller.DeployError, match=match):
|
||||
h.utility.plan_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.candidate_dir.exists()
|
||||
|
||||
|
||||
def test_freeze_rejects_nonexact_local_main_head_without_writes(harness, monkeypatch):
|
||||
h = harness
|
||||
_remove_candidate_and_freeze(h)
|
||||
monkeypatch.setattr(h.controller, "output", lambda _args: "c" * 40)
|
||||
with pytest.raises(h.controller.DeployError, match="exact protected main head"):
|
||||
h.utility.freeze_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.freeze_dir.parent.exists()
|
||||
|
||||
|
||||
def test_freeze_rejects_staged_source_mismatch_without_freeze_record(harness, monkeypatch):
|
||||
h = harness
|
||||
_remove_candidate_and_freeze(h)
|
||||
monkeypatch.setattr(h.controller, "exact_source_matches_revision", lambda *_args: False)
|
||||
with pytest.raises(h.controller.DeployError, match="Staged MCP Hub source differs"):
|
||||
h.utility.freeze_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.freeze_dir.parent.exists()
|
||||
|
||||
|
||||
def test_freeze_rejects_invalid_epoch_before_staging_or_freeze_record(harness, monkeypatch):
|
||||
h = harness
|
||||
_remove_candidate_and_freeze(h)
|
||||
monkeypatch.setattr(h.controller, "mcp_hub_source_date_epoch", lambda *_args: "invalid")
|
||||
monkeypatch.setattr(
|
||||
h.controller,
|
||||
"mcp_hub_stage_release_source",
|
||||
lambda *_args: pytest.fail("invalid epoch must fail before source staging"),
|
||||
)
|
||||
with pytest.raises(h.controller.DeployError, match="source epoch"):
|
||||
h.utility.freeze_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.freeze_dir.parent.exists()
|
||||
|
||||
|
||||
def test_plan_rejects_staged_source_drift_before_candidate_writes(harness, monkeypatch):
|
||||
h = harness
|
||||
shutil.rmtree(h.candidate_dir)
|
||||
monkeypatch.setattr(h.controller, "exact_source_matches_revision", lambda *_args: False)
|
||||
with pytest.raises(h.controller.DeployError, match="Staged MCP Hub source differs"):
|
||||
h.utility.plan_candidate(h.controller.MCP_HUB_REPOSITORY, h.revision)
|
||||
assert not h.candidate_dir.exists()
|
||||
|
||||
|
||||
def test_freeze_wrong_repository_and_nonroot_fail_before_writes(modules, monkeypatch, tmp_path):
|
||||
controller, utility = modules
|
||||
monkeypatch.setattr(utility, "_is_host_root", lambda: True)
|
||||
monkeypatch.setattr(controller, "STATE_ROOT", tmp_path)
|
||||
with pytest.raises(controller.DeployError, match="fixed MCP Hub repository"):
|
||||
utility.freeze_candidate("someone/else", "a" * 40)
|
||||
assert list(tmp_path.iterdir()) == []
|
||||
monkeypatch.setattr(utility, "_is_host_root", lambda: False)
|
||||
with pytest.raises(controller.DeployError, match="host root"):
|
||||
utility.freeze_candidate(controller.MCP_HUB_REPOSITORY, "a" * 40)
|
||||
assert list(tmp_path.iterdir()) == []
|
||||
def test_plan_candidate_freezes_the_selected_workflow_creation_timestamp(
|
||||
harness, monkeypatch
|
||||
):
|
||||
@@ -334,7 +569,7 @@ def test_plan_candidate_freezes_the_selected_workflow_creation_timestamp(
|
||||
plan = json.loads(
|
||||
(staging / "build.json").read_text()
|
||||
)
|
||||
assert observed == [built_at]
|
||||
assert observed == [built_at, built_at]
|
||||
assert plan["build"]["builtAt"] == built_at
|
||||
assert len(compose_calls) == 1
|
||||
|
||||
@@ -349,6 +584,7 @@ def test_candidate_preparation_rejects_staging_path_outside_private_import_ancho
|
||||
h.utility.plan_candidate(
|
||||
h.controller.MCP_HUB_REPOSITORY,
|
||||
revision,
|
||||
built_at="2026-10-03T12:34:56.789Z",
|
||||
staging_directory=staging,
|
||||
)
|
||||
assert not staging.exists()
|
||||
@@ -363,16 +599,22 @@ def test_candidate_preparation_rejects_symlinked_staging_destination(harness):
|
||||
target = h.controller.STATE_ROOT / "untrusted-target"
|
||||
target.mkdir(mode=0o700)
|
||||
staging = token / revision
|
||||
staging.symlink_to(target, target_is_directory=True)
|
||||
try:
|
||||
staging.symlink_to(target, target_is_directory=True)
|
||||
except OSError:
|
||||
pytest.skip("symlink creation is unavailable on this filesystem")
|
||||
with pytest.raises(h.controller.DeployError):
|
||||
h.utility.plan_candidate(
|
||||
h.controller.MCP_HUB_REPOSITORY,
|
||||
revision,
|
||||
built_at="2026-10-03T12:34:56.789Z",
|
||||
staging_directory=staging,
|
||||
)
|
||||
|
||||
|
||||
def test_candidate_preparation_rejects_nonprivate_staging_parent(harness):
|
||||
if os.name == "nt":
|
||||
pytest.skip("POSIX private-mode enforcement is a Linux controller contract")
|
||||
h = harness
|
||||
revision = h.revision
|
||||
anchor = h.controller.STATE_ROOT / "mcp-hub-release-imports" / revision
|
||||
@@ -384,6 +626,7 @@ def test_candidate_preparation_rejects_nonprivate_staging_parent(harness):
|
||||
h.utility.plan_candidate(
|
||||
h.controller.MCP_HUB_REPOSITORY,
|
||||
revision,
|
||||
built_at="2026-10-03T12:34:56.789Z",
|
||||
staging_directory=staging,
|
||||
)
|
||||
|
||||
@@ -447,6 +690,10 @@ def test_capture_emits_candidate_and_pending_only_envelope_without_apply_calls(
|
||||
digests = json.loads((h.candidate_dir / "image-digests.json").read_text())
|
||||
assert result["status"] == "pending_review"
|
||||
assert set(candidate["images"]) == set(h.controller.MCP_HUB_SERVICES)
|
||||
assert candidate["images"]["connector-ingestion"]["imageRef"].endswith(
|
||||
"@sha256:" + h.state.ingestion_digest
|
||||
)
|
||||
assert candidate["build"]["builtAt"] == h.freeze_doc["build"]["builtAt"]
|
||||
assert digests["images"]["web"]["tag"] == candidate["images"]["web"]["imageRef"]
|
||||
assert digests["images"]["web"]["imageId"] == candidate["images"]["web"]["imageId"]
|
||||
candidate_bytes = (h.candidate_dir / "candidate.json").read_bytes()
|
||||
|
||||
Reference in new issue
Block a user