Automating the Launch and Update of a Website Using Cloud Run and GitHub Actions: Part 2
GDG Cloud Lahore
The place for cloud developers to come together to learn, and explore the latest advances in cloud technologies.
Contributed by : Adil Shahzad
GitHub Repo Source Code : https://github.com/GDGCloudLahore/cloud-run-sample
Hello Cloud Enthusiasts ??,
Welcome back to another installment of the GDG Cloud Lahore series! Previously, we delved into building and deploying images to Cloud Run ??. Today, we're going to explore how to automate this process using GitHub Actions ???. We'll be utilizing the code provided above, so please feel free to clone it and practice alongside us. If you encounter any issues, don't hesitate to ask questions in the comment section ??. We also welcome any feedback on topics you'd like us to cover in future series related to GDG Cloud Lahore ??.
What is Cloud Run?
Write code your way by deploying any container that listens for requests or events. Build applications in your favorite language, with your favorite dependencies and tools, and deploy them in seconds.
Cloud Run abstracts away all infrastructure management by automatically scaling up and down from zero almost instantaneously — depending on traffic. Cloud Run only charges you for the exact resources you use.
Cloud Run makes app development and deployment simpler and faster. And it’s fully integrated with Cloud Code, Cloud Build, Cloud Monitoring, and Cloud Logging for an enhanced end-to-end developer experience.
What are GitHub Actions?
GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want.
GitHub Action has a free tier of 2,000 minutes per month.
Developer Workflow for CI/CD and Getting Started With It
The CI/CD pipeline starts when a developer submits new code to GitHub. This action triggers automated workflows within GitHub Actions, where the code is built into a Docker image. Once the image is successfully built, it’s pushed to a Docker image registry. From there, the image is deployed to Cloud Run, making the updated application available for users. This seamless process ensures that code changes are efficiently and reliably delivered as live updates.
name: Build and Deploy to Google Cloud Run
on:
push:
branches:
- main
workflow_dispatch:
env:
PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
SERVICE_NAME: ${{ secrets.CLOUD_RUN_SERVICE_NAME }}
GCR_HOSTNAME: gcr.io
GCR_REGISTRY: us-west3-docker.pkg.dev
GCR_IMAGE: gdgcloudlahore-419421
GCR_REGION: us-west3
jobs:
setup-build-publish-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Necessary to fetch all tags and history
- name: Determine new version
id: versioning
run: |
git fetch --tags
# Check if any tags exist
if [ $(git tag | wc -l) -eq 0 ]; then
echo "No tags found. Please create an initial tag."
exit 1 # Exit with error if no tags are found
else
LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1`)
fi
echo "Latest tag is $LATEST_TAG"
# Prepare the next tag without the 'v' prefix
NEXT_TAG=$(echo $LATEST_TAG | sed 's/v//g' | awk -F. '{$NF = $NF + 1;} 1' | sed 's/ /./g')
echo "Attempting new tag $NEXT_TAG"
# Check if the NEXT_TAG already exists
if git rev-parse "v$NEXT_TAG" >/dev/null 2>&1; then
echo "New tag v$NEXT_TAG already exists. Using the latest tag $LATEST_TAG instead."
# If NEXT_TAG exists, we stick with LATEST_TAG and do not create a new one.
echo "NEW_TAG=$LATEST_TAG" >> $GITHUB_ENV
else
echo "New tag is $NEXT_TAG"
# Add 'v' prefix when creating the tag in git
git tag "v$NEXT_TAG"
git push origin "v$NEXT_TAG"
# Use the successfully created new tag without the 'v' prefix in the workflow.
echo "NEW_TAG=$NEXT_TAG" >> $GITHUB_ENV
fi
- name: Set up Cloud SDK
uses: google-github-actions/[email protected]
with:
version: 'latest'
service_account_email: ${{ secrets.GCP_SA_EMAIL }}
service_account_key: ${{ secrets.GCP_SA_KEY }}
project_id: ${{ env.PROJECT_ID }}
export_default_credentials: true
- name: Login to GCR
uses: docker/login-action@v3
with:
registry: gcr.io
username: _json_key
password: ${{ secrets.GCP_SA_KEY}}
- name: Setup Project
run: |
gcloud auth configure-docker ${GCR_REGISTRY}
- name: Build image Build and Tag
run: |
DOCKER_BUILDKIT=0
docker build -t ${GCR_REGISTRY}/${{ secrets.GCP_PROJECT_ID }}/${GCR_IMAGE}/helloworld:${{ env.NEW_TAG }} .
- name: Docker Push to Google Registry
run: |
docker push ${GCR_REGISTRY}/${{ secrets.GCP_PROJECT_ID }}/${GCR_IMAGE}/helloworld:${{ env.NEW_TAG }}
- name: Deploying Cloud Run with Latest image
run: |
gcloud run deploy helloworld \
--region ${GCR_REGION} \
--image ${GCR_REGISTRY}/${{ secrets.GCP_PROJECT_ID }}/${GCR_IMAGE}/helloworld:${{ env.NEW_TAG }} \
--platform managed \
--allow-unauthenticated \
--project ${{ secrets.GCP_PROJECT_ID }}
Alright, let's break down this GitHub Actions workflow into an easy-to-understand explanation:
How is Authentication of GitHub Action and GCP Working?
The diagram you're looking at represents a secure handshake between GitHub and Google Cloud to make sure that updates or deployments are done safely and automatically. When you trigger a GitHub Actions workflow, GitHub confirms its identity to Google Cloud using what's called an OIDC provider. Google Cloud then checks this identity and, if everything looks good, it gives GitHub a temporary pass — sort of like a VIP badge — that lets GitHub access your cloud resources. This badge is only good for the job at hand and expires right after, keeping your cloud resources secure.
Authentication
Creating a Service Account
The GitHub runner operates in their own data center, so we need to authenticate the calls to our GCP project. GitHub also provides the capability to have the actions running within your own environment, but that will be a topic for another post. To achieve this, we will create a Service Account and add the keys to the GitHub Secrets section.
领英推荐
Save it.
In the next page, click on the service account name and click on Add Key
Click on Create a new key and leave it to the JSON format and click create. You should download a JSON key.
Add the Service Account credentials to GitHub
You will also need to enable the Cloud Run API and Container Registry API:
Now, once you have configured the GitHub secrets and Google Cloud API connections, the next step is to create the Google Cloud Registry. You can create it manually and pass the value to the GitHub Action workflow. You can manually trigger the GitHub action, and it will first create a new version tag, then log in to GCR using your service connection authentication, set your registry, build and tag your registry image with the latest tag, and then push it to GCR images. Finally, you can deploy the image to Cloud Run. Once you receive the following output, it means your Cloud Run is up and running, and whenever a change is made to GitHub, it will automatically be pushed to Cloud Run. The next step is to lock the main/master branch and restrict developers from pushing changes directly. Instead, they should create a pull request, and after review, you can merge it to the master and deploy your code to the Cloud Run. You can also set up different environments, i.e., Dev, QA, and Production, and set up your Cloud Run environment accordingly. Here is the final output from the GitHub actions:
Here you can see the website version is up and running
Clean UP
So…
You could see the GitHub Actions integrates smoothly with GCP. You also have an option to use your own runner inside your own environment if you are concern about security and data on someone's server.
Cloud Run is pretty straight forward as well, and I do recommend you have a try if serverless is an option for you — and you don’t want to care about servers.
You can also see a fully working version on GitHub : https://github.com/GDGCloudLahore/cloud-run-sample
Please feel free to comment and let me know if you have any questions.
References