Publish your next Hugo blog post automatically while you sleep using Github Actions

The Challenge

I wanted to be able to publish a new post that has already been written at a future date, without needing to manaully publish the article.

The Solution

Github Actions.

I already push updates to my site using github actions. So I thought why not have articles published in the future after they are written.

A little background. I do all my edits in a private GitHub repo. When I push to master in this repo. A workflow action is triggered that causes my live site to be updated. The automatic merge that this system creates, results in my live site being updated without my taking further actions. See my previous post.

How I implemented this:
I added the file publish.yml to my .github/workflows folder.

Note:
cron runs based on UTC time. So you will need to take that into account when you define your cron job’s time.

If you need some help understanding the crontab format. I would refer you to crontab.guru

name: Publish Future Article
on:
  schedule:
    - cron: '30 0 8 8 *' # Publish at 00:30 on August 8th UTC time.


jobs:
  createPullRequest:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          ref: site-update

      # Required to make this commit ahead of the actual push
      - name: Make changes to pull request
        run: date +%s > lastAutoUpdate.txt

      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v3.1.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          commit-message: Ready to publish
          committer: GitHub <noreply@github.com>
          author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
          signoff: false
          base: master
          branch: PublishArticle
          title: 'PublishNewArticle'
          body: |
            Testing to publish a new article.
          labels: |
            automerge

This published my new article at 00:30 on August 8th UTC.

Note:

  1. ref: site-update tells the action which branch to copy to generate the pull request.
  2. base: master tells the action which branch the pull request should be merged into.
  3. branch: PublishArticle the new temporary branch that the pull request will create. It will be deleted by the auto merge action listed below.
  4. The automerge label is needed to trigger the next action script that follows.

The next thing to do is to create an action that will actually merge this new pull request.

I created a file again in the .github/workflows called automerge.yml.

This file contains:

name: automerge
on:
  pull_request:
    types:
      - opened
  status: {}
jobs:
  automerge:
    runs-on: ubuntu-latest
    steps:
      - name: Merge pull requests
        uses: pascalgn/automerge-action@v0.9.0
        env:
          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
          MERGE_DELETE_BRANCH: true

I think this whole workflow could be improved to add more useful information to the generated pull_request. Something to consider.

In order to use these actions in the current form. You will need to edit the cron: time each time you want to have an article published in the future. Also note that cron does not support year. So if you leave this cron in place. It will run at the same time each year.

I should also point out that the merge actually triggers a push to master. This results in the live site being updated from this private repo.

4 Likes

Maybe I’m missing something, but this seems a little roundabout?

Hugo won’t include posts with a future date by default (note --buildFuture/-F), so you should be able to simply

  • commit the post with the date you want in its meta data to master, and
  • build and publish master on a schedule every night (in particular, no changing the workflow file for each post).

Not sure if you were looking for some other gain from that MR workflow, but for the problem statement up top it doesn’t seem necessary.

3 Likes

Thanks for your feed back.

You are probably right.

I would probably simplify this now. Though using a specific cron time instead of nightly would have a couple of benefits.

  1. Save on GitHub action processing time.
  2. Avoid updating the site when it not required.
  3. Publish an article at exactly the time I want. This might be needed if you are under an embargo and can not publish before a given date/time. But you still want to be one of the first to publish. (I personally do not have this requirement)

Of note: The cron appears only to work if its part of the master branch, at least at the time that I wrote the original post.

Github Actions can be triggered via their API. You’d have to run that on a schedule in some way, though. If you don’t have an always-on machine, it probably won’t work out for you?

Coming up with a Github Action that can check whether there’s any new or updated content (date or lastMod between this and the last workflow run?) might be an interesting exercise. If so, running that check on a frequent schedule wouldn’t incur too much costs, if still some.