molecule-core/workspace-server/internal/provisioner
Hongming Wang 552602e462 fix(provisioner): force re-pull of moving image tags on workspace start
Previously Start() only pulled when the image was missing locally
(imgErr != nil). Once a tenant's Docker daemon had `:latest` cached,
it stuck on that snapshot forever even after publish-runtime pushed
a newer image with the same tag — the same image-cache class that
sibling task #232 closed on the controlplane redeploy path.

Now Start() additionally re-pulls when the tag is "moving"
(`:latest`, no tag, `:staging`, `:main`, `:dev`, `:edge`, `:nightly`,
`:rolling`). Pinned tags (semver, sha-prefixed, date-stamped, build-id)
and digest-pinned references (`@sha256:...`) skip the pull because
their contents are by definition immutable.

The classifier (imageTagIsMoving) is deliberately conservative on the
"moving" side — only the well-known moving tags trip it. Misclassifying
a pinned tag as moving wastes bandwidth on every provision; misclassifying
moving as pinned silently bricks the fleet on stale snapshots, which
is exactly the bug class this fix closes.

Edge cases handled:
- Registry hostname with port (`localhost:5000/foo`) — the `:5000` is
  not mistaken for a tag.
- Digest pinning (`image@sha256:...`) — never re-pulled even if a
  moving-looking tag is also present.
- Legacy local-build tags (`workspace-template:hermes`) — treated as
  pinned (no registry to move from).

Test coverage: 22 cases across all classifier shapes. No changes to
the pull-failure path (still best-effort, ContainerCreate still
surfaces the actionable "image not found" error if the pull failed
and the cache is also empty).

Task: #215. Companion to #232.
2026-05-02 23:56:32 -07:00
..
architecture_test.go test(arch): codify 4 module boundaries as architecture tests (#2344) 2026-04-29 22:12:58 -07:00
backend_contract_test.go refactor(handlers): widen WorkspaceHandler.provisioner to LocalProvisionerAPI interface (#2369) 2026-04-30 09:18:16 -07:00
cp_provisioner_instance_id_test.go test: regression guard for #1738 — cp-provisioner uses real instance_id 2026-04-23 17:45:13 -07:00
cp_provisioner_test.go fix(cp-provisioner): surface CP non-2xx on Stop to plug EC2 leak 2026-05-01 22:59:01 -07:00
cp_provisioner.go fix(cp-provisioner): surface CP non-2xx on Stop to plug EC2 leak 2026-05-01 22:59:01 -07:00
isrunning_test.go fix(provisioner): treat "removal already in progress" as no-op success 2026-04-27 13:25:32 -07:00
local_provisioner_api.go refactor(handlers): widen WorkspaceHandler.provisioner to LocalProvisionerAPI interface (#2369) 2026-04-30 09:18:16 -07:00
platform_test.go fix(provisioner): force linux/amd64 pull + create on Apple Silicon hosts (#1875) 2026-04-23 14:55:34 -07:00
provisioner_test.go fix(provisioner): force re-pull of moving image tags on workspace start 2026-05-02 23:56:32 -07:00
provisioner.go fix(provisioner): force re-pull of moving image tags on workspace start 2026-05-02 23:56:32 -07:00