Skip to content

Commit 38d886e

Browse files
authored
Merge pull request #159 from Clever/INFRANG-6802-env
INFRANG-6802-env
2 parents 291dd95 + a54d857 commit 38d886e

File tree

10 files changed

+220
-105
lines changed

10 files changed

+220
-105
lines changed

VERSION

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
v1.0.4
2-
updated parsing of go version from go.mod
1+
v1.0.5
2+
- Supporting lazy loading of environment variables
33

44
Previously:
5+
- updated parsing of go version from go.mod
56
- goci now supports validation of go version
67
- variable MASTER_COMPARE is now required for local dev
78
- Instead of emitting an error on failed catalog syncs, simply warn

cmd/goci/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ goci accepts very limited arguments which merely change the mode it runs in. The
1010

1111
1. `goci detect` detects any changed applications according to their launch configuration. This can be used to pass a name of apps to another script.
1212
2. `goci artifact-build-publish-deploy` builds, publishes and deploys any application artifacts.
13+
3. `goci validate` validates an applications go version, while also checking for compatible branch naming conventions for catapult.
1314

1415

1516
## Multi-app Support

cmd/goci/main.go

Lines changed: 60 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ const usage = "usage: goci <validate|detect|artifact-build-publish-deploy>"
2727

2828
// ValidationError represents an error that occurs during validation.
2929
type ValidationError struct {
30-
Message string
30+
Message string
3131
}
3232

3333
func (e *ValidationError) Error() string {
34-
return e.Message
34+
return e.Message
3535
}
3636

3737
func main() {
@@ -42,12 +42,12 @@ func main() {
4242
mode := os.Args[1]
4343
if err := run(mode); err != nil {
4444
if _, ok := err.(*ValidationError); ok {
45-
fmt.Println("Validation error:", err)
46-
os.Exit(2) // Use a different exit code for validation errors
47-
} else {
48-
fmt.Println("Error:", err)
49-
os.Exit(1)
50-
}
45+
fmt.Println("Validation error:", err)
46+
os.Exit(2) // Use a different exit code for validation errors
47+
} else {
48+
fmt.Println("Error:", err)
49+
os.Exit(1)
50+
}
5151
}
5252
}
5353

