Schedule Statiq Deploy with Github Actions

USING GITHUB ACTIONS TO AUTOMATE STATIQ DEPLOYMENTS

by

Github Actions is a powerful tool to help you add dynamic functionality to your static website. This tutorial will walk you through how to schedule automatic deployments for sites built with Statiq.Web, a .NET Core static site generator, but the principles can be extended for use with preferred static site generator, such as Gatsby, Hugo, or Jekyll.

Configure Statiq

Suppose you have a site built with Statiq. Tip: you can use my Statiq blog boilerplate to get a headstart. Next, configure a deployment pipeline that works for you (AWS, Azure App Service, GitHub Pages, Netlify, etc). In this example, I will be deploying to Netlify.

Statiq.Web includes built-in pipelines for deploying to common sources. To deploy to Netlify, for example, simply invoke the DeployToNetlify method to the Statiq Bootstrapper in Program.cs and pass your Netlify site's ID and your personal access token.

.DeployToNetlify(
	Environment.GetEnvironmentVariable("NetlifySiteId"),
	Environment.GetEnvironmentVariable("NetlifyAccessToken")
)

I am passing these values as environment variables with names NetlifySiteId and NetlifyAccessToken. We will configure the values for these environment variables in GitHub.

Using GitHub Secrets

Rather than setting the values for environment variables directly in the GitHub Action workflow, we will use GitHub's Secrets functionality. In your GitHub repository, navigate to Settings > Secrets. Here, you can add new secrets to be used in your project. I created a secret to hold the values for my Netlify access token and for my Netlify project's Site Id. You can use any name you want, but I used the same names as my environment variables NetlifySiteId and NetlifyAccessToken to keep thing simple.

Using GitHub Actions

Now, set up a GitHub Actions workflow. If you start with the .NET Core workflow, it will scaffold an Ubuntu environment with .NET Core configured. This will give you an idea about the structure of the GitHub Actions workflow

name: .NET Core

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 3.1.101
    - name: Install dependencies
      run: dotnet restore
    - name: Build
      run: dotnet build --configuration Release --no-restore
    - name: Test
      run: dotnet test --no-restore --verbosity normal

This is a good start, but we need to make some changes. First, change the name on Line 1 to something more meaningful, like Scheduled Deploy. Now would also be a good time to change the filename. Again, something like scheduled-deploy.yml will work.

Next, set up the environment variables your project needs at the end of the file by adding an env: section. Environment variables are configured with the following syntax name: value. In this case, we will pull the values from the encrypted GitHub secrest we created earlier.

env:
  NetlifySiteId: ${{ secrets.NetlifySiteId }}
  NetlifyAccessToken: ${{ secrets.NetlifyAccessToken }}

By default, this workflow is scheduled to run when a new commit is pushed to the repo or when a new pull request has been created. I am only interested in re-deploying when code is committed to the master branch or when a pull request is merged (not when one is created). On GitHub, since merging a pull request automatically triggers a push event, I will just remove the on: pull_request trigger.

However, in this example, I also want to automatically re-deploy every day at 05:00 UTC. Something like this could be useful for scheduling posts or for regularly fetching content from a dynamic source, like a database or API. To do this, I can add a cron job to run this workflow at set intervals. The first part of my workflow, now looks like the following:

name: Scheduled Deploy

on:
  push:
    branches:
      - master
  schedule:
  - cron: "0 5 * * *"

I will keep the first part of the build: section from the scaffolded workflow, because I do want to checkout the master branch and set up .NET Core.

jobs:
  build:
  runs-on: ubuntu-latest
  steps:
  - uses: actions/checkout@v2
    with:
      ref: master
  - name: Setup .NET Core
    uses: actions/setup-dotnet@v1
    with:
      dotnet-version: 3.1.101

If no arguments are passed to the checkout action, it will checkout the master branch. Above, I have made checking out the master branch explicit, so you will know how use a different branch if your use case requires it.

The only dependency required by Statiq is .NET Core itself, so we do not need to run dotnet restore.

However, if your project has javascript or css dependencies installed by libman or npm, now is the time to configure the required tools and restore those. To use libman, for instance, you must first add libman's command line tool and then use the tool to restore your project's dependencies

- name: Install Libman
  run: dotnet tool install -g Microsoft.Web.LibraryManager.CLI
- name: Restore dependencies
  run: libman restore

Note: If you have a multi-project solution or need to run this tool from a different directory for some other reason, you can set the working directory in GitHub Actions as follows:

- name: Install Libman
  run: dotnet tool install -g Microsoft.Web.LibraryManager.CLI
- name: Restore dependencies
  working-directory: ./MySite.Blog
  run: libman restore

Finally, run your build and pass the deploy command to automatically execute the deployment pipelines, such as the one we configured for Netlify.

- name: Deploy
  run: dotnet run -- deploy

Here, you can also configure a working-directory or specifically launch any build profiles you have configured in launchSettings.json.

- name: Deploy
      working-directory: ./MySite.Blog
      run: dotnet run --launch-profile "Production" -- deploy

Completed GitHub Actions Workflow

Your completed GitHub Actions workflow for automating Statiq deployments may look like the following:

name: Scheduled Deploy

on:
  push:
    branches:
      - master
  schedule:
  - cron: "0 5 * * *"
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
      with:
        ref: master
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 3.1.101
    - name: Install Libman
      run: dotnet tool install -g Microsoft.Web.LibraryManager.CLI
    - name: Restore dependencies
      working-directory: ./MySite.Blog
      run: libman restore
    - name: Deploy
      working-directory: ./MySite.Blog
      run: dotnet run --launch-profile "Production" -- deploy
      env:
        NetlifySiteId: ${{ secrets.NetlifySiteId }}
        NetlifyAccessToken: ${{ secrets.NetlifyAccessToken }}

Don't stop learning!

There is so much to discover about C#. That's why I am making my favorite tips and tricks available for free. Enter your email address below to become a better .NET developer.


Did you know?

Our beautiful, multi-column C# reference guides contain more than 150 tips and examples to make it even easier to write better code.

Get your cheat sheets