-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathbuildutil.go
122 lines (112 loc) · 3.9 KB
/
buildutil.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
// Copyright (c) Microsoft Corporation.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package buildutil
import (
"fmt"
"log"
"os"
"strconv"
"strings"
)
// Retry runs f until it succeeds or the attempt limit is reached.
func Retry(attempts int, f func() error) error {
var i = 0
for ; i < attempts; i++ {
if attempts > 1 {
fmt.Printf("---- Running attempt %v of %v...\n", i+1, attempts)
}
err := f()
if err != nil {
if i+1 < attempts {
fmt.Printf("---- Attempt failed with error: %v\n", err)
continue
}
fmt.Printf("---- Final attempt failed.\n")
return err
}
break
}
fmt.Printf("---- Successful on attempt %v of %v.\n", i+1, attempts)
return nil
}
// MaxMakeRetryAttemptsOrExit returns max retry attempts for the Go build according to an env var.
func MaxMakeRetryAttemptsOrExit() int {
return maxAttemptsOrExit("GO_MAKE_MAX_RETRY_ATTEMPTS")
}
func maxAttemptsOrExit(varName string) int {
attempts, err := getEnvIntOrDefault(varName, 1)
if err != nil {
log.Fatal(err)
}
if attempts <= 0 {
log.Fatalf("Expected positive integer for environment variable %q, but found: %v\n", varName, attempts)
}
return attempts
}
func getEnvIntOrDefault(varName string, defaultValue int) (int, error) {
a, err := GetEnvOrDefault(varName, strconv.Itoa(defaultValue))
if err != nil {
return 0, err
}
i, err := strconv.Atoi(a)
if err != nil {
return 0, fmt.Errorf("env var %q is not an int: %w", varName, err)
}
return i, nil
}
// GetEnvOrDefault find an environment variable with name varName and returns its value. If the env
// var is not set, returns defaultValue.
//
// If the env var is found and its value is empty string, returns an error. This can't happen on
// Windows because setting an env var to empty string deletes it. However, on Linux, it is possible.
// It's likely a mistake, so we let the user know what happened with an error. For example, the env
// var might be empty string because it was set by "example=$(someCommand)" and someCommand
// encountered an error and didn't send any output to stdout.
func GetEnvOrDefault(varName, defaultValue string) (string, error) {
v, ok := os.LookupEnv(varName)
if !ok {
return defaultValue, nil
}
if v == "" {
return "", fmt.Errorf(
"env var %q is empty, not a valid string. To use the default string %v, unset the env var",
varName, defaultValue)
}
return v, nil
}
// AppendExperimentEnv sets the GOEXPERIMENT env var to the given value, or if GOEXPERIMENT is
// already set, appends a comma separator and then the given value.
func AppendExperimentEnv(experiment string) {
// If the experiment enables a crypto backend, allow fallback to Go crypto. Go turns off cgo
// and/or cross-builds in various situations during the build/tests, so we need to allow for it.
if strings.Contains(experiment, "opensslcrypto") ||
strings.Contains(experiment, "cngcrypto") ||
strings.Contains(experiment, "boringcrypto") ||
strings.Contains(experiment, "darwincrypto") ||
strings.Contains(experiment, "systemcrypto") {
experiment += ",allowcryptofallback"
}
if v, ok := os.LookupEnv("GOEXPERIMENT"); ok {
experiment = v + "," + experiment
}
fmt.Printf("Setting GOEXPERIMENT: %v\n", experiment)
if err := os.Setenv("GOEXPERIMENT", experiment); err != nil {
panic(err)
}
}
// UnassignGOROOT unsets the GOROOT env var if it is set.
//
// Setting GOROOT explicitly in the environment has not been necessary since Go
// 1.9 (https://go.dev/doc/go1.9#goroot), but a dev or build machine may still
// have it set. It interferes with attempts to run the built Go (such as when
// building the race runtime), so remove the explicit GOROOT if set.
func UnassignGOROOT() error {
if explicitRoot, ok := os.LookupEnv("GOROOT"); ok {
fmt.Printf("---- Removing explicit GOROOT from environment: %v\n", explicitRoot)
if err := os.Unsetenv("GOROOT"); err != nil {
return err
}
}
return nil
}