feat(tasks): add hogland sandbox runtime#60042
Draft
webjunkie wants to merge 2 commits into
Draft
Conversation
Add hogland as an additional sandbox option behind a new `sandbox_runtime` opt-in field on the run-create requests. Field absent or null routes through the existing path; "posthog" routes to the new HoglandSandbox adapter backed by the posthog-hogland SDK. Auth helpers fetch the bearer and host at call time so swapping to EKS OIDC + TrustMapping later is a one-line change inside `_get_hog_token` / `_get_hog_host`, no integration-site refactor. Prepared and not yet ready to merge — waiting on the posthog-hogland SDK PyPI release. Wheel is ad-hoc installable for testing today.
Contributor
|
🎭 Playwright didn't run on this PR — your changes touch code that could affect E2E behavior, but Playwright is opt-in via label now to keep CI cost down. Add the Most PRs don't need this. Real regressions still get caught on master and fix-forward. |
Contributor
|
Size Change: 0 B Total Size: 80 MB ℹ️ View Unchanged
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Tasks needs an additional sandbox runtime option so downstream clients of PostHog Code/AI can opt into a different backend per run. This PR adds hogland as an additional sandbox option, plumbed end-to-end but kept neutral on the public surface so the runtime name doesn't lock us into a vendor.
Status: prepared, not yet ready to merge — waiting on the
posthog-hoglandSDK PyPI release. The wheel is ad-hoc installable today for local testing (uv pip install /path/to/posthog_hogland-0.1.0-py3-none-any.whl).Changes
Public surface. Optional
sandbox_runtimefield onTaskRunCreateRequestSerializerandTaskRunBootstrapCreateRequestSerializer. Only value accepted today is"posthog"; absent / null keeps current behaviour. Wired throughRunState, persisted inTaskRun.state, propagated onresume_from_run_id.Selection.
provision_sandbox.create_sandbox_for_repositorybranches onctx.sandbox_runtime:"posthog"→get_sandbox_class_for_backend("hogland"), else the existing default. Mapping from public runtime name to internal backend string is local to that activity — no name leakage elsewhere.Adapter. New
products/tasks/backend/services/hogland_sandbox.pyimplementingSandboxBaseon top of theposthog-hoglandSDK. Same lifecycle / exception types / agent-server port (8080) as the existing implementation. Reuseswait_for_health_check,build_agent_runtime_env_prefix,redact_sandbox_commandfor parity.Auth. Lazy credential helpers (
_get_hog_token,_get_hog_host) fetch token + host at call time. Today:HOG_TOKENenv, fallback to projected K8s SA token at/var/run/secrets/kubernetes.io/serviceaccount/token. When EKS OIDC + TrustMapping lands hogland-side, swap is a one-line change inside_get_hog_tokenwith no integration-site refactor. Host comes from newsettings.HOGLAND_API_URL(env varHOGLAND_API_URL) — single source of truth, so moving the endpoint between playground / prod / regional EU is a config change.Snapshot-delete gate. Extended the existing
MODAL_TOKEN_*check inSandboxSnapshot.deleteto also acceptHOG_TOKEN, so a deploy running on hogland credentials doesn't silently skip cleanup.How did you test this code?
Agent-authored; no manual UI testing. Verified end-to-end via Django shell:
posthog-hogland0.1.0 wheel installs and imports cleanlyTaskRunCreateRequestSerializeracceptssandbox_runtime="posthog", rejects"modal"and other stringsRunState.sandbox_runtimeparses from a state dictget_sandbox_class_for_backend("hogland")resolves toHoglandSandboxHoglandSandboxhas no abstract methods left (fullSandboxBaseimplementation)_get_hog_token()and_get_hog_host()resolve via env at call timeruff checkclean across all touched filesNo new tests added in this pass — adapter tests will mock
httpxviarespxonce the SDK is on PyPI and the infra side (EKS pod SA, TrustMapping) lands. Mocking the HTTP wire layer rather than the credential shape so the same tests keep working when OIDC swaps in.Publish to changelog?
no
Docs update
No user-facing surface yet — documentation will land alongside the GA flip.
🤖 Agent context
Authored by Claude Code (Opus 4.7) in collaboration with @webjunkie.
Decisions worth flagging:
Field shape:
None | "posthog"not symmetric enum. Considered explicit"posthog" | "external"and version-stylev1 / v2. Settled on a single opt-in value: absent / null means current behaviour,"posthog"is the only opt-in. No backfill, no name leakage, no third-party label exposed to the API surface. Asymmetry is intentional — if the default ever flips, callers re-route silently (acceptable for managed defaults; if pinning ever matters we can materialize the resolved runtime onto the row at provision time).State, not model field.
sandbox_runtimeis a per-run choice, parallel toruntime_adapter,model,reasoning_effort,interaction_origin. Lives inTaskRun.state, no Django migration.Credential fetching at call time, not module load. Following hogland infra notes — the seam is
_get_hog_token/_get_hog_host. OIDC swap touches one function. Tests are expected to mock the wire layer, not assert anything about token shape, so the same tests keep working as the credential format evolves.Host setting in temporal.py. Slots next to
SANDBOX_API_URL/SANDBOX_MCP_URLfor symmetry. Region routing layers on top later via a smallREGIONAL_HOSTSmap if needed.Non-code follow-ups for infra (called out so they don't get lost):
serviceAccountName(e.g.posthog-sandboxes) rather than the cluster default before TrustMapping can resolve identity.audiencesvalue matching whatever hogland configures.HOG_TOKEN(orHOGLAND_API_URL+ SA token) needs to be present on whichever deploys we want to exposesandbox_runtime="posthog"to.