diff --git a/README.md b/README.md index cca9b85..8fc58eb 100644 --- a/README.md +++ b/README.md @@ -380,6 +380,7 @@ Currently, supported CI are here: - Jenkins - GitLab CI - GitHub Actions +- Google Cloud Build ### Private Repository Considerations GitHub private repositories require the `repo` and `write:discussion` permissions. @@ -390,6 +391,17 @@ GitHub private repositories require the `repo` and `write:discussion` permission - Environment Variable - `PULL_REQUEST_NUMBER` or `PULL_REQUEST_URL` are required to set by user for Pull Request Usage +### Google Cloud Build Considerations + +- These environment variables are needed to be set using [substitutions](https://cloud.google.com/cloud-build/docs/configuring-builds/substitute-variable-values) + - `COMMIT_SHA` + - `BUILD_ID` + - `PROJECT_ID` + - `_PR_NUMBER` +- Recommended trigger events + - `terraform plan`: Pull request + - `terraform apply`: Push to branch + ## Committers * Masaki ISHIYAMA ([@b4b4r07](https://github.com/b4b4r07)) diff --git a/ci.go b/ci.go index e6159c6..f77cc03 100644 --- a/ci.go +++ b/ci.go @@ -146,3 +146,19 @@ func githubActions() (ci CI, err error) { ci.PR.Revision = os.Getenv("GITHUB_SHA") return ci, err } + +func cloudbuild() (ci CI, err error) { + ci.PR.Number = 0 + ci.PR.Revision = os.Getenv("COMMIT_SHA") + ci.URL = fmt.Sprintf( + "https://console.cloud.google.com/cloud-build/builds/%s?project=%s", + os.Getenv("BUILD_ID"), + os.Getenv("PROJECT_ID"), + ) + pr := os.Getenv("_PR_NUMBER") + if pr == "" { + return ci, nil + } + ci.PR.Number, err = strconv.Atoi(pr) + return ci, err +} diff --git a/ci_test.go b/ci_test.go index 7bd29bb..7d0eac9 100644 --- a/ci_test.go +++ b/ci_test.go @@ -759,3 +759,89 @@ func TestGitHubActions(t *testing.T) { } } } + +func TestCloudBuild(t *testing.T) { + envs := []string{ + "COMMIT_SHA", + "BUILD_ID", + "PROJECT_ID", + "_PR_NUMBER", + } + saveEnvs := make(map[string]string) + for _, key := range envs { + saveEnvs[key] = os.Getenv(key) + os.Unsetenv(key) + } + defer func() { + for key, value := range saveEnvs { + os.Setenv(key, value) + } + }() + + // https://cloud.google.com/cloud-build/docs/configuring-builds/substitute-variable-values + testCases := []struct { + fn func() + ci CI + ok bool + }{ + { + fn: func() { + os.Setenv("COMMIT_SHA", "abcdefg") + os.Setenv("BUILD_ID", "build-id") + os.Setenv("PROJECT_ID", "gcp-project-id") + os.Setenv("_PR_NUMBER", "123") + }, + ci: CI{ + PR: PullRequest{ + Revision: "abcdefg", + Number: 123, + }, + URL: "https://console.cloud.google.com/cloud-build/builds/build-id?project=gcp-project-id", + }, + ok: true, + }, + { + fn: func() { + os.Setenv("COMMIT_SHA", "") + os.Setenv("BUILD_ID", "build-id") + os.Setenv("PROJECT_ID", "gcp-project-id") + os.Setenv("_PR_NUMBER", "") + }, + ci: CI{ + PR: PullRequest{ + Revision: "", + Number: 0, + }, + URL: "https://console.cloud.google.com/cloud-build/builds/build-id?project=gcp-project-id", + }, + ok: true, + }, + { + fn: func() { + os.Setenv("COMMIT_SHA", "") + os.Setenv("BUILD_ID", "build-id") + os.Setenv("PROJECT_ID", "gcp-project-id") + os.Setenv("_PR_NUMBER", "abc") + }, + ci: CI{ + PR: PullRequest{ + Revision: "", + Number: 0, + }, + URL: "https://console.cloud.google.com/cloud-build/builds/build-id?project=gcp-project-id", + }, + ok: false, + }, + } + + for _, testCase := range testCases { + testCase.fn() + ci, err := cloudbuild() + if !reflect.DeepEqual(ci, testCase.ci) { + t.Errorf("got %q but want %q", ci, testCase.ci) + } + if (err == nil) != testCase.ok { + t.Errorf("got error %q", err) + } + } +} diff --git a/config/config.go b/config/config.go index d4411d9..b80f79c 100644 --- a/config/config.go +++ b/config/config.go @@ -146,6 +146,8 @@ func (cfg *Config) Validation() error { // ok pattern case "github-actions": // ok pattern + case "cloud-build", "cloudbuild": + // ok pattern default: return fmt.Errorf("%s: not supported yet", cfg.CI) } diff --git a/config/config_test.go b/config/config_test.go index e296373..9a48269 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -220,6 +220,14 @@ func TestValidation(t *testing.T) { contents: []byte("ci: gitlabci\n"), expected: "notifier is missing", }, + { + contents: []byte("ci: cloudbuild\n"), + expected: "notifier is missing", + }, + { + contents: []byte("ci: cloud-build\n"), + expected: "notifier is missing", + }, { contents: []byte("ci: circleci\nnotifier:\n github:\n"), expected: "notifier is missing", diff --git a/main.go b/main.go index dd0436f..505c9d7 100644 --- a/main.go +++ b/main.go @@ -82,6 +82,11 @@ func (t *tfnotify) Run() error { if err != nil { return err } + case "cloud-build", "cloudbuild": + ci, err = cloudbuild() + if err != nil { + return err + } case "": return fmt.Errorf("CI service: required (e.g. circleci)") default: