Files
kandev/apps/backend/internal/agent/lifecycle/env_preparer_docker.go
T
José Almeida 948743600e refactor(cleanup): drop dead code, dedupe predicates, unify token injection
Tier 1 of the post-review cleanup. Each item is independently safe; bundling
because they're all small, mechanical, and lint-passing.

- fix(clone): unify injectTokenIntoURL across Docker and Sprites — Sprites
  used to ignore GH_TOKEN entirely (a user with only GH_TOKEN set got 401
  on Sprites clone but worked on Docker). Promote one
  `injectGitHubTokenIntoCloneURL` helper, accept both env vars
  (GITHUB_TOKEN wins, matching Docker), and use the documented
  `https://x-access-token:T@github.com/` form on both surfaces.
- fix(executor-popover): swap the <span tabIndex role="button"> trigger
  for <Button variant="ghost"> so Enter/Space activation, focus rings on
  Safari, and disabled semantics come for free.
- test(docker): rewrite TestDockerStopInstance_PreservesSessionDirOnPlainStop
  to drive the real DockerExecutor.StopInstance path with ContainerID=""
  (skips the docker daemon, exercises the kandev-side cleanup branch).
  Previous version only iterated shouldRunExecutorCleanup strings — would
  pass even if StopInstance always cleaned up. Now table-driven over
  preserve+destructive reasons with on-disk asserts.
- refactor(orchestrator): drop dead `_ = arg` parameters from persist*
  helpers (persistResumeState, persistModelSwitchState, persistLaunchState).
  Brings signatures from 9→6 args, under the funlen lint cap.
- refactor(orchestrator): collapse byte-identical isContainerizedExecutor
  ≡ isCloneBasedExecutorType predicate into one.
- refactor(lifecycle): drop dead getMetadataBool, FileUploader.RunCommand,
  expandMountSource {home} arm (no production agent ships {home} in
  Mounts; codex_acp_test asserts it), dockerTaskBranch one-line wrapper.
2026-05-07 00:29:12 +01:00

65 lines
2.0 KiB
Go

package lifecycle
import (
"context"
"time"
"go.uber.org/zap"
"github.com/kandev/kandev/internal/common/logger"
"github.com/kandev/kandev/internal/worktree"
)
// DockerPreparer prepares a Docker-based execution environment.
// Steps: validate Docker → pull/build image (if needed).
type DockerPreparer struct {
logger *logger.Logger
}
// NewDockerPreparer creates a new DockerPreparer.
func NewDockerPreparer(log *logger.Logger) *DockerPreparer {
return &DockerPreparer{
logger: log.WithFields(zap.String("component", "docker-preparer")),
}
}
func (p *DockerPreparer) Name() string { return "docker" }
func (p *DockerPreparer) Prepare(ctx context.Context, req *EnvPrepareRequest, onProgress PrepareProgressCallback) (*EnvPrepareResult, error) {
start := time.Now()
var steps []PrepareStep
// Step 1: Validate Docker availability
step := beginStep("Validate Docker")
reportProgress(onProgress, step, 0, 1)
completeStepSuccess(&step)
steps = append(steps, step)
reportProgress(onProgress, step, 0, 1)
return &EnvPrepareResult{
Success: true,
Steps: steps,
WorkspacePath: req.WorkspacePath,
Duration: time.Since(start),
WorktreeBranch: nonWorktreeTaskBranch(req),
}, nil
}
// nonWorktreeTaskBranch resolves the kandev-managed feature branch for executors
// that don't go through the host-side worktree path (Docker, Sprites). On a
// fresh launch it generates a deterministic branch name from the task title +
// task ID prefix so the same task always lands on the same branch even when
// the env row was created before this fix and didn't persist a name. On resume
// the orchestrator carries the previously-generated branch back via
// req.WorktreeBranch and we keep it as-is.
func nonWorktreeTaskBranch(req *EnvPrepareRequest) string {
if req.WorktreeBranch != "" {
return req.WorktreeBranch
}
suffix := req.TaskID
if len(suffix) > 6 {
suffix = suffix[:6]
}
return worktree.TaskBranchNameWithSuffix(req.TaskTitle, req.TaskID, req.WorktreeBranchPrefix, suffix)
}