How to deploy a Next.js application running on Cloud Run via GitHub Actions
2022-01-25
GCPNext.jsCloud RunGitHub ActionsAs I posted before, this blog is running on GCP Cloud Run and also is built with Next.js.
Previously, before migrating to Next.js from Gatsby, this blog used to get deployed automatically via GitHub Actions every time PR is merged. In case you're interested, see this post for details.
GitHub Actions Dependencies
In terms of interacting with GCP, it depends on the following actions:
- google-github-actions/setup-gcloud for preparation to get connected with GCP
- README describes they have multiple ways for authorization, but using
credentials_json
might be the easiest way, though it'd be less secure than usingworkload_identity_provider
.
- README describes they have multiple ways for authorization, but using
- google-github-actions/deploy-cloudrun is a handy workflow to interact with Cloud Run specifically
- As it is dedicated to deploy Cloud Run application, it supports almost all of options Cloud Run provides.
YAML
The following YAML configuration is to:
- get authorization with GCP
- build a docker image that contains my application, i.e. this blog
- deploy the image on Cloud Run
- delete an older revision in Cloud Run to clean up
- not going to describe detail, but every PR gets deployed to Cloud Run as a preview version
name: main
on:
push:
branches:
- master
paths:
- '**.js'
- '**.ts'
- '**.tsx'
- 'src/**'
- 'content/**'
- '**.yaml'
env:
PROJECT_ID: ${{ secrets.GCP_PROJECT }}
SERVICE: blog
REGION: asia-northeast1
URL_MAP: ${{ secrets.GCP_URL_MAP }}
jobs:
run:
runs-on: ubuntu-latest
permissions:
contents: 'read'
id-token: 'write'
steps:
- uses: actions/checkout@v2
- name: setup node
uses: actions/setup-node@v2
with:
node-version: '17.x'
cache: 'yarn'
- name: authenticate with GCP
id: auth
uses: google-github-actions/auth@v0.4.2
with:
credentials_json: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v0.3.0
with:
project_id: ${{ env.PROJECT_ID }}
- name: Docker login on GCR
run: |
gcloud auth configure-docker --quiet
- name: Set revision
id: revision
env:
TZ: 'Asia/Tokyo'
run: |
echo "::set-output name=REVISION::$(date '+%Y%m%d')-${GITHUB_SHA::6}"
- name: Set docker image
id: image
run: echo "::set-output name=IMAGE::asia.gcr.io/${{ env.PROJECT_ID }}/${{ env.SERVICE }}:${{ steps.revision.outputs.REVISION }}"
- name: build docker image
run: | # yarn and yarn build will be running while building docker image
docker build -t ${{ steps.image.outputs.IMAGE }} .
- name: docker push
run: |
docker push ${{ steps.image.outputs.IMAGE }}
- name: Deploy to Cloud Run
uses: google-github-actions/deploy-cloudrun@v0.6.0
with:
service: blog
image: ${{ steps.image.outputs.IMAGE }}
region: asia-northeast1
no_traffic: false
tag: "v${{ steps.revision.outputs.REVISION }}" # need to start with an alphabetical letter
- name: Updates traffic
uses: google-github-actions/deploy-cloudrun@v0.6.0
with:
service: blog
tag_traffic: "v${{ steps.revision.outputs.REVISION }}=100"
region: asia-northeast1
cleanup:
needs: run
runs-on: ubuntu-latest
permissions:
contents: 'read'
id-token: 'write'
steps:
- uses: actions/checkout@v2
- name: authenticate with GCP
id: auth
uses: google-github-actions/auth@v0.4.2
with:
credentials_json: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v0.3.0
with:
project_id: ${{ env.PROJECT_ID }}
- name: delete last merged PR's preview revision
run: |
pr_number="$(git log --grep="Merge pull request #[0-9]\+" --pretty=oneline -1 | grep -E -o "#[0-9]+" | tr -d "#" | tr -d '\n')"
if [ -n "${pr_number}" ]; then
echo "Merged PR: #${pr_number}"
# disable the revision
gcloud run services update-traffic ${{ env.SERVICE }} --remove-tags pr-${pr_number} --region ${{ env.REGION }} --quiet
# delete the revision
gcloud run revisions delete "${{ env.SERVICE }}-pr-${pr_number}" --region ${{ env.REGION }} --quiet
fi
That's it.
As you might know, GCP offers Cloud Build that enables building application images in automated fashion.
See the document:
Deploying to Cloud Run | Cloud Build Documentation | Google Cloud
In addition to deploying to Cloud Run, I wanted to control traffic and manage preview versions as the above snippet shows.