This article describes how I update my website with a fixed schedule, with the Github Actions (GA) and a beta-prod design. After reading this post you will know how to set up a CICD that update your website in a fixed schedule, at the same time you can keep pushing your updates to a beta stage and check whether it looks good in a public endpoint.

Why update the website with a fixed schedule

I came across this idea from Yihui Xie, who didn't update for a whole year. I found a scheduled update a good idea. I usually spent duplicate efforts checking if there was an update in people’s blogs. By telling readers the expected schedule, the author saves the readers effort of constant checking. Furthermore, the schedule hints how fast the author iterates the website/content, and readers can decide at the first sight whether the blog is worth a bookmark.

Workflows: Makefile for the local, and Github Action configs for the remote

To achieve our goal we need a CICD. Here we push our content to a Github repo and use Github Actions (GA) to deploy it to AWS (in my case, S3) and expose the content to the public. There are two considerations worth noting.

Makefile for the local

I decided to contain all website-related logic in a Makefile, so that I can manually trigger it at local for testing, and ask GA to reuse it. A common Makefile includes the common tasks for iterating our blog: cleaning, forcefully regenerating contents, live testing with a server, deployment to beta/prod stages:

html:
# some logic
clean:
# some logic
regenerate:
# some logic
devserver:
# some logic

deploy-beta: html
    aws s3 sync $(OUTPUTDIR) $(WEBSITE_S3_BETA)
deploy-prod: html
    aws s3 sync $(OUTPUTDIR) $(WEBSITE_S3)

One note is that we need to separate the environment variables (secrets) out, so that you don’t commit them to the repo. You can use a .secret file at local to manage them and ask git to ignore it. You just need to source it in your Shell session before you develop. This design also allows you to use different keys for deployment. For example, you might want a more admin-like key at local, and a more restricted key for GA for the deployment.

Github Action configs for the remote

With deployment logic in Makefile, we are clear that GA is only responsible for the machine and any failure can be attributed to the environment. Therefore, in GA config, we will leverage public actions to setup the running environment, and leverage Makefile in the repo to deploy the contents. In this way, the GA config is largely agnostic to your business logic. To update with a fixed schedule, the content should be held before the prod stage. At the same time, we want a remote test (as opposed to local test) to see if our content looks good. Thus this leads to a beta-prod design: when we push our updateto repo, GA “beta job” deploys the content to a cloud-based/accessible endpoint so that I can ensure things look good. Once settled, at each scheduled time the GA “prod job” deploys the content to the main website. We can use the GA if clause to ensure that only when the github event is triggered by a scheduled job do we deploy the content to prod. This way also reuses the runner setup config and keeps all deployment logic within the same workflow. A sample below:

on:
  push:
    branches:
      - main
  schedule: 
      - cron: "0 0 1 * *"
jobs:
  deploy:
    name: Update blog contents
    runs-on: ubuntu-18.04

    steps:
      - uses: actions/checkout@v2
      - name: Install dependencies
            # some logic
      - uses: aws-actions/configure-aws-credentials@v1
            # some logic
      - name: Upload to beta
            # some logic
        run:
            # some logic
      - name: Upload to prod
        if: ${{ github.event_name=='schedule' }}
        run:
            # some logic
Comments

comments powered by Disqus

Published

Category

research

Tags