diff --git a/builder/build/build.go b/builder/build/build.go index a03268a..5dbf495 100644 --- a/builder/build/build.go +++ b/builder/build/build.go @@ -38,6 +38,18 @@ func (b *Build) LoadBuildEnv() (map[string]string, error) { if val, ok := os.LookupEnv("ALLOW_EOL_SHIMMED_BUILDER"); ok { env["ALLOW_EOL_SHIMMED_BUILDER"] = val } + // map CodeBuild-specific vars to neutral CI vars and pass into Docker builds as build args + // and into buildpack builds as env vars + for k, v := range map[string]string{ + "CI_COMMIT_REF": GetenvFallback([]string{"CODEBUILD_WEBHOOK_HEAD_REF", "CODEBUILD_SOURCE_VERSION"}), + "CI_COMMIT_SHA": os.Getenv("CODEBUILD_RESOLVED_SOURCE_VERSION"), + "CI_BUILD_STARTED_AT": os.Getenv("CODEBUILD_START_TIME"), + "CI_REPOSITORY_URL": os.Getenv("CODEBUILD_SOURCE_REPO_URL"), + } { + if v != "" { + env[k] = v + } + } params, err := b.aws.GetParametersByPath(paths[0]) stripParamPrefix(params, paths[0], &env) if err != nil { diff --git a/builder/build/build_test.go b/builder/build/build_test.go index 7e760e5..0c2cdeb 100644 --- a/builder/build/build_test.go +++ b/builder/build/build_test.go @@ -80,6 +80,72 @@ func TestLoadEnvInheritance(t *testing.T) { } } +func TestLoadBuildEnvCIVars(t *testing.T) { + appName := "test-app" + mockedAWS := new(MockAWS) + appConfigPrefix := fmt.Sprintf("/apppack/apps/%s/config/", appName) + mockedAWS.On("GetParametersByPath", appConfigPrefix).Return(map[string]string{}, nil) + mockedState := emptyState() + mockedState.On("ReadEnvFile").Return(&map[string]string{}, nil) + + t.Setenv("CODEBUILD_WEBHOOK_HEAD_REF", "refs/heads/main") + t.Setenv("CODEBUILD_RESOLVED_SOURCE_VERSION", "deadbeef1234") + t.Setenv("CODEBUILD_START_TIME", "1234567890") + t.Setenv("CODEBUILD_SOURCE_REPO_URL", "https://github.com/org/repo") + + b := Build{ + Appname: appName, + CodebuildBuildId: CodebuildBuildId, + aws: mockedAWS, + state: mockedState, + Ctx: testContext, + } + env, err := b.LoadBuildEnv() + if err != nil { + t.Fatalf("expected no error, got %s", err) + } + if env["CI_COMMIT_REF"] != "refs/heads/main" { + t.Errorf("expected CI_COMMIT_REF=refs/heads/main, got %s", env["CI_COMMIT_REF"]) + } + if env["CI_COMMIT_SHA"] != "deadbeef1234" { + t.Errorf("expected CI_COMMIT_SHA=deadbeef1234, got %s", env["CI_COMMIT_SHA"]) + } + if env["CI_BUILD_STARTED_AT"] != "1234567890" { + t.Errorf("expected CI_BUILD_STARTED_AT=1234567890, got %s", env["CI_BUILD_STARTED_AT"]) + } + if env["CI_REPOSITORY_URL"] != "https://github.com/org/repo" { + t.Errorf("expected CI_REPOSITORY_URL=https://github.com/org/repo, got %s", env["CI_REPOSITORY_URL"]) + } +} + +func TestLoadBuildEnvCIVarsFallback(t *testing.T) { + // When CODEBUILD_WEBHOOK_HEAD_REF is not set, CI_COMMIT_REF should fall back to CODEBUILD_SOURCE_VERSION + appName := "test-app" + mockedAWS := new(MockAWS) + appConfigPrefix := fmt.Sprintf("/apppack/apps/%s/config/", appName) + mockedAWS.On("GetParametersByPath", appConfigPrefix).Return(map[string]string{}, nil) + mockedState := emptyState() + mockedState.On("ReadEnvFile").Return(&map[string]string{}, nil) + + t.Setenv("CODEBUILD_WEBHOOK_HEAD_REF", "") + t.Setenv("CODEBUILD_SOURCE_VERSION", "refs/heads/feature-branch") + + b := Build{ + Appname: appName, + CodebuildBuildId: CodebuildBuildId, + aws: mockedAWS, + state: mockedState, + Ctx: testContext, + } + env, err := b.LoadBuildEnv() + if err != nil { + t.Fatalf("expected no error, got %s", err) + } + if env["CI_COMMIT_REF"] != "refs/heads/feature-branch" { + t.Errorf("expected CI_COMMIT_REF=refs/heads/feature-branch, got %s", env["CI_COMMIT_REF"]) + } +} + func TestGenerateDockerEnvStrings(t *testing.T) { env := map[string]string{ "FOO": "bar",