I have implemented continuous delivery of Google AppEngine applications using CircleCI:
- Deploy to staging on pushing to
master
branch. - Deploy to production on pushing a tag matching
/^v\d+\.\d+\.\d+$/
.
This configuration is quite useful and I'm sure I'll have a chance to reuse it. In this article I describe the implementation details.
Create a Service Account
At first, I created a service account that will be used to authenticate Cloud SDK in CircleCI:
- Create a new account at Service Accounts of Google Cloud Platform Console:
- Named "circleci" to make it easy to guess what is's for.
- Created a key and download it in JSON.
- Attach roles to the created service account at IAM page:
- App Engine Deployer (
appengine.deployer
) - App Engine Service Admin (
appengine.serviceAdmin
) - Cloud Build Editor (
cloudbuild.builds.editor
) - Storage Object Creator (
storage.objectCreator
) - Storage Object Viewer (
storage.objectViewer
)
- App Engine Deployer (
Note that it may take a few minutes for the results to be reflected.
When you create a new GCP project, a xxx@cloudbuild.gserviceaccount.com
service account which has a Cloud Build Service Account role is created. You also need to attach the following role to the service account:
- Storage Object Viewer
Configure CircleCI
My GAE application uses nodejs10
runtime. I added following npm run scripts:
npm run test
- Run tests
npm run build
- Build project and put artifacts to the
/build
directory.
- Build project and put artifacts to the
And I implemented CD using those scripts.
Cloud SDK
I use google/cloud-sdk image which was described in How to Use Google Cloud SDK Using Docker:
Set the downloaded JSON key as GCLOUD_SERVICE_KEY
environment variable, then do following command to authenticate Cloud SDK:
echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account --key-file=-
workspace
Build artifacts (generated by npm run build
) are required to deploy.
Node.js is required to run npm
command but the google/cloud-sdk image does not contain Node.js runtime. There are some way to solve this problem:
- Create a Docker image with both Node.js and Cloud SDK and use it.
- Store build artifacts somewhere and use it in the Cloud SDK container.
I started by 1. but finally found that I can use workspaces to share files across jobs so adopted 2.
Deploy
gcloud app deploy
command deploys your application to GAE. I used the following options:
--version
- Give the version name.
- You can replace an existing version by specifing the same version name.
--no-promote
- Don't route traffic to the newly created version after deployment.
Conclusion
You may think it's hard to set up continuous delivery in the early stages of a project. However, from a medium- to long-term perspective, I think these efforts are worthwhile.