forked from remind101/conveyor
/
conveyor.go
108 lines (86 loc) · 2.29 KB
/
conveyor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package conveyor
import (
"fmt"
"io"
"log"
"os"
"time"
"github.com/remind101/conveyor/builder"
"github.com/remind101/pkg/reporter"
"golang.org/x/net/context"
)
const (
// DefaultTimeout is the default amount of time to wait for a build
// to complete before cancelling it.
DefaultTimeout = 20 * time.Minute
)
// Conveyor serves as a builder.
type Conveyor struct {
Builder builder.Builder
LogFactory builder.LogFactory
// A Reporter to use to report errors.
Reporter reporter.Reporter
// Timeout controls how long to wait before canceling a build. A timeout
// of 0 means no timeout.
Timeout time.Duration
}
// New returns a new Conveyor instance.
func New(b builder.Builder) *Conveyor {
return &Conveyor{
Builder: builder.WithCancel(builder.CloseWriter(b)),
Timeout: DefaultTimeout,
}
}
// EnqueueBuild enqueus a build to run at a later time.
func (c *Conveyor) EnqueueBuild(ctx context.Context, opts builder.BuildOptions) error {
w, err := c.newLogger(opts)
if err != nil {
return err
}
go c.Build(ctx, w, opts)
return err
}
func (c *Conveyor) Build(ctx context.Context, w io.Writer, opts builder.BuildOptions) (image string, err error) {
log.Printf("Starting build: repository=%s branch=%s sha=%s",
opts.Repository,
opts.Branch,
opts.Sha,
)
// Embed the reporter in the context.Context.
ctx = reporter.WithReporter(ctx, c.reporter())
if c.Timeout != 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, c.Timeout)
defer cancel() // Release resources.
}
reporter.AddContext(ctx, "options", opts)
defer reporter.Monitor(ctx)
defer func() {
if err != nil {
reporter.Report(ctx, err)
}
}()
image, err = c.Builder.Build(ctx, w, opts)
return
}
func (c *Conveyor) Cancel() error {
if b, ok := c.Builder.(*builder.CancelBuilder); ok {
return b.Cancel()
}
return fmt.Errorf("Builder does not support Cancel()")
}
func (c *Conveyor) newLogger(opts builder.BuildOptions) (builder.Logger, error) {
if c.LogFactory == nil {
return builder.StdoutLogger(opts)
}
return c.LogFactory(opts)
}
func (c *Conveyor) reporter() reporter.Reporter {
if c.Reporter == nil {
return reporter.ReporterFunc(func(ctx context.Context, err error) error {
fmt.Fprintf(os.Stderr, "reporting err: %v\n", err)
return nil
})
}
return c.Reporter
}