Publish curated Unraid-AppOps-Gateway source from a194da2defbd709ea58bd4c9503966dbd37b11f2

This commit is contained in:
Public Source Publisher committed 2026-10-14 17:11:07 +00:00
1 parent 2c5788da5d
commit c5224725b7
11 files changed
+626 -18

No files matched your search

+1 -1
View File
@@ -1,3 +1,3 @@
# Public source export # Public source export
This source snapshot was generated from the private canonical repository at revision `207d2a918641b199961d27de09b6c1fdf45a6e4b`. It contains no private Git history or operational evidence. Changes are published from the canonical repository. This source snapshot was generated from the private canonical repository at revision `a194da2defbd709ea58bd4c9503966dbd37b11f2`. It contains no private Git history or operational evidence. Changes are published from the canonical repository.
+28 -13
View File
@@ -1,6 +1,6 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"sourceRevision": "207d2a918641b199961d27de09b6c1fdf45a6e4b", "sourceRevision": "a194da2defbd709ea58bd4c9503966dbd37b11f2",
"files": [ "files": [
{ {
"path": ".dockerignore", "path": ".dockerignore",
@@ -294,8 +294,8 @@
}, },
{ {
"path": "backend/app/connectors/gitea_actions.py", "path": "backend/app/connectors/gitea_actions.py",
"sha256": "3c0be8c895079c007b9c04d2eaab152cc30d10ea8708b6d3914a86a3b1b35a65", "sha256": "4d3229e03b5878a67e8b3826a62ec073a54a7279426b986f7e6dff027a9caec4",
"bytes": 29286 "bytes": 29972
}, },
{ {
"path": "backend/app/connectors/gpu_metrics.py", "path": "backend/app/connectors/gpu_metrics.py",
@@ -877,6 +877,11 @@
"sha256": "1da47a3f061ef0b89158c9f646bb7018ce88b81c0687d8b27abe65b74df67fea", "sha256": "1da47a3f061ef0b89158c9f646bb7018ce88b81c0687d8b27abe65b74df67fea",
"bytes": 4948 "bytes": 4948
}, },
{
"path": "backend/tests/fixtures/hub_security_base_publication_23280.json",
"sha256": "74e5cff171b4fa5aeeec2a58ce71147546c3e217a69c224f2d9227b007294cd1",
"bytes": 3090
},
{ {
"path": "backend/tests/test_ai_remediation_planner.py", "path": "backend/tests/test_ai_remediation_planner.py",
"sha256": "784b83960cdff238e0ee25caaf83cfd1cb7c3cfc40976036b28bd256f6626e44", "sha256": "784b83960cdff238e0ee25caaf83cfd1cb7c3cfc40976036b28bd256f6626e44",
@@ -1024,8 +1029,8 @@
}, },
{ {
"path": "backend/tests/test_deploy_broker.py", "path": "backend/tests/test_deploy_broker.py",
"sha256": "5f7a8bd1724a81a5d7628f4b65e23687acb1a6af2ff5eb63e6d770d6e15914c0", "sha256": "a83b6d74fa51b208e38c9e5b9fc667c3150b342fc99265e2d538e8442a13f5b1",
"bytes": 442256 "bytes": 442377
}, },
{ {
"path": "backend/tests/test_deployment_auto_rollback.py", "path": "backend/tests/test_deployment_auto_rollback.py",
@@ -1204,8 +1209,8 @@
}, },
{ {
"path": "backend/tests/test_hub_candidate_import.py", "path": "backend/tests/test_hub_candidate_import.py",
"sha256": "87762293c6088b5e3e71adfa4c109ec468d7931f3e10b8be6e04ce1d19f8d849", "sha256": "9ae57b5a33652ca94bfdb4c69e65ec7dfe47650de4d6a39caa3026bfe8f3d354",
"bytes": 47846 "bytes": 52139
}, },
{ {
"path": "backend/tests/test_hub_candidate_transport.py", "path": "backend/tests/test_hub_candidate_transport.py",
@@ -1227,6 +1232,11 @@
"sha256": "3ba8efe338a21b100e4bc20e4fbffe043eb57c411a4143c00332fdb368db5011", "sha256": "3ba8efe338a21b100e4bc20e4fbffe043eb57c411a4143c00332fdb368db5011",
"bytes": 28482 "bytes": 28482
}, },
{
"path": "backend/tests/test_hub_security_publication_bindings.py",
"sha256": "7b086e64793faef0d98a2f62f36acbbc30d1f4b3363d4c6613db81f771358687",
"bytes": 3113
},
{ {
"path": "backend/tests/test_immutable_service_promotion.py", "path": "backend/tests/test_immutable_service_promotion.py",
"sha256": "8220a58307a0dd3a2ab8c885111b00ae57658bbc246e9e826fb46fcfddf76ef2", "sha256": "8220a58307a0dd3a2ab8c885111b00ae57658bbc246e9e826fb46fcfddf76ef2",
@@ -1264,8 +1274,8 @@
}, },
{ {
"path": "backend/tests/test_managed_validation_parallel.py", "path": "backend/tests/test_managed_validation_parallel.py",
"sha256": "8b3354bd6353831a081459b7398eac2ce4f8626251ff38422f6d217caf516ec3", "sha256": "dd8c2ac42ef8c129cc4ed7b24d72ef42f3e92d45fb3165822b9c8ea547c1648e",
"bytes": 2367 "bytes": 5935
}, },
{ {
"path": "backend/tests/test_mcp_hub_candidate_preparation.py", "path": "backend/tests/test_mcp_hub_candidate_preparation.py",
@@ -1279,8 +1289,8 @@
}, },
{ {
"path": "backend/tests/test_mcp_hub_governed_topology.py", "path": "backend/tests/test_mcp_hub_governed_topology.py",
"sha256": "59872024ae0a2e552aafe459d42d90098e022877648c3d77d33ce102c595d234", "sha256": "029cb69fec06a58bbf9125d0640e2b39aea0ec369d32da853ebf6a3f5fe0bcc5",
"bytes": 127375 "bytes": 129320
}, },
{ {
"path": "backend/tests/test_mcp_hub_legacy_registry_compatibility.py", "path": "backend/tests/test_mcp_hub_legacy_registry_compatibility.py",
@@ -1604,8 +1614,8 @@
}, },
{ {
"path": "backend/tests/test_runner_admission_controller.py", "path": "backend/tests/test_runner_admission_controller.py",
"sha256": "a03f9a18184149e210a3062578ade025559823050a355d55a760d861f36ae76c", "sha256": "b5ddebc17d647b3bb0a7032cc146fdc015da3fd8732063b8088f39f02b6569da",
"bytes": 81756 "bytes": 92461
}, },
{ {
"path": "backend/tests/test_runner_admission_policy.py", "path": "backend/tests/test_runner_admission_policy.py",
@@ -1682,6 +1692,11 @@
"sha256": "878fe58ff4dbb696ce6234b403f08f003a22881dba394cc2de1fbddc307c36ef", "sha256": "878fe58ff4dbb696ce6234b403f08f003a22881dba394cc2de1fbddc307c36ef",
"bytes": 3018 "bytes": 3018
}, },
{
"path": "backend/tests/test_runner_inventory_visibility.py",
"sha256": "06ff683bb9cd5b25053bce198e05a298b56e81352ce7230e13a8819a96f208f9",
"bytes": 3491
},
{ {
"path": "backend/tests/test_runner_profiles.py", "path": "backend/tests/test_runner_profiles.py",
"sha256": "45a8dba20d1e8d778dc90c20a997630037e2eaa1d462fa62f48671285aa82e0e", "sha256": "45a8dba20d1e8d778dc90c20a997630037e2eaa1d462fa62f48671285aa82e0e",
+13 -2
View File
@@ -344,6 +344,7 @@ class GiteaActionsConnector(BaseConnector):
"severity": severity, "severity": severity,
"generatedAt": datetime.now(UTC).isoformat(), "generatedAt": datetime.now(UTC).isoformat(),
"runners": [], "runners": [],
"inventory": {"scope": "all_registrations", "complete": False},
"queue": { "queue": {
"queued": 0, "queued": 0,
"inProgress": 0, "inProgress": 0,
@@ -404,7 +405,7 @@ class GiteaActionsConnector(BaseConnector):
try: try:
runner_payload = self._request( runner_payload = self._request(
"/api/v1/admin/actions/runners", {"disabled": "false"} "/api/v1/admin/actions/runners", {"page": 1, "limit": 100}
) )
queued_payload = self._request( queued_payload = self._request(
"/api/v1/admin/actions/jobs", "/api/v1/admin/actions/jobs",
@@ -654,7 +655,7 @@ class GiteaActionsConnector(BaseConnector):
elif ( elif (
(oldest_age or 0) >= _WARNING_AGE_SECONDS (oldest_age or 0) >= _WARNING_AGE_SECONDS
or (oldest_active_age or 0) >= _ACTIVE_WARNING_AGE_SECONDS or (oldest_active_age or 0) >= _ACTIVE_WARNING_AGE_SECONDS
or len(online_runners) < len(runners) or len(online_runners) < sum(not item["disabled"] for item in runners)
): ):
severity = "warning" severity = "warning"
@@ -702,6 +703,10 @@ class GiteaActionsConnector(BaseConnector):
restart_reason = "" restart_reason = ""
for label in [*blocked_labels, *stale_active_labels]: for label in [*blocked_labels, *stale_active_labels]:
target = self._target_for_label(label, runners, targets) target = self._target_for_label(label, runners, targets)
# A disabled registration can be an operator pause or a fenced
# active lease. Neither is permission to restart its container.
if any(item["name"] == target and item["disabled"] for item in runners):
continue
if target: if target:
restart_target = target restart_target = target
restart_reason = ( restart_reason = (
@@ -727,11 +732,17 @@ class GiteaActionsConnector(BaseConnector):
"severity": severity, "severity": severity,
"generatedAt": now.isoformat(), "generatedAt": now.isoformat(),
"runners": runners, "runners": runners,
"inventory": {
"scope": "all_registrations",
"complete": recovery_runners is not None,
},
"summary": { "summary": {
"total": len(runners), "total": len(runners),
"online": len(online_runners), "online": len(online_runners),
"busy": sum(bool(item["busy"]) for item in runners), "busy": sum(bool(item["busy"]) for item in runners),
"offline": sum(item["status"] != "online" for item in runners), "offline": sum(item["status"] != "online" for item in runners),
"disabled": sum(item["disabled"] for item in runners),
"available": sum(not item["busy"] for item in online_runners),
}, },
"queue": { "queue": {
"queued": display_count(queued_payload.get("total_count", 0)), "queued": display_count(queued_payload.get("total_count", 0)),
@@ -0,0 +1,52 @@
{
"artifactName": "hub-release-security-bases-3237e4d8aec312d63d13b4e80664422a7520b5f9",
"candidateEmitted": false,
"preparedImages": [
{
"archiveRef": "gitea.example.com/jens/itworx-mcp-hub/postgres:3237e4d8aec312d63d13b4e80664422a7520b5f9-security-run-23280-attempt-1",
"imageId": "sha256:227c8e37851f267cca5853042f86726995acadfbc84fd2d726879b6cce4d98a7",
"imageRef": "gitea.example.com/jens/itworx-mcp-hub/postgres:3237e4d8aec312d63d13b4e80664422a7520b5f9-security-run-23280-attempt-1@sha256:4e471418b9cf0805ed3c5cce716fb13ac96aa1fcabb6751fd4386b1db679e176",
"parentRef": "gitea.example.com/jens/itworx-mcp-hub/postgres:wp400-gosu-v2-20261002-a94e0b4d2029@sha256:a60d81e06987671ae903757f1b71cdfbbff4d481b42610e4de2b7dcfa32aad73",
"runtimeVerified": true,
"service": "postgres",
"sourceInputs": {
"evidence/WP-400/database-image-candidate-20261003/recipes/postgres/verify-gosu-metadata.sh": {
"materializedSha256": "0c33ed42751a48bb76908285519cef7a41b7e383b07418f641e799e183245a4b",
"sourceSha256": "0c33ed42751a48bb76908285519cef7a41b7e383b07418f641e799e183245a4b"
},
"infrastructure/images/security-bases/postgres/Dockerfile": {
"materializedSha256": "fcd828b854c6aa2c83116a813ef83e7fa5431f9c2035c98871d90720f166adfb",
"sourceSha256": "fcd828b854c6aa2c83116a813ef83e7fa5431f9c2035c98871d90720f166adfb"
}
},
"vulnerabilityAndSecretVerified": true
},
{
"archiveRef": "gitea.example.com/jens/itworx-mcp-hub/ingestion-clamd:3237e4d8aec312d63d13b4e80664422a7520b5f9-security-run-23280-attempt-1",
"imageId": "sha256:f16f3f6d8a2a0a6c56d32d4e97e173ad8fdff08c88ac40ddc9890ab27cfdda35",
"imageRef": "gitea.example.com/jens/itworx-mcp-hub/ingestion-clamd:3237e4d8aec312d63d13b4e80664422a7520b5f9-security-run-23280-attempt-1@sha256:eeca204bb48b30e78cf103bff00a33babb45e7c289747d7469396551803a8d23",
"parentRef": "clamav/clamav:1.4.6@sha256:a5f03c12a79dbe9f6d8a527b6bb1ea053fa8dd061d3738a26897f055ee2d9303",
"runtimeVerified": true,
"service": "ingestion-clamd",
"sourceInputs": {
"infrastructure/images/security-bases/ingestion-clamd/Dockerfile": {
"materializedSha256": "0b806f1077af26b85a059eb2a40eeff27b661ef997d57fc82bb648fc311043d5",
"sourceSha256": "0b806f1077af26b85a059eb2a40eeff27b661ef997d57fc82bb648fc311043d5"
},
"infrastructure/images/security-bases/ingestion-clamd/verify-pcre2.sh": {
"materializedSha256": "1ec848d1f52b37d3abfb56e1308383d4d2907810e65bad95368b5ecee60a5514",
"sourceSha256": "1ec848d1f52b37d3abfb56e1308383d4d2907810e65bad95368b5ecee60a5514"
}
},
"vulnerabilityAndSecretVerified": true
}
],
"reportCount": 5,
"repository": "jens/itworx_mcp_hub",
"revision": "3237e4d8aec312d63d13b4e80664422a7520b5f9",
"runAttempt": 1,
"runId": 23280,
"schema": "itworx.security-base-preparation/v1",
"status": "security-bases-prepared",
"tree": "8a97fdcd1fed62e48217326a29d18bc9805385ec"
}
+3 -2
View File
@@ -8760,9 +8760,10 @@ def test_appops_uses_push_validation_without_a_deploy_runner_workflow():
assert "branches: [main]" in managed_validation assert "branches: [main]" in managed_validation
assert "unraid-deploy" not in managed_validation assert "unraid-deploy" not in managed_validation
# Keep all jobs on the installed legacy fleet during specialized-runner bootstrap. # The fleet is specialized: lightweight jobs use Checks, while the four
expected_runner = "linux-validation" # execution lanes retain their installed legacy-compatible routing.
for job in ("preflight", "backend", "frontend", "security", "polyglot", "full"): for job in ("preflight", "backend", "frontend", "security", "polyglot", "full"):
expected_runner = "itworx-ci-checks" if job in {"preflight", "full"} else "linux-validation"
match = re.search( match = re.search(
rf"(?ms)^ {re.escape(job)}:\n(?P<body>.*?)(?=^ [a-z][a-z0-9_-]*:\n|\Z)", rf"(?ms)^ {re.escape(job)}:\n(?P<body>.*?)(?=^ [a-z][a-z0-9_-]*:\n|\Z)",
managed_validation, managed_validation,
@@ -1184,6 +1184,81 @@ def test_custom_external_database_accepts_exact_custom_repo_digest(
assert calls == [archive_ref, image_ref] assert calls == [archive_ref, image_ref]
@pytest.mark.parametrize("service", ("postgres", "ingestion-clamd"))
def test_reviewed_external_variant_requires_its_exact_archive_and_digest(
modules, monkeypatch, service
):
importer, controller = modules.importer, modules.controller
image_ref = f"gitea.example.com/jens/itworx-mcp-hub/{service}:security-fixture@sha256:{'b' * 64}"
archive_ref = f"itworx-mcp-hub/{service}:security-fixture"
repo_digest = image_ref.split(":security-fixture", 1)[0] + "@sha256:" + "b" * 64
approved = {
name: (binding,) for name, binding in importer.EXTERNAL_IMAGES.items()
}
approved[service] += ((image_ref, archive_ref, repo_digest),)
monkeypatch.setattr(controller, "MCP_HUB_APPROVED_EXTERNAL_IMAGE_BINDINGS", approved, raising=False)
image_id = "sha256:" + "c" * 64
inspected = {
archive_ref: {"Id": image_id},
image_ref: {"Id": image_id, "RepoDigests": [repo_digest]},
}
monkeypatch.setattr(importer, "_inspect_image", inspected.get)
row = {"imageRef": image_ref, "archiveRef": archive_ref, "imageId": image_id}
assert importer._require_loaded_image(service, row, external=True)["Id"] == image_id
inspected[image_ref]["RepoDigests"] = [repo_digest[:-1] + "0"]
with pytest.raises(importer.CandidateRejected, match="Pinned external digest"):
importer._require_loaded_image(service, row, external=True)
@pytest.mark.parametrize("service", ("postgres", "ingestion-clamd"))
def test_external_variant_never_accepts_an_unreviewed_ref(modules, monkeypatch, service):
importer = modules.importer
image_id = "sha256:" + "c" * 64
unknown_ref = f"gitea.example.com/jens/itworx-mcp-hub/{service}:unknown@sha256:{'b' * 64}"
monkeypatch.setattr(importer, "_inspect_image", lambda _ref: {"Id": image_id, "RepoDigests": []})
with pytest.raises(importer.CandidateRejected, match="reviewed external image binding"):
importer._require_loaded_image(
service, {"imageRef": unknown_ref, "archiveRef": "unknown", "imageId": image_id}, external=True
)
@pytest.mark.parametrize("service", ("postgres", "ingestion-clamd"))
def test_protected_model_external_variant_has_a_distinct_exact_archive_ref(
modules, monkeypatch, service
):
importer, controller = modules.importer, modules.controller
image_ref = f"gitea.example.com/jens/itworx-mcp-hub/{service}:security-fixture@sha256:{'b' * 64}"
archive_ref = f"itworx-mcp-hub/{service}:security-fixture"
approved = {name: (binding,) for name, binding in importer.EXTERNAL_IMAGES.items()}
approved[service] += ((image_ref, archive_ref, image_ref.split(":security-fixture", 1)[0] + "@sha256:" + "b" * 64),)
monkeypatch.setattr(controller, "MCP_HUB_APPROVED_EXTERNAL_IMAGE_BINDINGS", approved)
services = {
name: {"image": importer.EXTERNAL_IMAGES[name][0] if name in importer.EXTERNAL_IMAGES else "fixture:" + name}
for name in controller.MCP_HUB_SERVICES
}
ingestion = {"imageRef": services["connector-ingestion"]["image"], "archiveRef": "fixture:ingestion"}
services[service]["image"] = image_ref
references = importer._expected_image_refs({"services": services}, ingestion_binding=ingestion)
assert references[service] == (image_ref, archive_ref)
assert all(references[name][1] == binding[1] for name, binding in importer.EXTERNAL_IMAGES.items() if name != service)
services[service]["image"] = image_ref[:-1] + "0"
with pytest.raises(importer.CandidateRejected, match="fixed digest"):
importer._expected_image_refs({"services": services}, ingestion_binding=ingestion)
@pytest.mark.parametrize("service", ("postgres", "ingestion-clamd"))
def test_loaded_external_image_cannot_substitute_an_archive_alias(modules, monkeypatch, service):
importer = modules.importer
image_ref = importer.EXTERNAL_IMAGES[service][0]
monkeypatch.setattr(importer, "_inspect_image", lambda _ref: pytest.fail("must reject before inspecting a foreign alias"))
with pytest.raises(importer.CandidateRejected, match="reviewed external image binding"):
importer._require_loaded_image(
service,
{"imageRef": image_ref, "archiveRef": "foreign:alias", "imageId": "sha256:" + "c" * 64},
external=True,
)
@pytest.mark.parametrize("service", ("postgres", "redis")) @pytest.mark.parametrize("service", ("postgres", "redis"))
@pytest.mark.parametrize( @pytest.mark.parametrize(
"failure", ("upstream", "wrong_custom", "missing_repo_digests", "foreign_image_id") "failure", ("upstream", "wrong_custom", "missing_repo_digests", "foreign_image_id")
@@ -0,0 +1,60 @@
from __future__ import annotations
import json
from pathlib import Path
import pytest
from test_hub_candidate_import import modules # noqa: F401 - reuse importer isolation fixture
RECEIPT = json.loads(
(Path(__file__).parent / "fixtures/hub_security_base_publication_23280.json").read_text()
)
@pytest.mark.parametrize("row", RECEIPT["preparedImages"], ids=lambda row: row["service"])
def test_actual_published_security_image_requires_exact_archive_id_and_digest(modules, monkeypatch, row):
importer, controller = modules.importer, modules.controller
service = row["service"]
repository, digest = row["imageRef"].split("@", 1)
repo_digest = repository.rsplit(":", 1)[0] + "@" + digest
assert RECEIPT["revision"] == "3237e4d8aec312d63d13b4e80664422a7520b5f9"
assert RECEIPT["runId"] == 23280 and RECEIPT["runAttempt"] == 1
assert RECEIPT["candidateEmitted"] is False and RECEIPT["reportCount"] == 5
assert row["runtimeVerified"] and row["vulnerabilityAndSecretVerified"]
inspected = {
row["archiveRef"]: {"Id": row["imageId"]},
row["imageRef"]: {"Id": row["imageId"], "RepoDigests": [repo_digest]},
}
monkeypatch.setattr(importer, "_inspect_image", inspected.get)
assert importer._require_loaded_image(service, row, external=True)["Id"] == row["imageId"]
binding = controller.mcp_hub_external_image_binding(service, row["imageRef"])
assert binding == (row["imageRef"], row["archiveRef"], repo_digest)
old_binding = controller.mcp_hub_external_image_binding(service, row["parentRef"])
assert old_binding is not None
assert old_binding[1] != row["archiveRef"]
with pytest.raises(importer.CandidateRejected, match="reviewed external image binding"):
importer._require_loaded_image(service, {**row, "archiveRef": old_binding[1]}, external=True)
inspected[row["archiveRef"]]["Id"] = "sha256:" + "0" * 64
with pytest.raises(importer.CandidateRejected, match="Loaded Docker image ID differs"):
importer._require_loaded_image(service, row, external=True)
inspected[row["archiveRef"]]["Id"] = row["imageId"]
inspected[row["imageRef"]]["RepoDigests"] = [old_binding[2]]
with pytest.raises(importer.CandidateRejected, match="Pinned external digest"):
importer._require_loaded_image(service, row, external=True)
@pytest.mark.parametrize("row", RECEIPT["preparedImages"], ids=lambda row: row["service"])
def test_actual_security_pin_preserves_only_reviewed_forward_predecessors(modules, row):
controller = modules.controller
allowed = controller._mcp_hub_observed_external_ref_allowed
service, new, old = row["service"], row["imageRef"], row["parentRef"]
assert allowed(service, new, old)
assert allowed(service, new, new)
assert not allowed(service, old, new)
assert not allowed(service, new, old + "-drift")
assert not allowed(service, new[:-1] + "0", old)
if service == "postgres":
assert allowed(service, new, controller.MCP_HUB_POSTGRES_LEGACY_IMAGE)
assert allowed(service, new, controller.MCP_HUB_POSTGRES_PREVIOUS_IMAGE)
@@ -1,6 +1,12 @@
import re import re
import importlib.util
import os
import subprocess
import sys
from pathlib import Path from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2] ROOT = Path(__file__).resolve().parents[2]
WORKFLOW = ROOT / ".gitea" / "workflows" / "managed-validation.yml" WORKFLOW = ROOT / ".gitea" / "workflows" / "managed-validation.yml"
@@ -61,3 +67,68 @@ def test_backend_budget_is_bounded_without_weakening_validation():
assert "continue-on-error" not in backend_body assert "continue-on-error" not in backend_body
assert "--ignore" not in backend_body assert "--ignore" not in backend_body
assert "--deselect" not in backend_body assert "--deselect" not in backend_body
def _job_body(job):
text = WORKFLOW.read_text(encoding="utf-8")
match = re.search(rf"(?ms)^ {re.escape(job)}:\n(?P<body>.*?)(?=^ [a-z][a-z0-9_-]*:\n|\Z)", text)
assert match is not None
return match["body"]
def test_light_checks_use_existing_single_checks_profile():
spec = importlib.util.spec_from_file_location(
"appops_light_checks_profiles", ROOT / "ops/gitea-deploy-broker/runner_profiles.py"
)
profiles = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = profiles
spec.loader.exec_module(profiles)
try:
for job in ("preflight", "full"):
label = re.search(r"(?m)^ runs-on: (\S+)\s*$", _job_body(job)).group(1)
assert tuple(profile.id for profile in profiles.profiles_for_labels((label,))) == ("checks",)
assert profiles.RUNNER_PROFILES["checks"].memory_mib == 1536
for job in ("backend", "frontend", "security", "polyglot"):
assert " runs-on: linux-validation\n" in _job_body(job)
finally:
sys.modules.pop(spec.name, None)
def _bash_script(job):
body = _job_body(job)
script = body.split(" run: |\n", 1)[1]
return "\n".join(line[10:] if line.startswith(" ") else line for line in script.splitlines())
@pytest.mark.skipif(os.name == "nt", reason="Execute actual workflow Bash on Linux")
@pytest.mark.parametrize("failed_lane", [None, "PREFLIGHT", "BACKEND", "FRONTEND", "SECURITY", "POLYGLOT"])
def test_light_full_gate_executes_all_required_lane_results(tmp_path, failed_lane):
environment = {"PATH": os.defpath, **{name: "success" for name in ("PREFLIGHT", "BACKEND", "FRONTEND", "SECURITY", "POLYGLOT")}}
if failed_lane:
environment[failed_lane] = "failure"
result = subprocess.run(["bash", "-c", _bash_script("full")], cwd=tmp_path, env=environment,
capture_output=True, text=True, timeout=10)
assert (result.returncode == 0) is (failed_lane is None)
assert ("All managed validation lanes passed." in result.stdout) is (failed_lane is None)
@pytest.mark.skipif(os.name == "nt", reason="Execute actual workflow Bash/Git on Linux")
@pytest.mark.parametrize("change", ["clean", "whitespace", "conflict"])
def test_light_preflight_executes_git_and_rejects_bad_source(tmp_path, change):
environment = {"PATH": os.defpath, "HOME": str(tmp_path), "GITHUB_OUTPUT": str(tmp_path / "output")}
for args in (["init", "--quiet"], ["config", "user.name", "CI fixture"],
["config", "user.email", "ci@example.invalid"]):
subprocess.run(["git", *args], cwd=tmp_path, env=environment, check=True, capture_output=True)
readme = tmp_path / "README.md"
readme.write_text("Clean source\n")
subprocess.run(["git", "add", "README.md"], cwd=tmp_path, env=environment, check=True, capture_output=True)
subprocess.run(["git", "commit", "--quiet", "-m", "fixture"], cwd=tmp_path, env=environment, check=True, capture_output=True)
if change == "whitespace":
readme.write_text("Trailing whitespace \n")
elif change == "conflict":
readme.write_text("<<<<<<< fixture\n")
result = subprocess.run(["bash", "-c", _bash_script("preflight")], cwd=tmp_path, env=environment,
capture_output=True, text=True, timeout=10)
assert (result.returncode == 0) is (change == "clean")
if change == "clean":
assert "runtime_change=true" in (tmp_path / "output").read_text()
@@ -2234,6 +2234,37 @@ def test_observed_baseline_is_separate_evidence_and_preserves_unknown_controller
if os.name != "nt": if os.name != "nt":
assert stat.S_IMODE(evidence_path.stat().st_mode) == 0o600 assert stat.S_IMODE(evidence_path.stat().st_mode) == 0o600
@pytest.mark.parametrize("service", ("postgres", "ingestion-clamd"))
def test_reviewed_security_transition_preserves_the_exact_live_baseline(
controller, monkeypatch, tmp_path, service
):
project, _candidate, model, _backup, runtime, _images, state_path, prior = (
_observed_live_fixture(controller, monkeypatch, tmp_path)
)
original_state = state_path.read_bytes()
name = f"itworx-mcp-hub-{service}-1"
observed_ref = runtime[name]["Config"]["Image"]
security_ref = f"gitea.example.com/jens/itworx-mcp-hub/{service}:security-fixture@sha256:{'e' * 64}"
bindings = dict(controller.MCP_HUB_APPROVED_EXTERNAL_IMAGE_BINDINGS)
bindings[service] += ((security_ref, "fixture:security", security_ref),)
monkeypatch.setattr(controller, "MCP_HUB_APPROVED_EXTERNAL_IMAGE_BINDINGS", bindings)
transitions = dict(getattr(controller, "MCP_HUB_APPROVED_OBSERVED_EXTERNAL_TRANSITIONS", {}))
transitions[service] = {security_ref: (observed_ref, security_ref)}
monkeypatch.setattr(controller, "MCP_HUB_APPROVED_OBSERVED_EXTERNAL_TRANSITIONS", transitions, raising=False)
model["services"][service]["image"] = security_ref
verified, facts, observed_model = controller.mcp_hub_verify_observed_baseline(project, prior, model)
assert verified[name]["Config"]["Image"] == observed_ref
assert facts[name]["image_ref"] == observed_ref
assert observed_model["services"][service]["image"] == observed_ref
assert state_path.read_bytes() == original_state
assert controller._mcp_hub_observed_external_ref_allowed(service, security_ref, observed_ref)
assert not controller._mcp_hub_observed_external_ref_allowed(service, observed_ref, security_ref)
assert not controller._mcp_hub_observed_external_ref_allowed(service, security_ref, observed_ref + "-unexpected")
assert not controller._mcp_hub_observed_external_ref_allowed(service, security_ref[:-1] + "0", observed_ref)
def test_backup_receipt_validator_rejects_an_unpersisted_boolean_claim( def test_backup_receipt_validator_rejects_an_unpersisted_boolean_claim(
controller, monkeypatch, tmp_path controller, monkeypatch, tmp_path
): ):
@@ -316,6 +316,69 @@ def test_safe_live_metric_fluctuations_do_not_restart_stable_headroom(controller
assert reason is None assert reason is None
@pytest.mark.parametrize("change", ["load", "memory", "cache", "swap", "stale", "future", "pressure", "guard"])
def test_cached_post_start_sample_preserves_stability_without_authorizing_enable(
controller_module, monkeypatch, change
):
controller, now, host, capacity = _host_gate_sample(controller_module, monkeypatch)
state = {}
controller._fresh_mutation_gate("backend", ["backend"], state)
now[0] = 160
host["swapSampleAt"] = 160
assert controller._fresh_mutation_gate("backend", ["backend"], state)[0] is None
established = copy.deepcopy(state["hostStability"])
now[0] = 161
assert controller._fresh_mutation_gate(
"backend", ["backend"], state, minimum_sample_at=160
)[0] == "runner_admission_host_telemetry_not_refreshed"
assert state["hostStability"] == established
now[0] = 162
host["swapSampleAt"] = 162
assert controller._fresh_mutation_gate(
"backend", ["backend"], state, minimum_sample_at=160
)[0] is None
if change == "load":
host["loadRatio"] = 0.71
elif change == "memory":
host["availableMemoryBytes"] = 15 * 1024**3 - 1
elif change == "cache":
host["cacheFreeBytes"] = 0
elif change == "swap":
host["swapCritical"] = True
elif change == "stale":
now[0] = 253
elif change == "future":
host["swapSampleAt"] = 163
elif change == "pressure":
capacity["decision"]["pressure"] = "critical"
elif change == "guard":
monkeypatch.setattr(controller, "_host_evidence", lambda: ("blocked", "runner_capacity_pressure_critical", capacity))
assert controller._fresh_mutation_gate(
"backend", ["backend"], state, minimum_sample_at=162
)[0] is not None
assert state["hostStability"] is None
def test_cached_post_start_wait_never_shortens_required_stability(controller_module, monkeypatch):
controller, now, host, _ = _host_gate_sample(controller_module, monkeypatch)
state = {}
controller._fresh_mutation_gate("backend", ["backend"], state)
now[0] = 130
host["swapSampleAt"] = 130
assert controller._fresh_mutation_gate("backend", ["backend"], state)[0] == "runner_admission_host_headroom_not_stable"
now[0] = 131
assert controller._fresh_mutation_gate(
"backend", ["backend"], state, minimum_sample_at=130
)[0] == "runner_admission_host_telemetry_not_refreshed"
now[0] = 140
host["swapSampleAt"] = 140
assert controller._fresh_mutation_gate(
"backend", ["backend"], state, minimum_sample_at=130
)[0] == "runner_admission_host_headroom_not_stable"
assert state["hostStability"]["since"] == 100
@pytest.mark.parametrize("change", ["load", "memory", "cache", "swap", "stale", "future", "pressure", "guard"]) @pytest.mark.parametrize("change", ["load", "memory", "cache", "swap", "stale", "future", "pressure", "guard"])
def test_unsafe_sample_restarts_the_entire_stability_window(controller_module, monkeypatch, change): def test_unsafe_sample_restarts_the_entire_stability_window(controller_module, monkeypatch, change):
module = controller_module module = controller_module
@@ -1539,6 +1602,142 @@ def test_busy_controller_owned_runner_gets_a_durable_disable_but_job_is_not_stop
assert claims == ["backend"] assert claims == ["backend"]
@pytest.mark.parametrize("busy_flag,active_inventory", [(True, False), (False, True), (True, True)])
def test_busy_disabled_drain_does_not_starve_other_profile(
controller_module, monkeypatch, busy_flag, active_inventory
):
module = controller_module
waiting = {"id": "waiting-backend", "labels": ["itworx-ci-backend"], "queued_at": time.time() - 30}
controller, state, observation, _inventory, containers = _lease_fixture(
module, enabled=("frontend",), busy=("frontend",), queue=(waiting,)
)
profile = module.RUNNER_PROFILES["frontend"]
runner_id = observation["profileRunnerIds"]["frontend"]
row = observation["runnerRows"][profile.container_name]
row.update(disabled=True, busy=busy_flag)
state["profiles"]["frontend"].update(enabledByController=False, drainOwned=True)
if not active_inventory:
observation["activeJobs"][runner_id] = []
stops = []
monkeypatch.setattr(controller, "_stop_drained_profile", lambda *args, **kwargs: stops.append(kwargs) or "runner_admission_drain_stop_deferred")
assert controller._drain_one_idle_profile(state, observation) is None
assert stops == []
assert containers[profile.container_name]["running"] is True
assert state["profiles"]["frontend"]["drainOwned"] is True
assert observation["claims"] == ["frontend"]
choice = module.select_admission(
observation["queue"], available_profiles=["backend"], active_claims=observation["claims"]
)
assert choice.profile_id == "backend"
@pytest.mark.parametrize("blocked", [None, "resource", "host", "capacity"])
@pytest.mark.parametrize("projection_status", ["healthy", "degraded"])
def test_cycle_can_select_second_slot_during_busy_drain_but_keeps_guards(
controller_module, monkeypatch, blocked, projection_status
):
module = controller_module
now = time.time()
waiting = {"id": "waiting-backend", "labels": ["itworx-ci-backend"], "queued_at": now - 30}
controller, state, observation, _inventory, _containers = _lease_fixture(
module, enabled=("frontend",), busy=("frontend",), queue=(waiting,)
)
profile = module.RUNNER_PROFILES["frontend"]
observation["runnerRows"][profile.container_name]["disabled"] = True
state["profiles"]["frontend"].update(enabledByController=False, drainOwned=True)
state["terminalHistoryUpdatedAt"] = now
observation.update(specialization="active", at=now, resourceProof={"ready": True}, hostReason=None)
if blocked == "resource":
observation.update(resourceProof=None, resourceReason="runner_admission_resource_attestation_unready")
elif blocked == "host":
observation["hostReason"] = "runner_capacity_pressure_critical"
elif blocked == "capacity":
observation["claims"].append("build")
selected = []
monkeypatch.setattr(controller, "_process_lock", lambda: nullcontext())
monkeypatch.setattr(controller, "_read_state", lambda: state)
monkeypatch.setattr(controller, "_save_state", lambda _state: None)
monkeypatch.setattr(controller, "_observe", lambda **_kwargs: observation)
monkeypatch.setattr(controller, "_seed_or_consume_bootstrap_receipt", lambda *_args: False)
monkeypatch.setattr(controller, "_reconcile_ownership", lambda *_args: False)
monkeypatch.setattr(controller, "_record_aggregate_sample", lambda *_args: False)
monkeypatch.setattr(controller, "_record_idle_state", lambda *_args: False)
monkeypatch.setattr(controller, "_public_snapshot", lambda *_args, **_kwargs: {"status": projection_status, "reason": None})
monkeypatch.setattr(controller, "_write_projection", lambda _projection: None)
monkeypatch.setattr(controller, "_stop_drained_profile", lambda *_args, **_kwargs: pytest.fail("busy job must be retained"))
monkeypatch.setattr(controller, "_continue_pending", lambda *_args, **kwargs: selected.append(kwargs["reserved_profile_id"]) or "test_selected")
result = controller.cycle()
assert selected == (["backend"] if blocked is None else [])
assert observation["claims"] == (["frontend", "build"] if blocked == "capacity" else ["frontend"])
assert state["profiles"]["frontend"]["drainOwned"] is True
if blocked is not None:
assert state["pending"] is None
assert result["status"] != "test_selected"
assert result["statistics"]["reason"] == result["status"]
@pytest.mark.parametrize("stage", ["reserved", "started"])
@pytest.mark.parametrize("blocked", [None, "operator", "fresh_queue", "guard"])
def test_pending_start_does_not_starve_guarded_idle_lease_cleanup(
controller_module, monkeypatch, stage, blocked
):
module = controller_module
now = time.time()
waiting = {"id": "queued-backend", "labels": [module.RUNNER_PROFILES["backend"].runner_label], "queued_at": now - 600}
controller, state, observation, inventory, containers = _lease_fixture(
module, enabled=("checks",), queue=(waiting,)
)
checks = module.RUNNER_PROFILES["checks"]
checks_id = observation["profileRunnerIds"]["checks"]
pending = {"profileId": "backend", "runnerId": observation["profileRunnerIds"]["backend"], "jobId": waiting["id"], "createdAt": module._utc_iso(now - 200), "stage": stage}
state.update(pending=pending, terminalHistoryUpdatedAt=module._utc_iso(now))
state["profiles"]["checks"]["idleSince"] = now - module.IDLE_DRAIN_SECONDS - 1
observation.update(specialization="active", at=now, resourceProof={"ready": True}, claims=["checks", "backend"])
if stage == "started":
containers[module.RUNNER_PROFILES["backend"].container_name].update(running=True, health="healthy")
if blocked == "operator":
state["profiles"]["checks"]["operatorEnabled"] = True
queue_rows = [_raw_job(module, waiting)]
if blocked == "fresh_queue":
queued_check = {"id": "queued-checks", "labels": [checks.runner_label], "queued_at": now - 10}
observation["queue"].append(queued_check)
queue_rows.append(_raw_job(module, queued_check))
_install_lease_io(monkeypatch, controller, module, inventory, containers, queue_rows=queue_rows)
if blocked == "guard":
monkeypatch.setattr(controller, "_trusted_host_guard_state", lambda: ("blocked", "guard"))
patches, continued = [], []
def disable(runner_id, value):
patches.append((runner_id, value))
next(row for row in inventory if row["id"] == runner_id)["disabled"] = value
monkeypatch.setattr(controller, "_set_disabled", disable)
monkeypatch.setattr(controller, "_process_lock", lambda: nullcontext())
monkeypatch.setattr(controller, "_read_state", lambda: state)
monkeypatch.setattr(controller, "_observe", lambda **_kwargs: observation)
monkeypatch.setattr(controller, "_seed_or_consume_bootstrap_receipt", lambda *_args: False)
monkeypatch.setattr(controller, "_reconcile_ownership", lambda *_args: False)
monkeypatch.setattr(controller, "_record_aggregate_sample", lambda *_args: False)
monkeypatch.setattr(controller, "_public_snapshot", lambda *_args, **_kwargs: {"status": "healthy"})
monkeypatch.setattr(controller, "_write_projection", lambda *_args: None)
monkeypatch.setattr(controller, "_continue_pending", lambda *_args, **_kwargs: continued.append(True) or "runner_admission_host_headroom_insufficient")
result = controller.cycle()
assert state["pending"] is pending
if blocked is None:
assert result["status"] == "runner_admission_drained_idle_profile"
assert patches == [(checks_id, True)] and continued == []
assert containers[checks.container_name]["running"] is False
else:
assert patches == [] and containers[checks.container_name]["running"] is True
expected = {
"operator": "runner_admission_host_headroom_insufficient",
"fresh_queue": "runner_admission_drain_deferred_queue",
"guard": "runner_admission_drain_state_changed",
}
assert result["status"] == expected[blocked]
def test_cycle_fences_a_busy_owned_lease_even_without_a_resource_proof( def test_cycle_fences_a_busy_owned_lease_even_without_a_resource_proof(
controller_module, monkeypatch controller_module, monkeypatch
): ):
@@ -0,0 +1,93 @@
"""Complete display inventory must never authorize recovery of fenced runners."""
from datetime import UTC, datetime, timedelta
from backend.app.core.config import settings
from backend.tests.test_runner_scheduler_liveness_recovery import _configure
def _snapshot(
monkeypatch, *, busy=False, queued=False, apply_filter=True, incomplete=False
):
connector = _configure(monkeypatch)
monkeypatch.setitem(
settings.apis,
"GITEA_RUNNER_TARGETS_JSON",
'{"linux-validation":"itworx-ci-backend"}',
)
runners = [
{
"id": 71 + index,
"name": f"itworx-ci-{profile}",
"status": "online" if busy and profile == "backend" else "offline",
"busy": busy and profile == "backend",
"disabled": True,
"labels": ["linux-validation"],
"token": "fixture-secret",
}
for index, profile in enumerate(
("checks", "backend", "frontend", "security", "browser", "build")
)
]
requests = []
def request(path, params=None):
requests.append((path, params))
if path.endswith("/runners"):
rows = [] if apply_filter and params.get("disabled") == "false" else runners
return {"total_count": len(rows) + int(incomplete), "runners": rows}
jobs = []
if queued and params.get("status") == "queued":
jobs = [
{
"id": 9,
"status": "queued",
"runner_id": 0,
"labels": ["linux-validation"],
"created_at": (
datetime.now(UTC) - timedelta(minutes=20)
).isoformat(),
}
]
return {"total_count": len(jobs), "jobs": jobs}
monkeypatch.setattr(connector, "_request", request)
return connector.snapshot(refresh=True), requests
def test_standby_fleet_remains_visible_and_does_not_appear_broken(monkeypatch):
result, requests = _snapshot(monkeypatch)
assert len(result["runners"]) == 6
assert result["summary"]["disabled"] == 6
assert result["summary"]["available"] == 0
assert result["inventory"] == {"scope": "all_registrations", "complete": True}
assert result["severity"] == "healthy"
assert result["recommendedAction"] is None
assert "fixture-secret" not in repr(result)
assert requests[0][1] == {"page": 1, "limit": 100}
def test_fenced_busy_runner_is_counted_without_becoming_claimable(monkeypatch):
result, _ = _snapshot(monkeypatch, busy=True)
assert result["summary"]["busy"] == 1
assert result["summary"]["online"] == 0
assert result["summary"]["available"] == 0
assert result["summary"]["disabled"] == 6
assert result["runners"][1]["busy"] is True
assert result["runners"][1]["disabled"] is True
def test_disabled_runner_never_receives_restart_guidance_for_a_stalled_queue(
monkeypatch,
):
result, _ = _snapshot(monkeypatch, queued=True, apply_filter=False)
assert result["severity"] == "critical"
assert result["queue"]["queued"] == 1
assert result["recommendedAction"] is None
def test_incomplete_runner_sample_is_not_reported_as_complete(monkeypatch):
result, _ = _snapshot(monkeypatch, incomplete=True)
assert len(result["runners"]) == 6
assert result["inventory"] == {"scope": "all_registrations", "complete": False}
assert result["recommendedAction"] is None