Automated Pull Requests for Hugo Updates with Github-CI

Building upon my last post about automated regression testing for Hugo I wanted to create a scheduled workflow that would issue pull requests for Hugo updates.

We’re working with just a single file today. Let’s name it hugo-updates.yml and put it with the rest of your github workflow files.

Steps



Check the latest release

In this first step we need to check the latest release from the github api and compare it to our .hugoversion. We also need to use workflow commands so that we can use these variables later in the workflow.

name: Check for new Hugo versions

on:
  workflow_dispatch:
  schedule:
    - cron: 0 0 1,15 * * # Every 1st and 15th of the month

jobs:
  hugo-updates:
    runs-on: ubuntu-latest
    steps:
    - name: Check for new hugo version
      id: versions
      run: |
        # Find the latest release
        NEW=$(curl -s https://api.github.com/repos/gohugoio/hugo/releases/latest | jq -r .name)
        
        # Download current .hugoversion file
        wget https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_SHA/.hugoversion
        OLD=$(cat .hugoversion)

        echo "::set-output name=new::$NEW"
        echo "::set-output name=old::$OLD"
        echo "$OLD == $NEW"        

We wget the .hugoversion here to save a little time in the case that there is no new version instead of cloning the whole repository.


Clone the repository

This is the first step with a conditional. All future steps will have this same condition and will therefore be skipped if there is not a new version.

    - name: Clone the repository
      if: steps.versions.outputs.new != steps.versions.outputs.old
      uses: actions/checkout@v2
      with:
        ref: master

Modify the .hugoversion

    - name: Modify .hugoversion
      if: steps.versions.outputs.new != steps.versions.outputs.old
      env:
        VERSION: ${{ steps.versions.outputs.new }}
      run: echo -ne $VERSION > .hugoversion

Get release notes

In this step we use the github api again to get the release notes for the new version. We need to escape some characters before setting the output to preserve the newlines.

    - name: Get hugo release notes
      id: release
      if: steps.versions.outputs.new != steps.versions.outputs.old
      env:
        VERSION: ${{ steps.versions.outputs.new }}
      run: |
        RELEASE_NOTES="$(
          curl -s https://api.github.com/repos/gohugoio/hugo/releases \
            | jq -r --arg version $VERSION \
                '.[] | select(.tag_name == $version) | .body'
        )"
        # Escape \n, \r and %
        RELEASE_NOTES="${RELEASE_NOTES//'%'/'%25'}"
        RELEASE_NOTES="${RELEASE_NOTES//$'\n'/'%0A'}"
        RELEASE_NOTES="${RELEASE_NOTES//$'\r'/'%0D'}"
        echo "::set-output name=notes::$RELEASE_NOTES"        

Generate a special auth token for Github

This step isn’t actually required unless you would like the pull request created to trigger other workflows (like the regression test workflow in the last post). Pull requests created with a GITHUB_TOKEN cannot trigger them so we use a different type of authentication that can. Here’s a great guide on how to use a GitHub App to generate a token.

    - name: Generate token for Pull Request
      id: generate-token
      uses: tibdex/github-app-token@v1
      if: steps.versions.outputs.new != steps.versions.outputs.old
      with:
        app_id: ${{ secrets.PR_APP_ID }}
        private_key: ${{ secrets.PR_APP_PRIVATE_KEY }}

Create the pull request

Finally, we create the pull request!

    - name: Create Pull Request
      uses: peter-evans/create-pull-request@v3
      if: steps.versions.outputs.new != steps.versions.outputs.old
      with:
        token: ${{ steps.generate-token.outputs.token }}
        labels: test-for-regression
        branch: hugo-${{ steps.versions.outputs.new }}
        commit-message: Update Hugo to ${{ steps.versions.outputs.new }}
        title: Update Hugo to ${{ steps.versions.outputs.new }}
        body: |
          👑 Hugo update!

          # ${{ steps.versions.outputs.new }} Release Notes
          ${{ steps.release.outputs.notes }}          

Thank you

Your comment has been submitted and will be published once it has been approved.

OOPS!

Your comment has not been submitted. Please go back and try again. Thank You!

If this error persists, please open an issue by clicking here.

Say something