Skip to content

Commit ad1b36a

Browse files
authored
batches: Remote Mount #5 - src-cli (#816)
1 parent 4e07d07 commit ad1b36a

19 files changed

Lines changed: 930 additions & 153 deletions

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ All notable changes to `src-cli` are documented in this file.
1313

1414
### Added
1515

16+
- Mounting files now works when running batch changes server side. [sourcegraph/src-cli#816](https://github.com/sourcegraph/src-cli/pull/816)
17+
1618
### Changed
1719

1820
### Fixed
@@ -857,4 +859,4 @@ Re-release of 3.29.3 for Sourcegraph 3.30.
857859
### Changed
858860

859861
- The terminal UI has been replaced by the logger-based UI that was previously only visible in verbose-mode (`-v`). [#228](https://github.com/sourcegraph/src-cli/pull/228)
860-
- Deprecated the `-endpoint` flag. Instead, use the `SRC_ENDPOINT` environment variable. [#235](https://github.com/sourcegraph/src-cli/pull/235)
862+
- Deprecated the `-endpoint` flag. Instead, use the `SRC_ENDPOINT` environment variable. [#235](https://github.com/sourcegraph/src-cli/pull/235)

cmd/src/batch_common.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ func executeBatchSpec(ctx context.Context, ui ui.ExecUI, opts executeBatchSpecOp
304304

305305
// Parse flags and build up our service and executor options.
306306
ui.ParsingBatchSpec()
307-
batchSpec, rawSpec, err := parseBatchSpec(ctx, opts.file, svc, false)
307+
batchSpec, batchSpecDir, rawSpec, err := parseBatchSpec(ctx, opts.file, svc)
308308
if err != nil {
309309
var multiErr errors.MultiError
310310
if errors.As(err, &multiErr) {
@@ -378,15 +378,14 @@ func executeBatchSpec(ctx context.Context, ui ui.ExecUI, opts executeBatchSpecOp
378378
Creator: workspaceCreator,
379379
EnsureImage: imageCache.Ensure,
380380
Parallelism: parallelism,
381+
WorkingDirectory: batchSpecDir,
381382
Timeout: opts.flags.timeout,
382383
TempDir: opts.flags.tempDir,
383384
GlobalEnv: os.Environ(),
384-
IsRemote: false,
385385
},
386386
Logger: logManager,
387387
Cache: executor.NewDiskCache(opts.flags.cacheDir),
388388
GlobalEnv: os.Environ(),
389-
IsRemote: false,
390389
},
391390
)
392391

@@ -508,13 +507,10 @@ func setReadDeadlineOnCancel(ctx context.Context, f *os.File) {
508507

509508
// parseBatchSpec parses and validates the given batch spec. If the spec has
510509
// validation errors, they are returned.
511-
//
512-
// isRemote argument is a temporary argument used to determine if the batch spec is being parsed for remote
513-
// (server-side) processing. Remote processing does not support mounts yet.
514-
func parseBatchSpec(ctx context.Context, file string, svc *service.Service, isRemote bool) (*batcheslib.BatchSpec, string, error) {
510+
func parseBatchSpec(ctx context.Context, file string, svc *service.Service) (*batcheslib.BatchSpec, string, string, error) {
515511
f, err := batchOpenFileFlag(file)
516512
if err != nil {
517-
return nil, "", err
513+
return nil, "", "", err
518514
}
519515
defer f.Close()
520516

@@ -526,26 +522,35 @@ func parseBatchSpec(ctx context.Context, file string, svc *service.Service, isRe
526522

527523
data, err := io.ReadAll(f)
528524
if err != nil {
529-
return nil, "", errors.Wrap(err, "reading batch spec")
525+
return nil, "", "", errors.Wrap(err, "reading batch spec")
530526
}
531527

528+
dir, err := getBatchSpecDirectory(file)
529+
if err != nil {
530+
return nil, "", "", errors.Wrap(err, "batch spec path")
531+
}
532+
533+
spec, err := svc.ParseBatchSpec(dir, data)
534+
return spec, dir, string(data), err
535+
}
536+
537+
func getBatchSpecDirectory(file string) (string, error) {
532538
var workingDirectory string
539+
var err error
533540
// if the batch spec is being provided via standard input, set the working directory to the current directory
534541
if file == "" || file == "-" {
535542
workingDirectory, err = os.Getwd()
536543
if err != nil {
537-
return nil, "", errors.Wrap(err, "batch spec path")
544+
return "", errors.Wrap(err, "batch spec path")
538545
}
539546
} else {
540547
p, err := filepath.Abs(file)
541548
if err != nil {
542-
return nil, "", errors.Wrap(err, "batch spec path")
549+
return "", errors.Wrap(err, "batch spec path")
543550
}
544551
workingDirectory = filepath.Dir(p)
545552
}
546-
547-
spec, err := svc.ParseBatchSpec(workingDirectory, data, isRemote)
548-
return spec, string(data), err
553+
return workingDirectory, nil
549554
}
550555

551556
func checkExecutable(cmd string, args ...string) error {

cmd/src/batch_exec.go

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@ import (
1010
"path/filepath"
1111
"time"
1212

13+
"github.com/sourcegraph/src-cli/internal/batches/docker"
14+
"github.com/sourcegraph/src-cli/internal/batches/log"
15+
"github.com/sourcegraph/src-cli/internal/batches/repozip"
16+
"github.com/sourcegraph/src-cli/internal/batches/workspace"
17+
1318
"github.com/sourcegraph/sourcegraph/lib/errors"
1419

15-
"github.com/sourcegraph/src-cli/internal/batches/docker"
1620
"github.com/sourcegraph/src-cli/internal/batches/executor"
1721
"github.com/sourcegraph/src-cli/internal/batches/graphql"
18-
"github.com/sourcegraph/src-cli/internal/batches/log"
19-
"github.com/sourcegraph/src-cli/internal/batches/repozip"
2022
"github.com/sourcegraph/src-cli/internal/batches/service"
2123
"github.com/sourcegraph/src-cli/internal/batches/ui"
22-
"github.com/sourcegraph/src-cli/internal/batches/workspace"
2324
"github.com/sourcegraph/src-cli/internal/cmderrors"
2425

2526
batcheslib "github.com/sourcegraph/sourcegraph/lib/batches"
@@ -30,10 +31,11 @@ const (
3031
)
3132

3233
type executorModeFlags struct {
33-
timeout time.Duration
34-
file string
35-
tempDir string
36-
repoDir string
34+
timeout time.Duration
35+
file string
36+
tempDir string
37+
repoDir string
38+
workspaceFilesDir string
3739
}
3840

3941
func newExecutorModeFlags(flagSet *flag.FlagSet) (f *executorModeFlags) {
@@ -42,6 +44,7 @@ func newExecutorModeFlags(flagSet *flag.FlagSet) (f *executorModeFlags) {
4244
flagSet.StringVar(&f.file, "f", "", "The workspace execution input file to read.")
4345
flagSet.StringVar(&f.tempDir, "tmp", "", "Directory for storing temporary data.")
4446
flagSet.StringVar(&f.repoDir, "repo", "", "Path of the checked out repo on disk.")
47+
flagSet.StringVar(&f.workspaceFilesDir, "workspaceFiles", "", "Path of workspace files on disk.")
4548

4649
return f
4750
}
@@ -69,7 +72,7 @@ github.com/sourcegraph/sourcegraph/lib/batches.
6972
7073
Usage:
7174
72-
src batch exec -f FILE -repo DIR [command options]
75+
src batch exec -f FILE -repo DIR -workspaceFiles DIR [command options]
7376
7477
Examples:
7578
@@ -140,6 +143,12 @@ func executeBatchSpecInWorkspaces(ctx context.Context, flags *executorModeFlags)
140143
}
141144
}
142145

146+
// Grab the absolute path to the workspace files contents.
147+
workspaceFilesDir, err := filepath.Abs(flags.workspaceFilesDir)
148+
if err != nil {
149+
return errors.Wrap(err, "getting absolute path for workspace files dir")
150+
}
151+
143152
// Test if git is available.
144153
if err := checkExecutable("git", "version"); err != nil {
145154
return err
@@ -177,8 +186,7 @@ func executeBatchSpecInWorkspaces(ctx context.Context, flags *executorModeFlags)
177186
ui.PreparingContainerImagesSuccess()
178187

179188
// Empty for now until we support secrets or env var settings in SSBC.
180-
globalEnv := []string{}
181-
isRemote := true
189+
var globalEnv []string
182190

183191
// Set up the execution UI.
184192
taskExecUI := ui.ExecutingTasks(false, 1)
@@ -191,19 +199,18 @@ func executeBatchSpecInWorkspaces(ctx context.Context, flags *executorModeFlags)
191199
EnsureImage: imageCache.Ensure,
192200
Task: task,
193201
// TODO: Should be slightly less than the executor timeout. Can we somehow read that?
194-
Timeout: flags.timeout,
195-
TempDir: tempDir,
196-
GlobalEnv: globalEnv,
197-
// Temporarily prevent the ability to sending a batch spec with a mount for server-side processing.
198-
IsRemote: isRemote,
199-
RepoArchive: &repozip.NoopArchive{},
200-
UI: taskExecUI.StepsExecutionUI(task),
202+
Timeout: flags.timeout,
203+
TempDir: tempDir,
204+
WorkingDirectory: workspaceFilesDir,
205+
GlobalEnv: globalEnv,
206+
RepoArchive: &repozip.NoopArchive{},
207+
UI: taskExecUI.StepsExecutionUI(task),
201208
}
202209
results, err := executor.RunSteps(ctx, opts)
203210

204211
// Write all step cache results for all results.
205212
for _, stepRes := range results {
206-
cacheKey := task.CacheKey(globalEnv, isRemote, stepRes.StepIndex)
213+
cacheKey := task.CacheKey(globalEnv, workspaceFilesDir, stepRes.StepIndex)
207214
k, err := cacheKey.Key()
208215
if err != nil {
209216
return errors.Wrap(err, "calculating step cache key")

cmd/src/batch_remote.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Examples:
6363
// may as well validate it at the same time so we don't even have to go to
6464
// the backend if it's invalid.
6565
ui.ParsingBatchSpec()
66-
spec, raw, err := parseBatchSpec(ctx, file, svc, true)
66+
spec, batchSpecDir, raw, err := parseBatchSpec(ctx, file, svc)
6767
if err != nil {
6868
ui.ParsingBatchSpecFailure(err)
6969
return err
@@ -100,6 +100,21 @@ Examples:
100100
}
101101
ui.SendingBatchSpecSuccess()
102102

103+
hasWorkspaceFiles := false
104+
for _, step := range spec.Steps {
105+
if len(step.Mount) > 0 {
106+
hasWorkspaceFiles = true
107+
break
108+
}
109+
}
110+
if hasWorkspaceFiles {
111+
ui.UploadingWorkspaceFiles()
112+
if err = svc.UploadBatchSpecWorkspaceFiles(ctx, batchSpecDir, batchSpecID, spec.Steps); err != nil {
113+
return err
114+
}
115+
ui.UploadingWorkspaceFilesSuccess()
116+
}
117+
103118
// Wait for the workspaces to be resolved.
104119
ui.ResolvingWorkspaces()
105120
ticker := time.NewTicker(1 * time.Second)

cmd/src/batch_repositories.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Examples:
7474
}
7575

7676
out := output.NewOutput(flagSet.Output(), output.OutputOpts{Verbose: *verbose})
77-
spec, _, err := parseBatchSpec(ctx, file, svc, false)
77+
spec, _, _, err := parseBatchSpec(ctx, file, svc)
7878
if err != nil {
7979
ui := &ui.TUI{Out: out}
8080
ui.ParsingBatchSpecFailure(err)

cmd/src/batch_validate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Examples:
7373
return err
7474
}
7575

76-
if _, _, err := parseBatchSpec(ctx, file, svc, false); err != nil {
76+
if _, _, _, err := parseBatchSpec(ctx, file, svc); err != nil {
7777
ui.ParsingBatchSpecFailure(err)
7878
return err
7979
}

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ require (
2222
github.com/sourcegraph/go-diff v0.6.1
2323
github.com/sourcegraph/jsonx v0.0.0-20200629203448-1a936bd500cf
2424
github.com/sourcegraph/scip v0.2.1
25-
github.com/sourcegraph/sourcegraph/lib v0.0.0-20220825181731-397a768a5290
25+
github.com/sourcegraph/sourcegraph/lib v0.0.0-20221004162410-237d5855fa13
2626
github.com/stretchr/testify v1.8.0
2727
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
2828
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
@@ -105,7 +105,7 @@ require (
105105
go.uber.org/zap v1.23.0 // indirect
106106
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
107107
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
108-
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
108+
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec // indirect
109109
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 // indirect
110110
golang.org/x/text v0.3.7 // indirect
111111
golang.org/x/tools v0.1.12 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,8 @@ github.com/sourcegraph/log v0.0.0-20220901143117-fc0516a694c9 h1:JjFyvx9hCD5+Jpu
373373
github.com/sourcegraph/log v0.0.0-20220901143117-fc0516a694c9/go.mod h1:UxiwB6C3xk3xOySJpW1R0MDUyfGuJRFS5Z8C+SA5p2I=
374374
github.com/sourcegraph/scip v0.2.1 h1:t4cTR8TU81Psfmcj3ZYer67JFzsR/Sc7w5rsuckRo1Y=
375375
github.com/sourcegraph/scip v0.2.1/go.mod h1:EYyT39nXdZDNVmgbJAlyIVWbEb1txnAOKpJPSYpvgXk=
376-
github.com/sourcegraph/sourcegraph/lib v0.0.0-20220825181731-397a768a5290 h1:SLCu3Rf1eLZ4sNKl0Bg1oURTgDxEutRCaTQt5dpVqH4=
377-
github.com/sourcegraph/sourcegraph/lib v0.0.0-20220825181731-397a768a5290/go.mod h1:9wnFUNfpORLAOJn4XAO7ZeWnYkf6/CxlWaTU1vlpuKc=
376+
github.com/sourcegraph/sourcegraph/lib v0.0.0-20221004162410-237d5855fa13 h1:HEj9QVz35nIU4plPb7iJSFjcTA14zVnfAdfYZF5jsKg=
377+
github.com/sourcegraph/sourcegraph/lib v0.0.0-20221004162410-237d5855fa13/go.mod h1:e3v3msUOgthv/QCWUzhFdfR3+hwUSn37rtuw49IVJg4=
378378
github.com/sourcegraph/yaml v1.0.1-0.20200714132230-56936252f152 h1:z/MpntplPaW6QW95pzcAR/72Z5TWDyDnSo0EOcyij9o=
379379
github.com/sourcegraph/yaml v1.0.1-0.20200714132230-56936252f152/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
380380
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
@@ -540,8 +540,8 @@ golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBc
540540
golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
541541
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
542542
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
543-
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
544-
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
543+
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
544+
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
545545
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
546546
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8=
547547
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

internal/batches/executor/coordinator.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func (c *Coordinator) CheckCache(ctx context.Context, batchSpec *batcheslib.Batc
6767
func (c *Coordinator) ClearCache(ctx context.Context, tasks []*Task) error {
6868
for _, task := range tasks {
6969
for i := len(task.Steps) - 1; i > -1; i-- {
70-
key := task.CacheKey(c.opts.GlobalEnv, c.opts.IsRemote, i)
70+
key := task.CacheKey(c.opts.GlobalEnv, c.opts.ExecOpts.WorkingDirectory, i)
7171
if err := c.opts.Cache.Clear(ctx, key); err != nil {
7272
return errors.Wrapf(err, "clearing cache for step %d in %q", i, task.Repository.Name)
7373
}
@@ -100,7 +100,7 @@ func (c *Coordinator) checkCacheForTask(ctx context.Context, batchSpec *batchesl
100100
return specs, false, nil
101101
}
102102

103-
func (c Coordinator) buildChangesetSpecs(task *Task, batchSpec *batcheslib.BatchSpec, result execution.AfterStepResult) ([]*batcheslib.ChangesetSpec, error) {
103+
func (c *Coordinator) buildChangesetSpecs(task *Task, batchSpec *batcheslib.BatchSpec, result execution.AfterStepResult) ([]*batcheslib.ChangesetSpec, error) {
104104
input := &batcheslib.ChangesetSpecInput{
105105
Repository: batcheslib.Repository{
106106
ID: task.Repository.ID,
@@ -128,7 +128,7 @@ func (c *Coordinator) loadCachedStepResults(ctx context.Context, task *Task, glo
128128
// We start at the back so that we can find the _last_ cached step,
129129
// then restart execution on the following step.
130130
for i := len(task.Steps) - 1; i > -1; i-- {
131-
key := task.CacheKey(globalEnv, c.opts.IsRemote, i)
131+
key := task.CacheKey(globalEnv, c.opts.ExecOpts.WorkingDirectory, i)
132132

133133
result, found, err := c.opts.Cache.Get(ctx, key)
134134
if err != nil {
@@ -181,7 +181,7 @@ func (c *Coordinator) ExecuteAndBuildSpecs(ctx context.Context, batchSpec *batch
181181
// Write all step cache results to the cache.
182182
for _, res := range results {
183183
for _, stepRes := range res.stepResults {
184-
cacheKey := res.task.CacheKey(c.opts.GlobalEnv, c.opts.IsRemote, stepRes.StepIndex)
184+
cacheKey := res.task.CacheKey(c.opts.GlobalEnv, c.opts.ExecOpts.WorkingDirectory, stepRes.StepIndex)
185185
if err := c.opts.Cache.Set(ctx, cacheKey, stepRes); err != nil {
186186
return nil, nil, errors.Wrapf(err, "caching result for step %d", stepRes.StepIndex)
187187
}

internal/batches/executor/executor.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,12 @@ type NewExecutorOpts struct {
6262
Logger log.LogManager
6363

6464
// Config
65-
Parallelism int
66-
Timeout time.Duration
67-
TempDir string
68-
IsRemote bool
69-
GlobalEnv []string
65+
Parallelism int
66+
Timeout time.Duration
67+
WorkingDirectory string
68+
TempDir string
69+
IsRemote bool
70+
GlobalEnv []string
7071
}
7172

7273
type executor struct {
@@ -168,15 +169,15 @@ func (x *executor) do(ctx context.Context, task *Task, ui TaskExecutionUI) (err
168169

169170
// Actually execute the steps.
170171
opts := &RunStepsOpts{
171-
Task: task,
172-
Logger: l,
173-
WC: x.opts.Creator,
174-
EnsureImage: x.opts.EnsureImage,
175-
TempDir: x.opts.TempDir,
176-
IsRemote: x.opts.IsRemote,
177-
GlobalEnv: x.opts.GlobalEnv,
178-
Timeout: x.opts.Timeout,
179-
RepoArchive: repoArchive,
172+
Task: task,
173+
Logger: l,
174+
WC: x.opts.Creator,
175+
EnsureImage: x.opts.EnsureImage,
176+
TempDir: x.opts.TempDir,
177+
GlobalEnv: x.opts.GlobalEnv,
178+
Timeout: x.opts.Timeout,
179+
RepoArchive: repoArchive,
180+
WorkingDirectory: x.opts.WorkingDirectory,
180181

181182
UI: ui.StepsExecutionUI(task),
182183
}

0 commit comments

Comments
 (0)