Skip to main content

Github Actions

·952 words·5 mins
Devops Cloud Github CI/CD

Overview
#

Github Actions is Github’s CI/CD platform which enables automated build/test/deploy pipelines for Github repos. Workflows are custom defined and are event-triggered by actions taken upon the repo like pull requests.

Key Components
#

These are the foundational elements you should understand when starting out with Github Actions.

Workflows
#

Workflows are automated processes that run one or more jobs. Workflows are attached to repos, and there can be any number of them in a repo. Workflows are defined in YAML files that lives in your repo in the .github/workflows directory. There are reserved keywords that are used to define different parts of the Workflow.

Jobs
#

Jobs are contained within workflows, and contain one or more steps that are executed in order. Jobs themselves run in parallel by default, but can be configured to run sequentially as well as conditionally. Again, there can be any number of jobs in a workflow.

Steps
#

Steps are the specific individual tasks contained within a job. The Steps themselves are either shell commands, or Github defined Actions. Any number of steps can be defined in a job, and they run in the order they are defined. Steps can be conditional, like Jobs.

Events
#

Events are the trigger conditions that cause workflows to execute. Events could be manual actions or things such as a push to the repo.

Runners
#

Runners are execution environments that jobs run within. Github offers pre-built Runners for MacOS, Linux, and Windows operating systems to execute steps within, and custom Runners can also be created and used.

Hugo Blog Publishing Use Case
#

One of the things I use Github actions for is to process and publish this very blog. The process goes like so:

graph TB;
A@{ shape: docs, label: "Draft posts in Markdown locally"}-->B@{ shape: trap-b, label: "Review by running hugo server locally"};
B-->C[Commit drafts to local repo];
C-->D[Push local repo to Github];
D-->E@{ shape: processes, label: "Github Action triggered by push Event"};
E-->F@{ shape: lin-cyl, label: "Rendered blog content published via Github Pages"};

Keywords Used in Workflow file
#

  • The name keyword to define the name of the Workflow
  • The on keyword defines the Events which trigger the Workflow execution
  • The jobs keyword has job names nested underneath it with the runs_on keyword to indicate which Runner execution environment to use
  • The steps keyword contains key/value pairs of each step
  • There is a a Github Action used in one of these steps to checkout the blog repo into the Runner
  • deploy is another Job which uses another Github Action which deploys the resulting Hugo-rendered blog to Github Pages
# Sample workflow for building and deploying a Hugo site to GitHub Pages
name: Deploy Hugo site to Pages

on:
  # Runs on pushes targeting the default branch
  push:
    branches:
      - main

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
  group: "pages"
  cancel-in-progress: false

# Default to bash
defaults:
  run:
    # GitHub-hosted runners automatically enable `set -eo pipefail` for Bash shells.
    shell: bash

jobs:
  # Build job
  build:
    runs-on: ubuntu-latest
    env:
      DART_SASS_VERSION: 1.89.2
      HUGO_VERSION: 0.148.0
      HUGO_ENVIRONMENT: production
      TZ: America/Los_Angeles
    steps:
      - name: Install Hugo CLI
        run: |
          wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb
          sudo dpkg -i ${{ runner.temp }}/hugo.deb
      - name: Install Dart Sass
        run: |
          wget -O ${{ runner.temp }}/dart-sass.tar.gz https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
          tar -xf ${{ runner.temp }}/dart-sass.tar.gz --directory ${{ runner.temp }}
          mv ${{ runner.temp }}/dart-sass/ /usr/local/bin
          echo "/usr/local/bin/dart-sass" >> $GITHUB_PATH
      - name: Checkout
        uses: actions/checkout@v4
        with:
          submodules: recursive
          fetch-depth: 0
      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v5
      - name: Install Node.js dependencies
        run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
      - name: Cache Restore
        id: cache-restore
        uses: actions/cache/restore@v4
        with:
          path: |
            ${{ runner.temp }}/hugo_cache
          key: hugo-${{ github.run_id }}
          restore-keys:
            hugo-
      - name: Configure Git
        run: git config core.quotepath false
      - name: Build with Hugo
        run: |
          hugo \
            --gc \
            --minify \
            --baseURL "${{ steps.pages.outputs.base_url }}/" \
            --cacheDir "${{ runner.temp }}/hugo_cache"
      - name: Cache Save
        id: cache-save
        uses: actions/cache/save@v4
        with:
          path: |
            ${{ runner.temp }}/hugo_cache
          key: ${{ steps.cache-restore.outputs.cache-primary-key }}
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ./public

  # Deployment job
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

Setup in Github
#

The entire setup for using Github Actions to render and publish blogs with Hugo is covered here. Github provides real-time feedback while Workflows are running.

In the image, you can see the build job completed in 52s, and the deploy job has been underway for 2:38s. These job runtimes vary quite a bit, likely due to current load on the environment where the Github Runners execute. I’ve seen my Workflow finish in under a minute, and over 6 minutes. One of the status indicators you’ll see indicates if your jobs are waiting in queue to start.

Once the job has completed, Github gives feedback along with a link to the published blog. I have Github Pages configured with a custom domain, but the blog is indeed hosted via Github Pages.

Conclusion
#

That was a brief look at Github Actions as CI/CD pipeline. There are much moire sophisticated workflows that can be built and my little example did not employ any sort of testing. I’ll look to incorporate Github Actions in a future post on a topic that uses Terraform to demonstrate more CI/CD features.