fix: task templates use ingress CP_URL (https://agents.oreillyit.nz/api), not svc.cluster.local:8100
The deploy repo NetworkPolicy admits :8100 only from named apps and the traefik/cms-proxy namespaces; agent/script pods time out, so state-tx / cp-cli calls silently lost transitions. Invariant now rejects the in-cluster form and pins the ingress URL. Claude-Session: https://claude.ai/code/session_01N218bERyNeLhbLmDRDvbWF
This commit is contained in:
@@ -33,7 +33,7 @@ nodes:
|
||||
cmd: scripts/workflow/parent-link-check
|
||||
on_fail: refuse_dispatch
|
||||
runtime_env:
|
||||
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||
CP_URL: "https://agents.oreillyit.nz/api"
|
||||
WORKFLOW_ITEM_UUID: "${item.uuid}"
|
||||
PARENT_LINK_TAG: auto-resolve-bugs
|
||||
PARENT_LINK_RELATION: parent
|
||||
@@ -45,7 +45,7 @@ nodes:
|
||||
depends_on: [parent-link-check]
|
||||
on_fail: escalate
|
||||
runtime_env:
|
||||
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||
CP_URL: "https://agents.oreillyit.nz/api"
|
||||
WORKFLOW_ITEM_UUID: "${item.uuid}"
|
||||
TAG_SET_ADD: ai-resolve
|
||||
# Advance the bug; R2 then dispatches bug-verify-sonnet@1 at verify-pending.
|
||||
@@ -55,7 +55,7 @@ nodes:
|
||||
depends_on: [tag-ai-resolve]
|
||||
on_fail: escalate
|
||||
runtime_env:
|
||||
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||
CP_URL: "https://agents.oreillyit.nz/api"
|
||||
STATE_TX_NEW_STATE: verify-pending
|
||||
STATE_TX_FROM_STATES: "pending,open"
|
||||
# NOTE (script-node credentials): kind: script nodes are harness-exempt
|
||||
|
||||
@@ -36,7 +36,7 @@ nodes:
|
||||
runtime_env:
|
||||
AGENT_REPO_URL: "git@gitea.oreillyit.nz-ai-enablement:skynet/agent-runtimes-agents.git"
|
||||
AGENT_BRANCH: "bug-verify/${item.uuid}"
|
||||
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||
CP_URL: "https://agents.oreillyit.nz/api"
|
||||
prompt: |
|
||||
The agent-runtimes project repo is cloned at /workspace/project.
|
||||
Change to that directory before doing any work.
|
||||
|
||||
@@ -30,7 +30,7 @@ nodes:
|
||||
runtime_env:
|
||||
AGENT_REPO_URL: "git@gitea.oreillyit.nz-ai-enablement:skynet/agent-runtimes-agents.git"
|
||||
AGENT_BRANCH: "bug-verify/${item.uuid}"
|
||||
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||
CP_URL: "https://agents.oreillyit.nz/api"
|
||||
prompt: |
|
||||
The agent-runtimes project repo is cloned at /workspace/project.
|
||||
Change to that directory before doing any work.
|
||||
|
||||
@@ -22,6 +22,6 @@ nodes:
|
||||
cmd: scripts/workflow/state-tx
|
||||
on_fail: continue
|
||||
runtime_env:
|
||||
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||
CP_URL: "https://agents.oreillyit.nz/api"
|
||||
STATE_TX_NEW_STATE: test-skeleton-ready
|
||||
STATE_TX_FROM_STATES: scoped-tagged
|
||||
|
||||
@@ -27,7 +27,7 @@ nodes:
|
||||
runtime_env:
|
||||
AGENT_REPO_URL: "git@gitea.oreillyit.nz-ai-enablement:skynet/agent-runtimes-agents.git"
|
||||
AGENT_BRANCH: "spec/${item.uuid}"
|
||||
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||
CP_URL: "https://agents.oreillyit.nz/api"
|
||||
# AR-38: this stage's deliverable is work items POSTed to the CP, not a
|
||||
# repo diff — the empty-deliverable audit would fail every success.
|
||||
AGENT_EMPTY_DELIVERABLE_CHECK: "false"
|
||||
|
||||
@@ -26,7 +26,7 @@ nodes:
|
||||
runtime_env:
|
||||
AGENT_REPO_URL: "git@gitea.oreillyit.nz-ai-enablement:skynet/agent-runtimes-agents.git"
|
||||
AGENT_BRANCH: "spec/${item.uuid}"
|
||||
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||
CP_URL: "https://agents.oreillyit.nz/api"
|
||||
# The deliverable is a directory of plan files on disk — NOT a git diff.
|
||||
AGENT_EMPTY_DELIVERABLE_CHECK: "false"
|
||||
prompt: |
|
||||
|
||||
@@ -30,6 +30,6 @@ nodes:
|
||||
cmd: scripts/workflow/state-tx
|
||||
on_fail: continue
|
||||
runtime_env:
|
||||
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||
CP_URL: "https://agents.oreillyit.nz/api"
|
||||
STATE_TX_NEW_STATE: test-validated
|
||||
STATE_TX_FROM_STATES: test-write-pending
|
||||
|
||||
@@ -60,3 +60,58 @@ def test_state_tx_node_declares_from_states(name):
|
||||
assert doc["output"]["state"] not in states
|
||||
# The template's own input state must be an acceptable from-state.
|
||||
assert doc["input"]["state"] in states
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# CP_URL must be the ingress form, never the in-cluster Service on :8100.
|
||||
#
|
||||
# The deploy repo's networkpolicy-cp-internal-traefik-only.yaml admits :8100 only
|
||||
# from dashboard / git-planner-backend / cert-expiry-checker and the traefik and
|
||||
# cms-proxy namespaces. Agent/script pods are dropped, so a template pointing
|
||||
# CP_URL at svc.cluster.local:8100 times out (30s) and, with on_fail: continue,
|
||||
# silently loses the transition. The workflow scripts join CP_URL + "/v1/...",
|
||||
# so the /api ingress path prefix is preserved.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
CP_URL_INGRESS = "https://agents.oreillyit.nz/api"
|
||||
_FORBIDDEN_CP_URL_MARKERS = ("svc.cluster.local:8100", "controlplane.agent-runtimes.svc")
|
||||
|
||||
_ALL_TEMPLATES = sorted(_DIR.glob("*.yaml"))
|
||||
|
||||
|
||||
def _cp_url_values(path: Path) -> list[str]:
|
||||
doc = yaml.safe_load(path.read_text())
|
||||
return [
|
||||
(n.get("runtime_env") or {})["CP_URL"]
|
||||
for n in (doc.get("nodes") or [])
|
||||
if "CP_URL" in (n.get("runtime_env") or {})
|
||||
]
|
||||
|
||||
|
||||
def test_cp_url_templates_discovered():
|
||||
names = {p.name for p in _ALL_TEMPLATES if _cp_url_values(p)}
|
||||
assert {
|
||||
"test-validate@1.yaml",
|
||||
"frozen-fixture-emit@1.yaml",
|
||||
"bug-ancestor-auto-advance@1.yaml",
|
||||
"scope-decompose-sonnet@1.yaml",
|
||||
"scope-decompose-sonnet@2.yaml",
|
||||
"bug-verify-sonnet@1.yaml",
|
||||
"bug-verify-sonnet@2.yaml",
|
||||
} <= names
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", _ALL_TEMPLATES, ids=lambda p: p.name)
|
||||
def test_cp_url_is_ingress_not_in_cluster_service(path):
|
||||
for value in _cp_url_values(path):
|
||||
assert not any(m in value for m in _FORBIDDEN_CP_URL_MARKERS), (
|
||||
f"{path.name}: CP_URL={value!r} targets the in-cluster CP service; agent pods "
|
||||
"are blocked on :8100 by NetworkPolicy"
|
||||
)
|
||||
assert value == CP_URL_INGRESS, f"{path.name}: CP_URL={value!r}"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", _ALL_TEMPLATES, ids=lambda p: p.name)
|
||||
def test_no_template_mentions_in_cluster_cp_service(path):
|
||||
text = path.read_text()
|
||||
assert not any(m in text for m in _FORBIDDEN_CP_URL_MARKERS)
|
||||
|
||||
Reference in New Issue
Block a user