Blog post publishing with GitHub Actions

January 28th 2022 GitHub

For quite some time I have been regularly publishing new blog posts every Friday morning. I have the code for my blog in a GitHub repository. Each unpublished blog post that I have prepared in advance is in its own branch. To publish it, I just need to merge it with the main branch, which triggers the GitHub workflow I set up to deploy the blog.

I have a notification reminding me to do the merge on Friday morning. But while this does not take much time, I finally decided to look for ways to automate this last step. I quickly found the Merge Schedule GitHub Action, which seemed to do almost exactly what I needed: merge a pull request on a scheduled day. Creating pull requests for my post branches is not a huge effort.

To configure the action, I created a .github/workflows/merge-schedule.yml file in my repository:

name: Merge Schedule
on:
  pull_request:
    types:
      - opened
      - edited
      - synchronize
  schedule:
    - cron: 0 6 * * *

jobs:
  merge_schedule:
    runs-on: ubuntu-latest
    steps:
      - name: Obtain GitHub App Installation Access Token
        id: githubAppAuth
        run: |
          TOKEN="$(npx obtain-github-app-installation-access-token ci ${{ secrets.GH_APP_CREDENTIALS_TOKEN }})"
          echo "::add-mask::$TOKEN"
          echo "::set-output name=token::$TOKEN"
      - name: Run merge schedule action
        uses: gr2m/merge-schedule-action@v1
        env:
          GITHUB_TOKEN: ${{ steps.githubAppAuth.outputs.token }}

I based the file on the file in the GitHub action documentation, but changed the schedule using cron syntax so that the action runs once a day in the morning instead of every hour. This allows me to specify only the publish date without time in the pull request description with the following syntax /schedule 2022-01-28.

I also had to replace the automatically created secrets.GITHUB_TOKEN token with the token I created myself. I learned the hard way that workflows do not trigger other workflows when they use the automatically created token. This meant that the post was not published, even though it was merged in the main branch, because the deployment workfklow was not triggered.

I initially tried to get it to work with a personal access token, but I could not find a way to give the action all the permissions it needed. The checks operations always failed with the following error message:

HttpError: You must authenticate via a GitHub App.

As the error message suggested, I ended up using a GitHub App. I could not find much documentation about it, but fortunately I stumbled across a very helpful blog post. It was enough to follow the steps in that post to get my workflow working:

  1. I created a new GitHub App. I gave it a name and set its Homepage URL to the URL of my blog repository. I unchecked the Active option for the Webhook and added the following permissions:

    • Actions: Read-only
    • Checks: Read & write
    • Contents: Read & write
    • Metadata: Read-only (mandatory for apps and set by default)
    • Pull requests: Read & write
  2. After creating the app, I copied the App ID (six-digit value) from the top of the page and generated a private key using a button at the bottom of the page. I downloaded the private key locally.

  3. Next, I clicked Install App from the sidebar at the top of the page and installed the app in my blog repository. After that, I was able to copy the installation ID from the URL of the page for that installation (seven-digit value).

  4. I was now ready to generate a credentials token and a sample workflow script using a web page created by the author of the helpful blog post. I entered the three pieces of information I had gathered so far:

    • the six-digit GitHub App ID
    • the seven-digit installation ID
    • the downloaded private key

    Generating the GitHub App credentials token

  5. I copied the generated credentials token value and used it to create a new actions secret in the Settings section of my blog repository called GH_APP_CREDENTIALS_TOKEN.

    Creating a new actions secret for a GitHub repository

  6. I copied the first step of the generated sample workflow script into my final workflow script above and replaced the source for the GITHUB_TOKEN value with ${{ steps.githubAppAuth.outputs.token }} as seen in the second step of the sample workflow script.

That's it. When I now create a new pull request for a blog post with the schedule in the description, I can see that it is scheduled to publish on the selected day:

GitHub Pull Request scheduled for merge

And in the Actions section of my blog repository, I can see that the Merge Schedule workflow runs every morning:

Run history for Merge Schedule workflow

There is already a huge collection of GitHub actions. So even for someone like me who only knows the basics of GitHub actions, it's easy to create workflows to automate all sorts of tasks in a GitHub repository. Automating the publishing of my blog posts only took me a couple of hours, including testing.

Get notified when a new blog post is published (usually every Friday):

Copyright
Creative Commons License