@@ -82,7 +82,7 @@ func run(mode string) error {
8282
if err = validateRun(); err != nil {
8383
return err
8484
}
85-
85+
8686
if len(apps) == 0 {
8787
fmt.Println("No applications have buildable changes. If this is unexpected, " +
8888
"double check your artifact dependency configuration in the launch yaml.")
@@ -105,7 +105,7 @@ func run(mode string) error {
105105
}
106106

107107
if len(dockerTargets) > 0 {
108-
dkr, err := docker.New(ctx)
108+
dkr, err := docker.New(ctx, environment.OidcEcrUploadRole())
109109
if err != nil {
110110
return err
111111
}
@@ -125,7 +125,7 @@ func run(mode string) error {
125125
}
126126

127127
if len(lambdaTargets) > 0 {
128-
lmda := lambda.New(ctx)
128+
lmda := lambda.New(ctx, environment.LambdaArtifactBucketPrefix())
129129

130130
for artifact, t := range lambdaTargets {
131131
if err = repo.ExecBuild(t.Command); err != nil {
@@ -143,16 +143,16 @@ func run(mode string) error {
143143
return err
144144
}
145145

146-
if environment.Branch == "master" {
146+
if environment.Branch() == "master" {
147147
return cp.Deploy(ctx, appIDs)
148148
}
149149
return nil
150150
}
151151

152152
// validateRun checks the env.branch and go version to ensure the build is valid.
153153
func validateRun() error {
154-
if strings.Contains(environment.Branch, "/") {
155-
return &ValidationError{Message: fmt.Sprintf("branch name %s contains a `/` character, which is not supported by catapult", environment.Branch)}
154+
if strings.Contains(environment.Branch(), "/") {
155+
return &ValidationError{Message: fmt.Sprintf("branch name %s contains a `/` character, which is not supported by catapult", environment.Branch())}
156156
}
157157

158158
latestGoVersion, err := fetchLatestGoVersion()
@@ -161,12 +161,12 @@ func validateRun() error {
161161
}
162162

163163
goModPath := "./go.mod"
164-
fileBytes, err := os.ReadFile(goModPath)
165-
if err != nil {
166-
return fmt.Errorf("failed to read go.mod file: %v", err)
167-
}
164+
fileBytes, err := os.ReadFile(goModPath)
165+
if err != nil {
166+
return fmt.Errorf("failed to read go.mod file: %v", err)
167+
}
168168

169-
f, err := modfile.Parse("./go.mod", fileBytes , nil)
169+
f, err := modfile.Parse("./go.mod", fileBytes, nil)
170170
if err != nil {
171171
return fmt.Errorf("failed to parse go.mod file: %v", err)
172172
}
@@ -179,16 +179,14 @@ func validateRun() error {
179179
trimmedVersion = f.Go.Version
180180
}
181181

182-
version, e := strconv.ParseFloat(trimmedVersion, 64)
182+
repoVersion, e := strconv.ParseFloat(trimmedVersion, 64)
183183

184184
if e != nil {
185185
return fmt.Errorf("failed to parse go version: %v", e)
186186
}
187187

188188
// We will begin enforcing this policy for go version 1.24 and above, for now set the minimum version to 1.23
189-
if version <= 1.23 {
190-
version = 1.23
191-
}
189+
var enforceGoVersionUpgrade float64 = 1.23
192190

193191
// trim the patch value from the latest go version
194192
latestGoVersion = latestGoVersion[:len(latestGoVersion)-2]
@@ -197,11 +195,12 @@ func validateRun() error {
197195
return fmt.Errorf("failed to parse go version: %v", e)
198196
}
199197

200-
if version < newestGoVersion - 0.01 {
201-
return &ValidationError{Message: fmt.Sprintf("go version %v is no longer supported. Please upgrade to version %v", version, newestGoVersion)}
202-
} else if version == newestGoVersion - 0.01 {
198+
// Once 1.23 is no longer supported, we will enforce the policy for 1.24 and above
199+
if (repoVersion <= enforceGoVersionUpgrade) && (enforceGoVersionUpgrade < newestGoVersion-0.01) {
200+
return &ValidationError{Message: fmt.Sprintf("Your applications go version %v is no longer supported. Please upgrade to version %v.", repoVersion, newestGoVersion)}
201+
} else if repoVersion <= newestGoVersion-0.01 {
203202
// We'll give a PR comment to the Author to warn them about the need to upgrade
204-
fmt.Printf("Warning: This go version (%v) is nearing deprecation. Please upgrade to version %v\n", version, newestGoVersion)
203+
fmt.Printf("Warning: This applications go version will be out of support by the next major release. You will have until the next release before you need to upgrade to version %v\n", newestGoVersion)
205204
}
206205

207206
return nil
@@ -210,39 +209,39 @@ func validateRun() error {
210209
// fetchLatestGoVersion fetches the latest Go version from the official Go download page.
211210
func fetchLatestGoVersion() (string, error) {
212211
// official Go download page
213-
resp, err := http.Get("https://go.dev/dl/")
214-
if err != nil {
215-
return "", fmt.Errorf("failed to fetch Go download page: %v", err)
216-
}
217-
defer resp.Body.Close()
218-
219-
if resp.StatusCode != http.StatusOK {
220-
return "", fmt.Errorf("failed to fetch Go download page: status code %d", resp.StatusCode)
221-
}
222-
223-
bodyBytes, err := io.ReadAll(resp.Body)
224-
if err != nil {
225-
return "", fmt.Errorf("failed to read response body: %v", err)
226-
}
227-
body := string(bodyBytes)
228-
229-
// Extract the latest macOS (darwin) download URL
230-
re := regexp.MustCompile(`/dl/go[0-9]+\.[0-9]+\.[0-9]+\.darwin-arm64.pkg`)
231-
matches := re.FindStringSubmatch(body)
232-
if len(matches) == 0 {
233-
return "", fmt.Errorf("failed to find Go download URL")
234-
}
235-
goURL := "https://go.dev" + matches[0]
236-
237-
// Extract the Go version number from the URL
238-
reVersion := regexp.MustCompile(`[0-9]+\.[0-9]+\.[0-9]+`)
239-
versionMatches := reVersion.FindStringSubmatch(goURL)
240-
if len(versionMatches) == 0 {
241-
return "", fmt.Errorf("failed to find Go version in URL")
242-
}
243-
goVersion := versionMatches[0]
244-
245-
return goVersion, nil
212+
resp, err := http.Get("https://go.dev/dl/")
213+
if err != nil {
214+
return "", fmt.Errorf("failed to fetch Go download page: %v", err)
215+
}
216+
defer resp.Body.Close()
217+
218+
if resp.StatusCode != http.StatusOK {
219+
return "", fmt.Errorf("failed to fetch Go download page: status code %d", resp.StatusCode)
220+
}
221+
222+
bodyBytes, err := io.ReadAll(resp.Body)
223+
if err != nil {
224+
return "", fmt.Errorf("failed to read response body: %v", err)
225+
}
226+
body := string(bodyBytes)
227+
228+
// Extract the latest macOS (darwin) download URL
229+
re := regexp.MustCompile(`/dl/go[0-9]+\.[0-9]+\.[0-9]+\.darwin-arm64.pkg`)
230+
matches := re.FindStringSubmatch(body)
231+
if len(matches) == 0 {
232+
return "", fmt.Errorf("failed to find Go download URL")
233+
}
234+
goURL := "https://go.dev" + matches[0]
235+
236+
// Extract the Go version number from the URL
237+
reVersion := regexp.MustCompile(`[0-9]+\.[0-9]+\.[0-9]+`)
238+
versionMatches := reVersion.FindStringSubmatch(goURL)
239+
if len(versionMatches) == 0 {
240+
return "", fmt.Errorf("failed to find Go version in URL")
241+
}
242+
goVersion := versionMatches[0]
243+
244+
return goVersion, nil
246245
}
247246

248247
// allAppsBuilt returns an error if any apps are missing a build artifact.
@@ -265,4 +264,4 @@ func allAppsBuilt(discoveredApps map[string]*models.LaunchConfig, builtApps []*c
265264
}
266265
}
267266
return fmt.Errorf("applications %s not built", strings.Join(missing, ", "))
268-
}
267+
}

internal/catapult/catapult.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func New() *Catapult {
3636
// we only have the proto and hostname. There are two separate
3737
// variables provided to provide legacy support so clean up both
3838
// possibilities
39-
url := strings.TrimSuffix(environment.CatapultURL, "/v2/catapult")
39+
url := strings.TrimSuffix(environment.CatapultURL(), "/v2/catapult")
4040
url = strings.TrimSuffix(url, "/catapult")
4141
var rt http.RoundTripper = &basicAuthTransport{}
4242
cli := client.New(url, fmtPrinlnLogger{}, &rt)
@@ -52,9 +52,9 @@ func (c *Catapult) Publish(ctx context.Context, artifacts []*Artifact) error {
5252
grp.Go(func() error {
5353
fmt.Println("Publishing", art.ID)
5454
err := c.client.PostCatapultV2(grpCtx, &models.CatapultPublishRequest{
55-
Username: environment.CircleUser,
56-
Reponame: environment.Repo,
57-
Buildnum: environment.CircleBuildNum,
55+
Username: environment.CircleUser(),
56+
Reponame: environment.Repo(),
57+
Buildnum: environment.CircleBuildNum(),
5858
App: art,
5959
})
6060
if err != nil {
@@ -81,9 +81,9 @@ func (c *Catapult) Deploy(ctx context.Context, apps []string) error {
8181
fmt.Println("Deploying", app)
8282
err := c.client.PostDapple(ctx, &models.DeployRequest{
8383
Appname: app,
84-
Buildnum: environment.CircleBuildNum,
85-
Reponame: environment.Repo,
86-
Username: environment.CircleUser,
84+
Buildnum: environment.CircleBuildNum(),
85+
Reponame: environment.Repo(),
86+
Username: environment.CircleUser(),
8787
})
8888
if err != nil {
8989
return fmt.Errorf("failed to deploy %s: %v", app, err)
@@ -98,7 +98,7 @@ func (c *Catapult) Deploy(ctx context.Context, apps []string) error {
9898
type basicAuthTransport struct{}
9999

100100
func (ba *basicAuthTransport) RoundTrip(r *http.Request) (*http.Response, error) {
101-
r.SetBasicAuth(environment.CatapultUser, environment.CatapultPassword)
101+
r.SetBasicAuth(environment.CatapultUser(), environment.CatapultPassword())
102102
return http.DefaultTransport.RoundTrip(r)
103103
}
104104

internal/docker/docker.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ type Docker struct {
3838

3939
// New initializes a new docker daemon client and caches ecr credentials
4040
// for all 4 regions.
41-
func New(ctx context.Context) (*Docker, error) {
41+
func New(ctx context.Context, ecrUploadRole string) (*Docker, error) {
4242
cl, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation())
4343
if err != nil {
4444
return nil, fmt.Errorf("failed to initialize client: %v", err)
4545
}
4646
d := &Docker{
4747
cli: cl,
48-
awsCfg: environment.AWSCfg(ctx, environment.OidcEcrUploadRole),
48+
awsCfg: environment.AWSCfg(ctx, ecrUploadRole),
4949
}
5050

5151
grp, ctx := errgroup.WithContext(ctx)

internal/docker/targets.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ func BuildTargets(apps map[string]*models.LaunchConfig) (map[string]DockerTarget
4040
artifacts = append(artifacts, &catapult.Artifact{
4141
RunType: string(models.RunTypeDocker),
4242
ID: name,
43-
Branch: environment.Branch,
44-
Source: fmt.Sprintf("github:Clever/%s@%s", environment.Repo, environment.FullSHA1),
45-
Artifacts: fmt.Sprintf("docker:clever/%s@%s", artifact, environment.ShortSHA1),
43+
Branch: environment.Branch(),
44+
Source: fmt.Sprintf("github:Clever/%s@%s", environment.Repo(), environment.FullSHA1()),
45+
Artifacts: fmt.Sprintf("docker:clever/%s@%s", artifact, environment.ShortSHA1()),
4646
})
4747

4848
// Any apps with a shared artifact only need to be built and
@@ -59,7 +59,7 @@ func BuildTargets(apps map[string]*models.LaunchConfig) (map[string]DockerTarget
5959
for _, region := range environment.Regions {
6060
tag := fmt.Sprintf(
6161
"%s.dkr.ecr.%s.amazonaws.com/%s:%s",
62-
environment.ECRAccountID, region, artifact, environment.ShortSHA1,
62+
environment.ECRAccountID(), region, artifact, environment.ShortSHA1(),
6363
)
6464
tags = append(tags, tag)
6565
}

0 commit comments

Comments
 (0)