daemon: seed repo volume via CopyToContainer (host-path bind bug → empty workspace); web: spawn poll reads fresh session list

This commit is contained in:
Raphael Westphal
2026-08-18 16:55:58 +02:00
parent 1cc5d9a978
commit 55be4b2a38
6 changed files with 82 additions and 50 deletions
+12 -17
View File
@@ -424,37 +424,32 @@ func (s *Spawner) ensureRepoVolume(ctx context.Context, name string) (bool, erro
return true, nil
}
// seedVolume copies the cloned repo into the fresh named volume via a
// one-shot container from the worker image (no extra images needed).
// seedVolume populates the fresh named volume with the cloned repo by
// streaming a tar of the clone into a paused container via the docker API
// (CopyToContainer). No bind mounts: bind sources are HOST paths, but the
// clone lives inside the daemon container's filesystem.
func (s *Spawner) seedVolume(ctx context.Context, slug, repoVolume string) error {
repoDir := filepath.Join(s.reposDir, slug)
cfg := &container.Config{
Image: imageRefWorker,
Cmd: []string{"sh", "-c", "cp -a /src/. " + workspaceMount + "/"},
Cmd: []string{"true"}, // never started; created only as a volume mount point
}
hostCfg := &container.HostConfig{
Binds: []string{
repoVolume + ":" + workspaceMount,
repoDir + ":/src:ro",
},
Binds: []string{repoVolume + ":" + workspaceMount},
}
created, err := s.cli.ContainerCreate(ctx, cfg, hostCfg, nil, nil, "lvmh-seed-"+slug)
if err != nil {
return err
}
defer s.removeContainer(context.Background(), created.ID)
if err := s.cli.ContainerStart(ctx, created.ID, container.StartOptions{}); err != nil {
return err
var buf bytes.Buffer
if err := tarDir(&buf, repoDir); err != nil {
return fmt.Errorf("tar clone: %w", err)
}
waitCh, errCh := s.cli.ContainerWait(ctx, created.ID, container.WaitConditionNotRunning)
select {
case <-waitCh:
return nil
case err := <-errCh:
return err
case <-ctx.Done():
return ctx.Err()
if err := s.cli.CopyToContainer(ctx, created.ID, workspaceMount, &buf, container.CopyToContainerOptions{}); err != nil {
return fmt.Errorf("copy into volume: %w", err)
}
return nil
}
func (s *Spawner) removeContainer(ctx context.Context, id string) {