Skip to content

Commit 22b2158

Browse files
authored
Fix macOS panic by pulling images before determining workspace creator (#522)
I introduced this when re-organizing the code in `batch_common.go`, but I didn't run into this because I've only developed on Linux since. On macOS, though, `src` would panic when the `DockerVolumeWorkspaceCreator` would check the `ImageUIDGUID` on each step, because `step.image` was nil. This fixes the issue by making sure that all images are pulled before inspecting them. As a requirement to the change it also pulls out the pulling of the workspace creator image, which I think is actually an improvement because it makes the code less decoupled. Guess I should switch between macOS and Linux more often.
1 parent 11a874e commit 22b2158

File tree

2 files changed

+29
-20
lines changed

2 files changed

+29
-20
lines changed

cmd/src/batch_common.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,24 +234,30 @@ func executeBatchSpec(ctx context.Context, opts executeBatchSpecOpts) error {
234234
}
235235
batchCompletePending(pending, "Resolving namespace")
236236

237-
pending = batchCreatePending(opts.out, "Determining workspace type")
238-
workspaceCreator := workspace.NewCreator(ctx, opts.flags.workspace, opts.flags.cacheDir, opts.flags.tempDir, batchSpec.Steps)
239-
pending.VerboseLine(output.Linef("🚧", output.StyleSuccess, "Workspace creator: %T", workspaceCreator))
240-
batchCompletePending(pending, "Set workspace type")
241-
242-
loadWorkspaceImage := workspaceCreator.Type() == workspace.CreatorTypeVolume
243237
imageProgress := opts.out.Progress([]output.ProgressBar{{
244238
Label: "Preparing container images",
245239
Max: 1.0,
246240
}}, nil)
247-
err = svc.SetDockerImages(ctx, batchSpec, loadWorkspaceImage, func(perc float64) {
241+
err = svc.SetDockerImages(ctx, batchSpec, func(perc float64) {
248242
imageProgress.SetValue(0, perc)
249243
})
250244
if err != nil {
251245
return err
252246
}
253247
imageProgress.Complete()
254248

249+
pending = batchCreatePending(opts.out, "Determining workspace type")
250+
workspaceCreator := workspace.NewCreator(ctx, opts.flags.workspace, opts.flags.cacheDir, opts.flags.tempDir, batchSpec.Steps)
251+
if workspaceCreator.Type() == workspace.CreatorTypeVolume {
252+
_, err = svc.EnsureImage(ctx, workspace.DockerVolumeWorkspaceImage)
253+
if err != nil {
254+
return err
255+
}
256+
}
257+
258+
pending.VerboseLine(output.Linef("🚧", output.StyleSuccess, "Workspace creator: %T", workspaceCreator))
259+
batchCompletePending(pending, "Set workspace type")
260+
255261
pending = batchCreatePending(opts.out, "Resolving repositories")
256262
repos, err := svc.ResolveRepositories(ctx, batchSpec)
257263
if err != nil {

internal/batches/service/service.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"github.com/sourcegraph/src-cli/internal/batches/docker"
2222
"github.com/sourcegraph/src-cli/internal/batches/executor"
2323
"github.com/sourcegraph/src-cli/internal/batches/graphql"
24-
"github.com/sourcegraph/src-cli/internal/batches/workspace"
2524
)
2625

2726
type Service struct {
@@ -155,32 +154,36 @@ func (svc *Service) CreateChangesetSpec(ctx context.Context, spec *batches.Chang
155154
//
156155
// Progress information is reported back to the given progress function: perc
157156
// will be a value between 0.0 and 1.0, inclusive.
158-
func (svc *Service) SetDockerImages(ctx context.Context, spec *batches.BatchSpec, loadWorkspaceImage bool, progress func(perc float64)) error {
157+
func (svc *Service) SetDockerImages(ctx context.Context, spec *batches.BatchSpec, progress func(perc float64)) error {
159158
total := len(spec.Steps) + 1
160159
progress(0)
161160

162161
// TODO: this _really_ should be parallelised, since the image cache takes
163162
// care to only pull the same image once.
164163
for i := range spec.Steps {
165-
spec.Steps[i].SetImage(svc.imageCache.Get(spec.Steps[i].Container))
166-
if err := spec.Steps[i].EnsureImage(ctx); err != nil {
167-
return errors.Wrapf(err, "pulling image %q", spec.Steps[i].Container)
164+
img, err := svc.EnsureImage(ctx, spec.Steps[i].Container)
165+
if err != nil {
166+
return err
168167
}
169-
progress(float64(i) / float64(total))
170-
}
168+
spec.Steps[i].SetImage(img)
171169

172-
// We also need to ensure we have our own utility images available, if
173-
// necessary.
174-
if loadWorkspaceImage {
175-
if err := svc.imageCache.Get(workspace.DockerVolumeWorkspaceImage).Ensure(ctx); err != nil {
176-
return errors.Wrapf(err, "pulling image %q", workspace.DockerVolumeWorkspaceImage)
177-
}
170+
progress(float64(i) / float64(total))
178171
}
179172

180173
progress(1)
181174
return nil
182175
}
183176

177+
func (svc *Service) EnsureImage(ctx context.Context, name string) (docker.Image, error) {
178+
img := svc.imageCache.Get(name)
179+
180+
if err := img.Ensure(ctx); err != nil {
181+
return nil, errors.Wrapf(err, "pulling image %q", name)
182+
}
183+
184+
return img, nil
185+
}
186+
184187
func (svc *Service) BuildTasks(ctx context.Context, repos []*graphql.Repository, spec *batches.BatchSpec) ([]*executor.Task, error) {
185188
workspaceConfigs := []batches.WorkspaceConfiguration{}
186189
for _, conf := range spec.Workspaces {

0 commit comments

Comments
 (0)