I recently looked at how I could setup my Google App Engine apps to continuously deploy. I host the source code for these apps in GitHub and typically use Travis CI GitHub Actions for builds, but getting it to do the deployment would mean giving it admin credentials to App Engine and I’ve avoided introducing secrets into my CI config because I don’t like granting heavy admin permissions across services.

In July 2018 Google Cloud Build added support for a GitHub App integration that connects Build to GitHub. Pushes to GitHub will kick off builds in Build and Build can be configured with permissions to deploy to App Engine without needing to expose write permissions to other services.

In Google Cloud Platform most resources exist inside a project. The GitHub app will be bound to one project, so I’ve found if you want to deploy multiple GitHub repositories to different projects, it’s more straight forward to create a separate project for connecting to GitHub. That project can be given permission to deploy to the other projects. I’ll call this the build project and the other projects that I deploy to an app project.

This is what I needed to do to set it up:

Step 1: Install the Google Cloud Build app on GitHub.

Step 2: Enable App Engine’s Admin API on your build project.

Step 3: Get the project number of the build project from its settings page.

Step 4: In the app project IAM page add a member for the build project with the name and roles below so that the build project can deploy to the app project.

Name: <build-project-number>@cloudbuild.gserviceaccount.com

Roles:

  • Service Account User - Allows the build project to act as a service account user.
  • App Engine Deployer - Allows the build project to deploy an app.
  • App Engine Service Admin - Allows the build project to promote and scale a new version being deployed.
  • Storage Object Admin - Allows the build project to write app files to Google Cloud Storage which is part of the deployment process.
  • Cloud Build Service Account - Allows the build project to kick off builds of new versions being deployed.

The IAM pages for both the app project and build project will end up looking something like this:

Step 5: Add a cloudbuild.yaml to the root of your repository replacing <project-name> with the project the app will be deployed to. E.g.:

steps:
- name: 'gcr.io/cloud-builders/gcloud'
  args: ['app', 'deploy', '--project=<app-project-name>', '--version=$SHORT_SHA']

You can use the $SHORT_SHA variable substitution to set the version of the App Engine deployment to match the 7 character short sha of the commit being deployed.

Push a commit to the GitHub repository and watch the Build history in the build project. You should see a new build show up that will deploy the app to the app project.

Update (2021-05-11): In October 2020 Google Cloud started requiring the Service Account User role as well. There are details about this on Google’s issue tracker: https://issuetracker.google.com/issues/170538212.

Update (2021-10-30): I now use GitHub Actions instead of Travis CI after this incident.