Thursday, October 8, 2020

GitHub Actions to Cloudflare Workers Sites

As time goes by, I’m looking for solutions that require as little maintenance as possible. One of those is deploying our client web app and our homepage directly on the CDN edge, with GitHub Actions.

Not only we don’t need a server to host the app, but the deployment script is also serverless and maintenance-less. This allows me to focus on important tasks, knowing that deployment and serving of the app is always blazing fast.

Cloudflare Workers Sites allows us to serve the app from Cloudflare’s network of CDN servers without any actual origin. The site is out there, in the cloud, being served faster than any regular website would be. It literally takes milliseconds for the site to load in your browser, wherever you are in the world. And that goes a long way for user experience.

GitHub Actions enables us to build simple (or complicated) deployment flows, building the app and deploying it to the corresponding location.

As of the writing of this article, I don’t think there’s a faster delivery system than hosting your website directly on the CDN edge.

I won’t go into the details of how Cloudflare Workers Sites works, since there’s a lot of documentation for that, however here’s our wrangler.toml file, used by Cloudflare to deploy the website into “the cloud”:

# Wrangler Configuration

# Resources:

name = "app-local"
type = "webpack"
account_id = "a1a5...ba43"
zone_id = "f3eb...3ea0"
workers_dev = true

bucket = "dist"
entry-point = "workers-site"

name = "app-staging"
route = "*"

name = "app-production"
route = "*"

This is pretty much it. Publishing the app from the local command line is just a matter of running:

$ wrangler publish --env staging

Now, for the automation part, here comes GitHub Actions. Our development flow involves pushing to staging any merge into the master branch, and pushing to production any new release published. For this to work, we have two workflow files, release.yml and staging.yml, the main differences between these is when it’s run and deployment keys.

name: CI-Staging

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
    branches: [ master ]
    branches: [ master ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
  # This workflow contains a single job called "build"
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    name: Deploy Staging (Master branch)
    # Steps represent a sequence of tasks that will be executed as part of the job
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - uses: actions/checkout@master
    - name: NPM or Yarn install with caching
      uses: bahmutov/npm-install@v1.1.0

    # Runs a single command using the runners shell
    - name: Install packages
      run: 'yarn install --frozen-lockfile --non-interactive'
    - name: Setup Environment
      run: |
        echo "VUE_APP_API_ENDPOINT=$API_ENDPONT" > ./.env
        echo "VUE_APP_PUSHER_KEY=$PUSHER_KEY" >> ./.env
        sed -i.bak -e"s|BUILD_ID|$GITHUB_RUN_ID|" src/service-worker.js        
    - name: Build APP
      run: 'yarn build'
    - name: Build Changelog
      run: yarn run changelog
    - name: Deploy to Cloudflare Workers with Wrangler
      uses: cloudflare/wrangler-action@1.1.0
          apiToken: ${{ secrets.CF_API_TOKEN }}
          environment: 'staging'

As for the releases, we want those deployed only when a release is published, so the workflow file begins with:

name: CI-Release

      - published

And that’s pretty much it. Now, whenever code is pushed to master, a PR to master is created or a new Release is published, GitHub actions builds the app and deploys it to the corresponding environment.

GitHub Actions Screenshot

Our web app GitHub Actions

I hope you found this article useful.

If you’re looking for a simple solution to detect downtime before your customers do, check out