-
Notifications
You must be signed in to change notification settings - Fork 3
/
settings.go
147 lines (123 loc) · 4.09 KB
/
settings.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package build
import (
"context"
"fmt"
"io"
"os"
"os/exec"
"github.com/hashicorp/actions-go-build/internal/log"
)
// Settings contains settings for running builds.
// These are not to be confused with build.Config, these settings
// are build-run specific and not part of the _definition_ of the build.
// Don't use this directly, use the With... functions to set
// settings when calling New.
type Settings struct {
bash string
context context.Context
Log func(string, ...any)
Debug func(string, ...any)
Loud func(string, ...any)
stdout io.Writer
stderr io.Writer
forceRebuild bool
// forceVerification forces the build to be run as a verification build (i.e.
// in the verification root directory).
isVerification bool
cleanOnly bool
logPrefix string
}
// Option represents a function that configures Settings.
type Option func(*Settings)
// WithContext sets the context passed when we shell out.
func WithContext(c context.Context) Option { return func(s *Settings) { s.context = c } }
// WithLogfunc sets the log func.
func WithLogfunc(f func(string, ...any)) Option {
return func(s *Settings) { s.Log = s.makeLogFunc(f) }
}
// WithLogPrefix sets the log prefix.
func WithLogPrefix(p string) Option { return func(s *Settings) { s.logPrefix = p } }
// WithDebugfunc sest the debug func.
func WithDebugfunc(f func(string, ...any)) Option {
return func(s *Settings) { s.Debug = s.makeLogFunc(f) }
}
// WithDebugfunc sest the debug func.
func WithLoudfunc(f func(string, ...any)) Option {
return func(s *Settings) { s.Loud = s.makeLogFunc(f) }
}
// WithStdout sets the stdout for when we shell out.
func WithStdout(w io.Writer) Option { return func(s *Settings) { s.stdout = w } }
// WithStderr sets the stderr for when we shell out.
func WithStderr(w io.Writer) Option { return func(s *Settings) { s.stderr = w } }
// WithForceRebuild forces a build to be re-done rather than using cache.
func WithForceRebuild(on bool) Option { return func(s *Settings) { s.forceRebuild = on } }
// WithForceVerification forces a build to be a verification build (or not depending on
// the boolean passed).
func WithForceVerification(on bool) Option { return func(s *Settings) { s.isVerification = on } }
// AsVerificationBuild forces a build to be treated as a verification build (i.e. run
// in the verification root, and cached separately from primary builds).
func AsVerificationBuild() Option { return func(s *Settings) { s.isVerification = true } }
// AsPrimaryBuild forces a build to be treated as a primary build (i.e. run
// in the current directory, or primary root (for remote builds).
func AsPrimaryBuild() Option { return func(s *Settings) { s.isVerification = false } }
// WithCleanOnly causes the build to fail early if it's not based on a clean worktree.
func WithCleanOnly(on bool) Option { return func(s *Settings) { s.cleanOnly = on } }
func newSettings(options []Option) (Settings, error) {
s := &Settings{}
err := s.setOptions(options...)
return *s, err
}
func (s *Settings) setOptions(opts ...Option) error {
for _, o := range opts {
o(s)
}
return s.setDefaults()
}
func (s *Settings) setDefaults() (err error) {
s.bash, err = resolveBashPath(s.bash)
if err != nil {
return err
}
if s.context == nil {
s.context = context.Background()
}
if s.Debug == nil {
s.Debug = log.Debug
}
if s.Log == nil {
s.Log = log.Verbose
}
if s.Loud == nil {
s.Loud = log.Info
}
WithDebugfunc(s.Debug)(s)
WithLogfunc(s.Log)(s)
WithLoudfunc(s.Loud)(s)
if s.stdout == nil {
s.stdout = os.Stderr
}
if s.stderr == nil {
s.stderr = os.Stderr
}
return nil
}
func resolveBashPath(path string) (string, error) {
if path == "" {
path = "bash"
}
return exec.LookPath(path)
}
func (s *Settings) makeLogFunc(logFunc log.Func) log.Func {
return makePrefixedLocFunc(s.logPrefix, logFunc)
}
func makePrefixedLocFunc(name string, logFunc log.Func) log.Func {
if name != "" {
name = name + ": "
}
return func(f string, a ...any) {
f = fmt.Sprintf("%s%s", name, f)
logFunc(f, a...)
}
}