Skip to content

Commit 7a3403e

Browse files
committed
Add option to disable error wrapping
Sometimes implementations may want to transparently run code without wrapping errors from a library.
1 parent f068907 commit 7a3403e

File tree

4 files changed

+65
-5
lines changed

4 files changed

+65
-5
lines changed

examples/options_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package examples
2+
3+
import (
4+
"errors"
5+
"testing"
6+
7+
pipeline "github.com/ccremer/go-command-pipeline"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestExample_Options(t *testing.T) {
12+
p := pipeline.NewPipeline()
13+
p.WithOptions(pipeline.DisableErrorWrapping)
14+
p.WithSteps(
15+
pipeline.NewStepFromFunc("disabled error wrapping", func(_ pipeline.Context) error {
16+
return errors.New("some error")
17+
}),
18+
)
19+
result := p.Run()
20+
assert.Equal(t, "some error", result.Err.Error())
21+
}

options.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package pipeline
2+
3+
// Option configures the given Pipeline with a behaviour-altering setting.
4+
type Option func(pipeline *Pipeline)
5+
6+
// WithOptions configures the Pipeline with settings.
7+
// The options are applied immediately.
8+
// Options are applied to nested pipelines provided they are set before building the nested pipeline.
9+
// Nested pipelines can be configured with their own options.
10+
func (p *Pipeline) WithOptions(options ...Option) *Pipeline {
11+
for _, option := range options {
12+
option(p)
13+
}
14+
return p
15+
}
16+
17+
// DisableErrorWrapping disables the wrapping of errors that are emitted from pipeline steps.
18+
// This effectively causes Result.Err to be exactly the error as returned from a step.
19+
var DisableErrorWrapping Option = func(pipeline *Pipeline) {
20+
pipeline.disableErrorWrapping = true
21+
}

options_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package pipeline
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestPipeline_WithOptions(t *testing.T) {
10+
t.Run("DisableErrorWrapping", func(t *testing.T) {
11+
p := NewPipeline().WithOptions(DisableErrorWrapping)
12+
assert.True(t, p.disableErrorWrapping)
13+
})
14+
}

pipeline.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import (
88
type (
99
// Pipeline holds and runs intermediate actions, called "steps".
1010
Pipeline struct {
11-
steps []Step
12-
context Context
13-
beforeHooks []Listener
14-
finalizer ResultHandler
11+
steps []Step
12+
context Context
13+
beforeHooks []Listener
14+
finalizer ResultHandler
15+
disableErrorWrapping bool
1516
}
1617
// Result is the object that is returned after each step and after running a pipeline.
1718
Result struct {
@@ -87,7 +88,7 @@ func (p *Pipeline) WithSteps(steps ...Step) *Pipeline {
8788
// WithNestedSteps is similar to AsNestedStep, but it accepts the steps given directly as parameters.
8889
func (p *Pipeline) WithNestedSteps(name string, steps ...Step) Step {
8990
return NewStep(name, func(_ Context) Result {
90-
nested := &Pipeline{beforeHooks: p.beforeHooks, steps: steps, context: p.context}
91+
nested := &Pipeline{beforeHooks: p.beforeHooks, steps: steps, context: p.context, disableErrorWrapping: p.disableErrorWrapping}
9192
return nested.Run()
9293
})
9394
}
@@ -145,6 +146,9 @@ func (p *Pipeline) doRun() Result {
145146
// Abort pipeline without error
146147
return Result{}
147148
}
149+
if p.disableErrorWrapping {
150+
return Result{Err: err}
151+
}
148152
return Result{Err: fmt.Errorf("step '%s' failed: %w", step.Name, err)}
149153
}
150154
}

0 commit comments

Comments
 (0)