feat(ploeg): per-team and per-role sandbox RuntimeClass #5
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "agent/vik-555"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
VIK-555 — chart-only change, no Go changes.
What / why
The agent-sandbox executor took one global
executor.sandbox.runtimeClassName, applied to every team's and Role'sSandboxTemplate(templates/sandbox.yaml). The owner's fleet runs one team on Kata and one on gVisor (homelab RFCrfc-agent-runtime-kagent-vs-glide.md, D3), which the chart could not express. This adds per-teamexecutor.teams[].sandbox.runtimeClassNameand per-Roleplan[].roles[].sandbox.runtimeClassName, resolved field-by-field likeharness:already is:role→team→ globalexecutor.sandbox.runtimeClassName→""(noruntimeClassNamerendered).ploeg.runtimeClassNamehelper keeps the resolution in one place.values.schema.jsongains asandboxOverridedefinition onexecutor.teams[]andplan[].roles[](string-only, rejects a non-string value).values.yamldocuments placement: Kata on bare metal (own kernel, no nested-virt requirement); gVisor systrap on VMs without nested virt, accepting the file-I/O penalty on clone-heavy runs.docs/reference/configuration.mdregenerated.Evidence
CI is green on the final commit
327f548: all three pull-request workflows succeeded —checks,release-policy,tutorial-smoke(run: https://forgejo.webgrip.dev/webgrip/glide/actions/runs/89).The
checksjob runsmise run verify, whose Helm group runshelm lintplusscripts/helm-golden.sh checkand whose docs group runsdocs.py --check(includingdocs-configuration.py --check). So the real render, the goldens, the reject fixtures and the regenerated configuration reference are confirmed by CI, not asserted by hand.ci/golden/executor-sandbox-runtimeclass.yaml(fixtureci/executor-sandbox-runtimeclass-values.yaml) renders three distinctruntimeClassNamevalues:kata(global fallback),gvisor(team override),gvisor-systrap(Role override).executor-sandbox-teamgolden covers the empty-global/no-override case: noruntimeClassNameat all.ci/reject-runtimeclass-non-string-values.yaml, registered inhelm-golden.sh, provesvalues.schema.jsonrefuses a non-stringsandbox.runtimeClassName.Locally run and passed: the Ploeg verify script (
test -z "$(gofmt -l apps/ploeg)").helmand the fullmise run verifyare not available in the agent sandbox, so CI ran them instead.Risk notes for the reviewer
sandbox.runtimeClassName; that design choice is not made here and remains open.PLOEG_TEAM_PLANSwith plainjson.Unmarshal, so the extrasandboxkey now serialised into a plan Role is ignored at boot — worth re-confirming if a future change tightens that decoder.helm-golden.sh.Reference: VIK-555
This pull request was created by an AI agent (OpenHands, running as agent-builder) on behalf of the user.
builder — round 1
openhands run opened a PR for 074 · RuntimeClass per team [Ploeg verification passed]
Ploeg verification
Ploeg ran the configured checks on commit
327f5482b3b7after the agent finished.if [ -f apps/ploeg/go.mod ]; then test -z "$(gofmt -l apps/ploeg)"; fiPosted by Ploeg for the writing Run that pushed this branch.
reviewer — round 2
Chart-only per-team/per-role RuntimeClass override; all four acceptance criteria met; gofmt and docs-configuration checks pass; helm render/lint left to CI (no helm, no egress).
Verdict: approve
Reviewed
git diff development...agent/vik-555(2 commits,23f7e44+327f548) against VIK-555. Chart-only change; no Go, no agent-instruction/config files touched (none of AGENTS.md / CLAUDE.md / .claude/ / .agents/ / .openhands/ / .mcp.json / .cursorrules appear in the diff), no migrations, no release workflows.What the change does
apps/ploeg/ops/helm/ploeg/templates/_sandbox.tpl:28-42— newploeg.runtimeClassNamehelper resolving role → team → global, exactly thedefault-chain shape theharnessfields use in_helpers.tpl:110-155.apps/ploeg/ops/helm/ploeg/templates/sandbox.yaml:11-14— setspod.spec.runtimeClassNameonly when the helper returns a non-empty value (previously read the global$sb.runtimeClassNamedirectly).values.schema.json:392(team) and:765(planRole) reference a newsandboxOverridedefinition at:722-732(runtimeClassName: string,additionalProperties: false).values.yaml:199-207clarifies the global fallback and adds the Kata/gVisor placement guidance; the team example at:376-379shows the override.ci/executor-sandbox-runtimeclass-values.yaml+ci/golden/executor-sandbox-runtimeclass.yaml(render) andci/reject-runtimeclass-non-string-values.yaml(schema reject), registered inscripts/helm-golden.sh:57,77.Acceptance criteria — all met
_sandbox.tpl:39-41; schema permits bothexecutor.teams[].sandbox.runtimeClassNameandplan[].roles[].sandbox.runtimeClassName. The golden proves precedence:golden/executor-sandbox-runtimeclass.yaml:389=kata(teamkatatakes the global),:600=gvisor(team override),:773=gvisor-systrap(reviewer Role override) onploeg-worker-kata,ploeg-worker-gvisor-builder,ploeg-worker-gvisor-reviewer.""at every tier andsandbox.yaml:12guards theset. The empty-global case is already covered by the existingci/golden/executor-sandbox-team.yaml(0runtimeClassNameoccurrences; the fixture sets no global and thecopperteam no override).sandboxOverridetypes the valuestringunderadditionalProperties: false;reject-runtimeclass-non-string-values.yamlsetsruntimeClassName: 123andhelm-golden.sh:77asserts helm refuses it withruntimeClassNamein the message.values.yaml:203-206(Kata → bare metal; gVisor systrap → VMs without nested virt, file-I/O penalty on clone-heavy runs). It flows into the generateddocs/reference/configuration.md:204.Checks I ran
PLOEG_VERIFY_SCRIPT(the only configured check:gofmt -l apps/ploeg) — passed.python3 scripts/docs-configuration.py --check— passed; the hand-editedconfiguration.mdis byte-identical to what the generator produces from the changedvalues.yaml/values.schema.json(including the new### sandboxOverrideshape section and both new rows).python3 scripts/docs.py --check— partial: ADR validators (3 ledgers), the 3AGENTS.mdchecks, and repository-link resolution (376 sources / 1981 links) passed; the finalmkdocs build --strictcould not run (No module named mkdocs, and there is no network to install it). Left to CI.get.helm.shunreachable), sohelm-golden.sh checkand chart lint were not run — left to CI. As a substitute I verified the new golden structurally: after normalizing the team names, the new golden is byte-identical to the committedci/golden/executor-sandbox.yamlexcept for exactly three hunks — the two expectedruntimeClassNamevalue changes (kata→gvisorat :600,kata→gvisor-systrapat :773) and the plan'sPLOEG_TEAM_PLANSJSON gaining"sandbox":{"runtimeClassName":"gvisor-systrap"}. That whitespace/structure equality with an existing CI-generated golden is strong evidence the new one is a genuine render, not a hand-edit.Consequence I checked and cleared
The role's
sandboxkey is serialized intoPLOEG_TEAM_PLANS, so it reaches ploegd's plan parser.apps/ploeg/pkg/plan/plan.gouses plainjson.UnmarshalintoRoleand its package doc explicitly states it ignores per-role workload knobs it doesn't consume (model/image/harness, now sandbox). NoDisallowUnknownFields, so this cannot stop ploegd at boot and needs no Go change.Non-blocking notes (no action required)
apps/ploeg/docs/contracts/executor.md:116still reads "the RuntimeClass named inexecutor.sandbox.runtimeClassNamewhen one is set". With overrides this is now incomplete — a deployment can set per-team/role RuntimeClasses while the global is empty, so the prerequisite is any RuntimeClass reachable through the chain. A one-line update would keep the contract honest; the Work Item only asked for the values comment, so I am not blocking on it.runtimeClassName. The Work Item explicitly defers this ("Escalate if the keda executor path should also honour the key, since that is a design choice this ticket does not make"), so it is not a defect — but a human should know the builder recorded no escalation decision, and the consuming homelab enablement ticket must confirm its target node/executor combination.scripts/helm-golden.shis edited (a test runner), which the ticket's "Protected" line mentions not editing; the edit only appends two new case registrations and leaves every existing case untouched. That is the required mechanism for the Verification's "Add chart render tests under …/ci/", so I treat it as in scope._sandbox.tpldoc comment is prose; rootAGENTS.mdsays source comments are limited to machine directives/exported API docs. It matches the established convention of the surrounding Helm templates, so I would not change it.Posted by Ploeg on behalf of the reviewing agent. It could not push to this branch.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.