Blog

How To Create A Scheduled Cloud Build Trigger With Terraform

18 May, 2022
Xebia Background Header Wave

Scheduled builds are useful for recurring tasks such as nightly tests. Scheduling a build with Cloud Build, however, requires additional infrastructure to trigger the build. In this blog I'll show you how to use Terraform to configure a Manual trigger and trigger it with Cloud Scheduler.

Remark Sadly we can't use Terraform for all infrastructure. The source repository connection requires you to install the GitHub App -or similar- once.

Create a scheduled build

A scheduled build is created by defining the build trigger and configuring a job to run the build trigger. The required code is shown next.

resource "google_cloudbuild_trigger" "example" {
  project = "example"
  name    = "example"

  source_to_build {
    repo_type = "GITHUB"
    uri       = "https://github.com/binxio/scheduled-trigger-example"
    ref       = "refs/heads/main"
  }

  git_file_source {
    path = "cloudbuild.yaml"

    repo_type = "GITHUB"
    uri       = "https://github.com/binxio/scheduled-trigger-example"
    revision  = "refs/heads/main"
  }
}

resource "google_cloud_scheduler_job" "example_nightly" {
  project = "example"
  region  = "europe-west1" # NOTE: Scheduler availability is limited
  name    = "example-nightly"

  schedule  = "0 0 * * *"
  time_zone = "Europe/Amsterdam"

  attempt_deadline = "120s"

  http_target {
    http_method = "POST"
    uri         = "https://cloudbuild.googleapis.com/v1/projects/example/triggers/${google_cloudbuild_trigger.example.trigger_id}:run"

    oauth_token {
      service_account_email = google_service_account.build_runner.email
    }
  }
}

resource "google_service_account" "build_runner" {
  project      = "example"
  account_id   = "build-runner"
}

resource "google_project_iam_member" "build_runner_build_editor" {
  project = "example"
  role    = "roles/cloudbuild.builds.editor"
  member  = "serviceAccount:${google_service_account.build_runner.email}"
}

Bonus: Reduce scheduled job permissions

You might have noticed that we granted Cloud Build Editor permissions to the Scheduled Job. This is overkill, because we only need the cloudbuild.builds.create-permission to run a trigger. In the next example, the IAM assignment is replaced with a custom role.

resource "google_project_iam_custom_role" "build_runner" {
  project     = "example"
  role_id     = "buildRunner"
  title       = "Build Runner"
  description = "Grants permissions to trigger Cloud Builds."
  permissions = ["cloudbuild.builds.create"]
}

resource "google_project_iam_member" "build_runner_build_runner" {
  project = "example"
  role    = google_project_iam_custom_role.build_runner.name
  member  = "serviceAccount:${google_service_account.build_runner.email}"
}

While this is better. We are still not applying least privilege. First, the cloudbuild.builds.create permissions allows for more than running a trigger. I'm hoping for a future cloudbuild.builds.run permission to replace this. Second, the role is assigned at the Project-level. In effect you can trigger any build. Again, I'm hoping for a future Build Trigger level IAM permission to replace this.

Conclusion

Creating scheduled build triggers is as easy as configuring a couple of resources. However, beware of the excessive IAM permissions required to trigger a build.

Image by Andreas Lischka from Pixabay

As a cloud consultant I enjoy taking software engineering practices to the cloud. Continuously improving the customers systems, tools and processes by focusing on integration and quality.

Explore related posts