I recently migrated my website content away from a traditional web server host to Github Pages.

A key feature that initially inspired me to make this migration in the first place, is to figure out how to make use of Github automated functionality to schedule future post content.

Instead of needing to remind myself to manually rebuild my site and FTP it up to my host when needed, I wanted a way of writing a few articles on the weekend and letting them “self publish” on a specific future date.

In Content Management Systems like WordPress, it’s a trivial task to set your posts publication date to some future time at which point you have the confidence in the post being made publically available on that set future time.

Let’s sit down and achieve the same functionality (and confidence) with Github Pages!

The Gameplan

While I’m not after any kind of granular levels type of publication, I’m completely “ok” with the idea of a scheduled post being made available sometime during a 24-hour period.

There’s a few small things we’re after:

  • Create an Access Token
  • Create an environment secret with the Access Token
  • Configure Jekyll to ignore content with future dates
  • Update the Github Pages automation to trigger a page build
  • Some kind of scheduled trigger mechanism

Create an Access Token

  • Within your Github repo, you can navigate over to https://github.com/settings/tokens
  • Click on the “New” button to create a new token
  • Give it some kind of human friendly name for yourself, such as “Github Pages Scheduled” or something
  • You will need to assign it some permissions. There’s a long list to choose from, but you only need the public_repo setting checked
  • In the last step, copy this token into your favorite password management tool, or wherever you’re storing your passwords. This is a temporary display of your token - you WON’T be able to see it again - so don’t lose it

That covers “step 1”. This token is required, as our automated Github Action will be making use of it when running a job for you.

Create a “Secret” for your new Access Token

  • Now that you have your secret generated, open the repository for your GitHub Pages site
  • Click on Settings then the Secrets menu option
  • Create a new secret with the name USER_TOKEN, and paste in the token you just created
  • Save things

Configuring Jekyll

Now let’s update your site’s _config.yml with some entries:

future: false
timezone: your_timezone (eg. America/Dawson)

  • The future: false setting configures Jekyll to ignore the publication of content that has a future date-timestamp at the time of a build
  • For The timezone entry, use your local timezone from this list of TZ database time zones

Configuring a Jekyll Post

Once we’ve updated the main site configuration, we can go into the frontmatter of any blog post / content that you want to publish sometime in the future.

Simply update the date field within the blog posts frontmatter up at the top of the file:

date: 2022-08-07 14:25:52

  • The date should be in the format of YYYY-MM-DD HH:MM:SS
  • Only the “date” part of that is REALLY necessary, but thanks to the timezone setting that we updated in the _config.yml file, we can achieve some accurate level of a timestamp

So as it currently stands, from now on whenever we push some content up to our Github Page repository, posts tagged with a future datetime stamp will not be published.

The final piece: adding a Github Action

  • In your repository, add a .github/workflows set of folders
  • Within the new workflows subfolder, create schedule-posts.yml

Let’s take a look at this new .yml file:

name: scheduling post action
  # Triggers the workflow on a scheduled event
    - cron: '15 6 * * *' # 6:15 AM every day.
    # cron: '15 6 * * 1,5,6' will schedule 06:15 every Monday, Friday and Saturday
    runs-on: ubuntu-latest
    - name: Trigger GitHub pages rebuild
      uses: wei/curl@master
        args: "-X POST -H 'Authorization: token ${{ secrets.USER_TOKEN }}' -H 'Accept: application/vnd.github.ant-man-preview+json' https://api.github.com/repos/${{ github.repository }}/pages/builds"
        # You must create a personal token with repo access as GitHub does
        # not yet support server-to-server page builds.
        USER_TOKEN: ${{ secrets.USER_TOKEN }}

  • name: give our Action a name
  • on: this is the trigger that the Action will listen for. We’re using schedule to run on a schedule
  • cron: this is our specified time to run our Action schedule. Check the documentation on how to specify the cron fields, but for my specific use case, I’m fine with just having this Action being run every morning at 06:15. Adjust your own time / specific day as necessary.

The jobs section is the “meat” of this workflow. Once our cron hits our specific time, this workflow will activate and run whatever is defined in jobs.

  • build is just the label of our job. We could easily rename this to job1
  • runs-on specifies what platform to execute our Action on, use ubuntu-latest to specify a Github-hosted runner
  • steps this is the sequence of tasks that can run commands, run tasks or run other Action automation. There are no step limits, so long as your Action is running within the GitHub workflow usage limits
  • name this is the name of the job, which is displayed on GitHub
  • uses this is an existing action to run as part of the entire job. In other words, we’re making use of a pre-existing actions, wei/curl@master. Note that GitHub action documentation encourages the use of specifying the version number to avoid any future unexpected behavior
  • with this will specify the command-line params to use in conjunction with curl - our uses Action.

In our case, we want to make use of the curl Action to send a POST request at the endpoint which will trigger a build of the Jekyll site.

Due to security access, we need to specify an Authorization header, which is created with help from the USER_TOKEN secret that we created earlier on!

I hope you got something out of this article, and it demonstrates some simple techniques that GitHub Actions can provide for your site!