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