Modern Frontend CI/CD Architecture — The Missing Guide (Part. 3)

This is the third part of the “Modern Frontend CI/CD Architecture — The Missing Guide” series. We recommend you read the 1st part about how to set up a Continous Integration pipeline and the 2nd part about the Continuous Deployment.
tl;dr: The complete diagram of the Frontend CI/CD architecture pipeline.

Bonuses…

Now that we have both the Continuous Integration and Deployment working, let’s add some useful, yet important features.

Comment the Preview Link on the according PR on GitHub

1.a Create a GitHub Access Token

In order for us to create a comment on the GitHub PR, we will need to get a Personal Access Token (PAT) from GitHub in order to talk with the GitHub API.

Make sure you select the public_repo scope for this token. That's all what we need:

IMPORTANT: Write down this token, we will need it in the next step.

Note: We recommend you to create a GitHub app for this purpose if you are setting this CI/CD pipeline in your organisation. For the sake of this post, we will keep this process simpler to follow along. So a basic PAT will be sufficient for our need.

1.b Use the Google KMS service to store the GitHub PAT

Access tokens are by definition private tokens and mustn’t be shared publicly nor versioned in Git. So, in order to use the PAT with our CI/CD pipeline without having to hard code the token in the cloudbuild.yaml file, we need to store the PAT in the Cloud Key Management Service (KMS).

Like any API on the GCP, we need to enable the KMS usage before using it with our project:

The KMS API

Next, we need to create a Key-ring (or a Cryptographic key) that will hold our private token. From the menu sidebar, head to the Security entry, and choose the Cryptographic Keys option:

Once there, we will create a global Key-ring and call it GITHUB_ACCESS_TOKEN for simplicity:

Now, let’s encrypt and store our GitHub PAT in KMS:

IMPORTANT: Write down the base64 output, we will need it in the next step.

Before we move on, we just need to grant the Cloud Build service account permission to decrypt our encrypted access token. This will be needed in the next step:

1.c Comment the Preview Link on the GitHub

Now that we have securely stored the GitHub Personal Access Token, we can now add an additional step in the Cloud Build configuration file that will push a new comment on the PR providing the newly created Preview Link.

For this step, we will use the google/cloud-sdk:alpine because it provides us with the Bash, cURL and Python commands needed by our custom github-create-comment.bash script.

When running the custom script, we need to provide it with a couple of environment variables:

  • PREVIEW_BUILD_URL: containing the newly created preview link;
  • COMMIT_SHA: containing the SHA of the commit that triggered this build. We will use this particular SHA to identify the exact GitHub PR we will comment on (read below).

Since the custom script will require the GitHub access token in order to create the comment, and since our GitHub token is now securely encrypted and stored in the KMS service, we need to tell the Cloud Build service to use the GITHUB_ACCESS_TOKEN key from KMS. We do this by configuring the secrets.kmsKeyName and secrets.secretEnv.GITHUB_ACCESS_TOKEN entries in the cloudbuild.yaml file. Read more about using encrypted resources with Cloud Builds.

Let’s now have a look at the github-create-comment.bash script. What it does is basically:

  1. Use the commit SHA to query GitHub’s GraphQL API for the PR that contains this particular commit. Here is the GraphQL query:

Where:

  • REPO_NAME is xlayers/xlayers;
  • COMMIT_SHA is $COMMIT_SHA from the Cloud Build environment.

Using the subject ID — which represents the GitHub issue ID — we can now create a new comment on that issue. We will use a GraphQL mutation operation to insert a new comment:

Where:

  • ISSUE_ID is the subject ID got from the previous query request;
  • BODY_CONTENT is the issue content.

Here is the complete BASH script:

Note: the GraphQL requests were formatted for the cURL command.

Voilà!!!

The preview URL for this particular build has been correctly generated and it is pointing to the right container, and we can even check the Build ID that we stamped in the index.html of our app (at the footer):

Lastly, the preview URL is also correctly pushed to the right Github PR:


Notes & Optimisations

These notes apply to the 3 parts of this series.
  1. Security: Deployments (and hence preview links) will run on each PR — against any commit — pushed by anyone! You might want to enable this feature for core team members or specific contributors, both for security and performance reasons.
  2. Build Optimisations: We didn’t apply any optimisations while building the containers snapshots. You might want to use some caching to accelerate this process. Read more about how to speed up your builds.
  3. Tooling: We did not use Helm nor any other K8s package manager for this post. We wanted to focus on the core features. It is up to you to use such tools to help you manage your K8s clusters.
  4. You might also want to clean up the Pods, Services and Container images (snapshots) that are related to GitHub PRs that were already either merged or closed, or have an invalid state.
  5. Here is the complete diagram of the architecture we have just built (click to zoom):

Congratulations! You now have a complete and fully custom CI/CD pipeline that you can adapt to your needs. Have fun! 🎊

A special shout-out to David Gageot for helping out with the k8s Ingress configuration!


Follow @manekinekko for more updates about Web and Cloud technologies.