Skip to content

feat(api): add refresh-envd endpoint to rebuild a template with current envd - #3624

Open
AdaAibaby wants to merge 1 commit into
e2b-dev:mainfrom
AdaAibaby:feat/template-refresh-envd-endpoint
Open

feat(api): add refresh-envd endpoint to rebuild a template with current envd#3624
AdaAibaby wants to merge 1 commit into
e2b-dev:mainfrom
AdaAibaby:feat/template-refresh-envd-endpoint

Conversation

@AdaAibaby

@AdaAibaby AdaAibaby commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Old templates bake an old envd into their final snapshot, so a sandbox started from one resumes the old envd out of snapshot RAM. That blocks features gated on newer envd — e.g. volume mounts need envd ≥ 0.5.14. Neither existing no-rebuild upgrade path can lift such a template:

  • Live upgrade (envd-upgrade-target) is gated at MinEnvdVersionForUpgrade = 0.6.12 (sandboxes.go:1752) — old templates are far below it.
  • Offline upgrade (envd-offline-upgrade-target) only runs on the cold-boot / filesystem-only path (reboot.go:61, decideOfflineSwap), but a plain Sandbox.create from a memory-snapshot template goes through ResumeSandbox (sandboxes.go:314), never RebootSandbox, so the offline pre-boot swap is not on that path.

So the only way to get a newer envd into an old template is to rebuild. Users have been doing this by hand against the raw API, which has two footguns:

  • RegisterBuild defaults omitted specs to 2 vCPU / 1024 MiB, silently shrinking the template.
  • Registering under a fresh template id orphans the alias.

Change

Adds POST /v2/templates/{templateID}/refresh-envd. It derives a new build FROM the template's own latest ready build with a single trivial RUN ["true"] step. A FROM TEMPLATE base layer is always cached, and a cached source layer is exactly what sets UpdateEnvd=true in the step phase (packages/orchestrator/pkg/template/build/phases/steps/builder.go:235), which swaps in the host's current envd binary (layer_executor.go:165 updateEnvdInSandbox).

The endpoint:

  • collapses the register + start sequence into one call;
  • inherits the source build's cpu/ram and alias in-place (same templateID, default tag superseded) — fixing both footguns above;
  • returns {templateID, buildID, fromEnvdVersion, aliases}; the caller polls the existing /builds/{buildID}/status and /logs endpoints.

Self-referencing fromTemplate is safe: it resolves via GetTemplateWithBuildByTag which filters status_group = 'ready' (get_template_with_build_by_tag.sql.go:24), so it picks the old ready build, never the just-registered waiting one.

Files

  • spec/openapi.yml — new path + TemplateRefreshEnvdResponse schema.
  • packages/api/internal/api/api.gen.go — regenerated via go generate (oapi-codegen).
  • packages/api/internal/handlers/template_refresh_envd.go — handler; decision logic extracted into a pure buildRefreshEnvdPlan.
  • packages/api/internal/handlers/template_refresh_envd_test.go — unit tests for the plan.

No DB migration, no proto change, no orchestrator change.

Why this is not a duplicate

  • gh pr list --state open --search "refresh-envd" / "refresh envd" / "envd rebuild template" — no matching PR (only a fuzzy hit on an unrelated log-routing PR).

Tests run

  • go test ./internal/handlers/ -run TestBuildRefreshEnvdPlan — PASS (success inherits cpu/ram/alias + emits fromTemplate=self and the no-op RUN step; no-ready-build → 400; missing specs → 400; no-alias/no-envd-version fallbacks). Cross-team → 404 is enforced upstream by GetTeamTemplate's team-scoped query and noted in the handler doc.
  • go build ./... (api) — OK.
  • go vet ./internal/handlers/ — OK.
  • gofmt -l on changed files — clean.

Not run: a full end-to-end build through template-manager — this dev host has no complete builder stack. Correctness of the build-phase behavior rests on the code path traced above plus a manual reproduction of the same FROM TEMPLATE + no-op-step + cached-source-layer flow that the endpoint automates.

Companion CLI PR

The user-facing entry point e2b template rebuild --refresh-envd lives in the e2b-dev SDK/CLI: e2b-dev/E2B#1818. This API change is the server half; the CLI PR is the client half.

AI assistance

AI assistance was used to trace the resume/reboot and build-phase call chains, design the endpoint, and draft the code and tests. A human submitter has reviewed every changed line.

…nt envd

Templates bake the envd version into their final snapshot, so a sandbox
started from an old template resumes the old envd from snapshot RAM. Neither
the live-upgrade (gated at envd >= 0.6.12) nor the offline-upgrade (cold-boot /
filesystem-only only) path can lift a plain memory-snapshot template, so the
only way to get a newer envd -- e.g. the >= 0.5.14 needed for volume mounts --
is to rebuild.

Add POST /v2/templates/{templateID}/refresh-envd. It derives a new build FROM
the template's own latest ready build with one trivial RUN step: a FROM TEMPLATE
base layer is always cached, and a cached source layer drives UpdateEnvd=true in
the step phase (phases/steps/builder.go), which swaps in the host envd binary.

The endpoint collapses the register + start dance into one call and inherits the
source build's specs and alias in-place, fixing the two footguns of doing it by
hand against the raw API: RegisterBuild otherwise defaults omitted specs to
2 vCPU / 1024 MiB, and a fresh template id would orphan the alias.

Decision logic is extracted into a pure buildRefreshEnvdPlan and unit-tested
(no ready build -> 400, missing specs -> 400, success inherits cpu/ram/alias and
emits fromTemplate=self + the no-op RUN step). Cross-team access is enforced
upstream by GetTeamTemplate's team-scoped query (no row -> 404).

Companion CLI change (e2b template rebuild --refresh-envd) in the e2b-dev SDK.

Signed-off-by: AdaAibaby <shaolila@buaa.edu.cn>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants