Skip to content

Commit e486e84

Browse files
authored
executor UI: extract StepsExecutionUI from TaskExecutionUI and implement it in TUI and JSON (#606)
This is a follow-up to #597 and splits up the existing interface into two. That allows us to remove all formatting from `runSteps` and `executeSingleStep` and also provide more information for the JSON interface (e.g. when a step is finished). **Note**: the `OPERATION` and `STATUS` fields in the `logEvents` don't make a lot of sense. Happy to change everything there.
1 parent 9a4b64d commit e486e84

File tree

7 files changed

+276
-82
lines changed

7 files changed

+276
-82
lines changed

internal/batches/executor/coordinator.go

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ package executor
22

33
import (
44
"context"
5-
"io"
65
"reflect"
76
"strconv"
87
"time"
98

109
"github.com/cockroachdb/errors"
1110
"github.com/hashicorp/go-multierror"
11+
1212
batcheslib "github.com/sourcegraph/sourcegraph/lib/batches"
1313

1414
"github.com/sourcegraph/src-cli/internal/api"
@@ -207,22 +207,6 @@ func (c *Coordinator) cacheAndBuildSpec(ctx context.Context, taskResult taskResu
207207
return specs, nil
208208
}
209209

210-
type TaskExecutionUI interface {
211-
Start([]*Task)
212-
Success()
213-
214-
TaskStarted(*Task)
215-
TaskFinished(*Task, error)
216-
217-
TaskChangesetSpecsBuilt(*Task, []*batcheslib.ChangesetSpec)
218-
219-
// TODO: This should be split up into methods that are more specific.
220-
TaskCurrentlyExecuting(*Task, string)
221-
222-
StepStdoutWriter(context.Context, *Task, int) io.WriteCloser
223-
StepStderrWriter(context.Context, *Task, int) io.WriteCloser
224-
}
225-
226210
// Execute executes the given Tasks and the importChangeset statements in the
227211
// given spec. It regularly calls the executionProgressPrinter with the
228212
// current TaskStatuses.

internal/batches/executor/coordinator_test.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ package executor
33
import (
44
"context"
55
"fmt"
6-
"io"
76
"strings"
87
"sync"
98
"testing"
109

1110
"github.com/google/go-cmp/cmp"
1211
"github.com/google/go-cmp/cmp/cmpopts"
1312
"github.com/sourcegraph/batch-change-utils/overridable"
13+
1414
batcheslib "github.com/sourcegraph/sourcegraph/lib/batches"
1515
"github.com/sourcegraph/sourcegraph/lib/batches/git"
1616
"github.com/sourcegraph/sourcegraph/lib/batches/template"
@@ -545,18 +545,8 @@ func (d *dummyTaskExecutionUI) TaskChangesetSpecsBuilt(t *Task, specs []*batches
545545
d.specs[t] = specs
546546
}
547547

548-
type discardCloser struct {
549-
io.Writer
550-
}
551-
552-
func (discardCloser) Close() error { return nil }
553-
554-
func (d *dummyTaskExecutionUI) TaskCurrentlyExecuting(*Task, string) {}
555-
func (d *dummyTaskExecutionUI) StepStdoutWriter(ctx context.Context, task *Task, step int) io.WriteCloser {
556-
return discardCloser{io.Discard}
557-
}
558-
func (d *dummyTaskExecutionUI) StepStderrWriter(ctx context.Context, task *Task, step int) io.WriteCloser {
559-
return discardCloser{io.Discard}
548+
func (d *dummyTaskExecutionUI) StepsExecutionUI(t *Task) StepsExecutionUI {
549+
return NoopStepsExecUI{}
560550
}
561551

562552
var _ taskExecutor = &dummyExecutor{}

internal/batches/executor/executor.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,8 @@ func (x *executor) do(ctx context.Context, task *Task, ui TaskExecutionUI) (err
174174
wc: x.opts.Creator,
175175
ensureImage: x.opts.EnsureImage,
176176
tempDir: x.opts.TempDir,
177-
reportProgress: func(currentlyExecuting string) {
178-
ui.TaskCurrentlyExecuting(task, currentlyExecuting)
179-
},
180-
newUiStdoutWriter: ui.StepStdoutWriter,
181-
newUiStderrWriter: ui.StepStderrWriter,
177+
178+
ui: ui.StepsExecutionUI(task),
182179
}
183180

184181
result, stepResults, err := runSteps(runCtx, opts)

internal/batches/executor/run_steps.go

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"github.com/cockroachdb/errors"
1515
"github.com/hashicorp/go-multierror"
16+
1617
batcheslib "github.com/sourcegraph/sourcegraph/lib/batches"
1718
"github.com/sourcegraph/sourcegraph/lib/batches/git"
1819
"github.com/sourcegraph/sourcegraph/lib/batches/template"
@@ -64,27 +65,27 @@ type executionOpts struct {
6465

6566
tempDir string
6667

67-
logger log.TaskLogger
68-
reportProgress func(string)
68+
logger log.TaskLogger
6969

70-
newUiStdoutWriter func(context.Context, *Task, int) io.WriteCloser
71-
newUiStderrWriter func(context.Context, *Task, int) io.WriteCloser
70+
ui StepsExecutionUI
7271
}
7372

7473
func runSteps(ctx context.Context, opts *executionOpts) (result executionResult, stepResults []stepExecutionResult, err error) {
75-
opts.reportProgress("Downloading archive")
74+
opts.ui.ArchiveDownloadStarted()
7675
err = opts.task.Archive.Ensure(ctx)
7776
if err != nil {
7877
return executionResult{}, nil, errors.Wrap(err, "fetching repo")
7978
}
8079
defer opts.task.Archive.Close()
80+
opts.ui.ArchiveDownloadFinished()
8181

82-
opts.reportProgress("Initializing workspace")
82+
opts.ui.WorkspaceInitializationStarted()
8383
workspace, err := opts.wc.Create(ctx, opts.task.Repository, opts.task.Steps, opts.task.Archive)
8484
if err != nil {
8585
return executionResult{}, nil, errors.Wrap(err, "creating workspace")
8686
}
8787
defer workspace.Close(ctx)
88+
opts.ui.WorkspaceInitializationFinished()
8889

8990
var (
9091
execResult = executionResult{
@@ -118,12 +119,7 @@ func runSteps(ctx context.Context, opts *executionOpts) (result executionResult,
118119
return execResult, stepResults, nil
119120
}
120121

121-
switch startStep {
122-
case 1:
123-
opts.reportProgress("Skipping step 1. Found cached result.")
124-
default:
125-
opts.reportProgress(fmt.Sprintf("Skipping steps 1 to %d. Found cached results.", startStep))
126-
}
122+
opts.ui.SkippingStepsUpto(startStep)
127123
}
128124

129125
for i := startStep; i < len(opts.task.Steps); i++ {
@@ -157,9 +153,10 @@ func runSteps(ctx context.Context, opts *executionOpts) (result executionResult,
157153
return execResult, nil, errors.Wrap(err, "evaluating step condition")
158154
}
159155
if !cond {
160-
opts.reportProgress(fmt.Sprintf("Skipping step %d", i+1))
156+
opts.ui.StepSkipped(i + 1)
161157
continue
162158
}
159+
163160
// We need to grab the digest for the exact image we're using.
164161
img, err := opts.ensureImage(ctx, step.Container)
165162
if err != nil {
@@ -204,14 +201,18 @@ func runSteps(ctx context.Context, opts *executionOpts) (result executionResult,
204201
}
205202
stepResults = append(stepResults, stepResult)
206203
previousStepResult = result
204+
205+
opts.ui.StepFinished(i+1, stepResult.Diff, result.Files, stepResult.Outputs)
207206
}
208207

209-
opts.reportProgress("Calculating diff")
208+
opts.ui.CalculatingDiffStarted()
210209
diffOut, err := workspace.Diff(ctx)
211210
if err != nil {
212211
return execResult, nil, errors.Wrap(err, "git diff failed")
213212
}
214213

214+
opts.ui.CalculatingDiffFinished()
215+
215216
execResult.Diff = string(diffOut)
216217
execResult.ChangedFiles = previousStepResult.Files
217218

@@ -232,7 +233,7 @@ func executeSingleStep(
232233
// ----------
233234
// PREPARATION
234235
// ----------
235-
opts.reportProgress(fmt.Sprintf("Preparing step %d", i+1))
236+
opts.ui.StepPreparing(i + 1)
236237

237238
cidFile, cleanup, err := createCidFile(ctx, opts.tempDir, util.SlugForRepo(opts.task.Repository.Name, opts.task.Repository.Rev()))
238239
if err != nil {
@@ -274,7 +275,7 @@ func executeSingleStep(
274275
// ----------
275276
// EXECUTION
276277
// ----------
277-
opts.reportProgress(runScript)
278+
opts.ui.StepStarted(i+1, runScript)
278279

279280
workspaceOpts, err := workspace.DockerRunOpts(ctx, workDir)
280281
if err != nil {
@@ -316,8 +317,8 @@ func executeSingleStep(
316317

317318
writerCtx, writerCancel := context.WithCancel(ctx)
318319
defer writerCancel()
319-
uiStdoutWriter := opts.newUiStdoutWriter(writerCtx, opts.task, i)
320-
uiStderrWriter := opts.newUiStderrWriter(writerCtx, opts.task, i)
320+
uiStdoutWriter := opts.ui.StepStdoutWriter(writerCtx, opts.task, i)
321+
uiStderrWriter := opts.ui.StepStderrWriter(writerCtx, opts.task, i)
321322
defer func() {
322323
uiStdoutWriter.Close()
323324
uiStderrWriter.Close()

internal/batches/executor/ui.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package executor
2+
3+
import (
4+
"context"
5+
"io"
6+
7+
batcheslib "github.com/sourcegraph/sourcegraph/lib/batches"
8+
"github.com/sourcegraph/sourcegraph/lib/batches/git"
9+
)
10+
11+
type TaskExecutionUI interface {
12+
Start([]*Task)
13+
Success()
14+
15+
TaskStarted(*Task)
16+
TaskFinished(*Task, error)
17+
18+
TaskChangesetSpecsBuilt(*Task, []*batcheslib.ChangesetSpec)
19+
20+
StepsExecutionUI(*Task) StepsExecutionUI
21+
}
22+
23+
type StepsExecutionUI interface {
24+
ArchiveDownloadStarted()
25+
ArchiveDownloadFinished()
26+
27+
WorkspaceInitializationStarted()
28+
WorkspaceInitializationFinished()
29+
30+
SkippingStepsUpto(int)
31+
32+
StepSkipped(int)
33+
34+
StepPreparing(int)
35+
StepStarted(int, string)
36+
37+
StepStdoutWriter(context.Context, *Task, int) io.WriteCloser
38+
StepStderrWriter(context.Context, *Task, int) io.WriteCloser
39+
40+
CalculatingDiffStarted()
41+
CalculatingDiffFinished()
42+
43+
StepFinished(idx int, diff []byte, changes *git.Changes, outputs map[string]interface{})
44+
}
45+
46+
// NoopStepsExecUI is an implementation of StepsExecutionUI that does nothing.
47+
type NoopStepsExecUI struct{}
48+
49+
func (noop NoopStepsExecUI) ArchiveDownloadStarted() {}
50+
func (noop NoopStepsExecUI) ArchiveDownloadFinished() {}
51+
func (noop NoopStepsExecUI) WorkspaceInitializationStarted() {}
52+
func (noop NoopStepsExecUI) WorkspaceInitializationFinished() {}
53+
func (noop NoopStepsExecUI) SkippingStepsUpto(startStep int) {}
54+
func (noop NoopStepsExecUI) StepSkipped(step int) {}
55+
func (noop NoopStepsExecUI) StepPreparing(step int) {}
56+
func (noop NoopStepsExecUI) StepStarted(step int, runScript string) {}
57+
func (noop NoopStepsExecUI) StepStdoutWriter(ctx context.Context, task *Task, step int) io.WriteCloser {
58+
return discardCloser{io.Discard}
59+
}
60+
func (noop NoopStepsExecUI) StepStderrWriter(ctx context.Context, task *Task, step int) io.WriteCloser {
61+
return discardCloser{io.Discard}
62+
}
63+
func (noop NoopStepsExecUI) CalculatingDiffStarted() {}
64+
func (noop NoopStepsExecUI) CalculatingDiffFinished() {}
65+
func (noop NoopStepsExecUI) StepFinished(idx int, diff []byte, changes *git.Changes, outputs map[string]interface{}) {
66+
}
67+
68+
type discardCloser struct {
69+
io.Writer
70+
}
71+
72+
func (discardCloser) Close() error { return nil }

0 commit comments

Comments
 (0)