@@ -43,6 +43,22 @@ import (
43
43
const (
44
44
appDir = "/ko-app"
45
45
defaultAppFilename = "ko-app"
46
+
47
+ gorootWarningTemplate = `NOTICE!
48
+ -----------------------------------------------------------------
49
+ ko and go have mismatched GOROOT:
50
+ go/build.Default.GOROOT = %q
51
+ $(go env GOROOT) = %q
52
+
53
+ Inferring GOROOT=%q
54
+
55
+ Run this to remove this warning:
56
+ export GOROOT=$(go env GOROOT)
57
+
58
+ For more information see:
59
+ https://github.com/google/ko/issues/106
60
+ -----------------------------------------------------------------
61
+ `
46
62
)
47
63
48
64
// GetBase takes an importpath and returns a base image.
@@ -158,26 +174,59 @@ func moduleInfo(ctx context.Context) (*modules, error) {
158
174
return & modules , nil
159
175
}
160
176
177
+ // getGoroot shells out to `go env GOROOT` to determine
178
+ // the GOROOT for the installed version of go so that we
179
+ // can set it in our buildContext. By default, the GOROOT
180
+ // of our buildContext is set to the GOROOT at install
181
+ // time for `ko`, which means that we break when certain
182
+ // package managers update go or when using a pre-built
183
+ // `ko` binary that expects a different GOROOT.
184
+ //
185
+ // See https://github.com/google/ko/issues/106
186
+ func getGoroot (ctx context.Context ) (string , error ) {
187
+ output , err := exec .CommandContext (ctx , "go" , "env" , "GOROOT" ).Output ()
188
+ return strings .TrimSpace (string (output )), err
189
+ }
190
+
161
191
// NewGo returns a build.Interface implementation that:
162
192
// 1. builds go binaries named by importpath,
163
193
// 2. containerizes the binary on a suitable base,
164
194
func NewGo (ctx context.Context , options ... Option ) (Interface , error ) {
195
+ // TODO: We could do moduleInfo() and getGoroot() concurrently.
165
196
module , err := moduleInfo (ctx )
166
197
if err != nil {
167
198
return nil , err
168
199
}
169
200
201
+ goroot , err := getGoroot (ctx )
202
+ if err != nil {
203
+ // On error, print the output and set goroot to "" to avoid using it later.
204
+ log .Printf ("Unexpected error running \" go env GOROOT\" : %v\n %v" , err , goroot )
205
+ goroot = ""
206
+ } else if goroot == "" {
207
+ log .Printf (`Unexpected: $(go env GOROOT) == ""` )
208
+ }
209
+
210
+ // If $(go env GOROOT) successfully returns a non-empty string that differs from
211
+ // the default build context GOROOT, print a warning and use $(go env GOROOT).
212
+ bc := gb .Default
213
+ if goroot != "" && bc .GOROOT != goroot {
214
+ log .Printf (gorootWarningTemplate , bc .GOROOT , goroot , goroot )
215
+ bc .GOROOT = goroot
216
+ }
217
+
170
218
gbo := & gobuildOpener {
171
219
build : build ,
172
220
mod : module ,
173
- buildContext : & gb . Default ,
221
+ buildContext : & bc ,
174
222
}
175
223
176
224
for _ , option := range options {
177
225
if err := option (gbo ); err != nil {
178
226
return nil , err
179
227
}
180
228
}
229
+
181
230
return gbo .Open ()
182
231
}
183
232
0 commit comments