Harold L. Brown
Harold L. Brown

Reputation: 9946

Trigger Google Cloud Build with Google Cloud Scheduler periodically

Is it somehow possible to trigger a Google Cloud Build with Google Cloud Scheduler periodically?

I can't find anything related to it on the Internet.

Upvotes: 10

Views: 4544

Answers (4)

Douglas McGowan
Douglas McGowan

Reputation: 1

  • For this, I'm reusing the Service Account for both the schedule and the trigger. Ideally these should be separate
  • Also using google modules in places. Not sure how much value they add, but just using what I leveraged
  • Uses First Generation GitHub integration
#Trigger / Schedule Service Account
module "trigger_sa" {
  source  = "terraform-google-modules/service-accounts/google"
  version = "~> 4.2"

  project_id    = "my-project-id"
  names         = ["my-sa-name"]
  display_name  = "My SA Name"
  descriptions  = ["My CloudBuild and CloudTrigger Service Account"]
  project_roles = [
    "my-project-id=>roles/iam.serviceAccountUser",
    "my-project-id=>roles/cloudbuild.builds.editor",
    #ADD MORE PERMISSIONS HERE FOR THE ACTUAL TRIGGER AS NEEDED
  ]
}

#Trigger
resource "google_cloudbuild_trigger" "trigger" {

  project     = "my-project-id"
  location    = "australia-southeast1"
  name        = "my-trigger-name"
  description = "My CloudBuild Trigger Description"

  github {
    name  = "my-github-repo"
    owner = "repo-owner-name"

    push {
      branch = ".*" #We specify a wild card here. Run on any change detected in GitHub
    }
  }

  included_files     = [
    "include/these/files/*"
  ]

  service_account    = "projects/my-project-id/serviceAccounts/[email protected]"
  filename           = "cloudbuild.yaml"
  include_build_logs = "INCLUDE_BUILD_LOGS_WITH_STATUS"

  depends_on = [
    module.trigger_sa
  ]
}

#Schedule
resource "google_cloud_scheduler_job" "scheduler_job" {

  project     = "my-project-id"
  region      = "australia-southeast1"
  name        = "my-schedule-name"
  description = "My Schedule Description"
  schedule    = "0 1 * * 1"

  http_target {
    http_method = "POST"
    uri         = "https://cloudbuild.googleapis.com/v1/projects/my-project-id/locations/australia-southeast1/triggers/${google_cloudbuild_trigger.trigger.trigger_id}:run"
    body = base64encode(jsonencode({
      projectId = "my-project-id",
      triggerId = google_cloudbuild_trigger.trigger.trigger_id,
      source = {
        branchName = "main", #Schedule needs to tell the trigger which branch to look at
      }
    }))
    headers = {
      "Content-Type" = "application/json"
    }
    oauth_token {
      service_account_email = "[email protected]"
      scope                 = "https://www.googleapis.com/auth/cloud-platform"
    }
  }

  #Sticking to defaults for now
  retry_config {
    max_backoff_duration = "3600s"
    max_doublings        = 5
    max_retry_duration   = "0s"
    min_backoff_duration = "5s"
    retry_count          = 0
  }

  depends_on = [
    module.trigger_sa
  ]
}

Roles provide a bit more privilege than needed. If you want me to include a sample to create a custom role, let me know. But for now, keeping simple

Upvotes: 0

Cloudkollektiv
Cloudkollektiv

Reputation: 14669

The first option is to create a schedule to trigger a build:

gcloud scheduler jobs create http ${PROJECT_ID}-run-trigger \
    --schedule='0 12 * * *' \
    --uri=https://cloudbuild.googleapis.com/v1/projects/${PROJECT_ID}/triggers/${TRIGGER_ID}:run \
    --message-body='{\"branchName\": \"${BRANCH_NAME}\"}' \
    --oauth-service-account-email=${PROJECT_ID}@appspot.gserviceaccount.com \
    --oauth-token-scope=https://www.googleapis.com/auth/cloud-platform

Note that you can almost run this from within a cloud build. PROJECT_ID is the name of the project and BRANCH_NAME is the name of the branch (development, master, etc.). Both are available from within your cloud build pipeline. TRIGGER_ID can be fetched with the following command:

gcloud beta builds triggers list --format json

Additional to branchName, you can also specify other attributes in the message body, giving you more flexibility:

  • commitSha
  • dir
  • invertRegex
  • projectId
  • repoName
  • substitutions
  • tagName

The second option is to submit a cloudbuild on a schedule:

gcloud scheduler jobs create http ${PROJECT_ID}-run-build \
    --schedule='0 12 * * *' \
    --uri=https://cloudbuild.googleapis.com/v1/projects/${PROJECT_ID}/builds \
    --message-body-from-file=cloudbuild.json \
    --message-body="{\"branchName\": \"${BRANCH_NAME}\"} \
    --oauth-service-account-email=${PROJECT_ID}@appspot.gserviceaccount.com \
    --oauth-token-scope=https://www.googleapis.com/auth/cloud-platform

Your cloudbuild.json can look something like this:

{
    "timeout": "60s",
    "steps": [
        {
            "name": "gcr.io/cloud-builders/gcloud",
            "entrypoint": "bash",
            "args": [
                "-c",
                "echo "Hello"
            ]
        },
        {
            "name": "gcr.io/cloud-builders/gcloud",
            "entrypoint": "bash",
            "args": [
                "-c",
                "echo "World"
            ]
        }
    ],
    "substitutions": {
        "BRANCH_NAME": "$BRANCH_NAME"
    }
}

Upvotes: 14

Harold L. Brown
Harold L. Brown

Reputation: 9946

In Cloud Scheduler we perform a HTTP request on the project's build trigger: https://cloud.google.com/cloud-build/docs/api/reference/rest/v1/projects.triggers/run

For authentication we use a service account.

Upvotes: 8

pessolato
pessolato

Reputation: 1562

You can do that by making the Cloud Scheduler job target the Cloud Build projects.builds.create API to manually start your builds. With this you can pass a Build instance through the request body to specify your build.

Keep in mind that you will need to authenticate your request, check the Using authentication with HTTP Targets documentation for more information on how to do that.

Upvotes: 2

Related Questions