Author Avatar Image
Alexander Reelsen

Backend developer, productivity fan, likes distributed systems & the new serverless era

GitHub Actions: Updating a GitHub wiki after an edit
Oct 29, 2021
4 minutes read

TLDR; This is a reference for myself how you can change the contents of a GitHub wiki using a GitHub action.

So, the use-case to cover was to create a summary document, whenever the wiki was modified by someone. Luckily GitHub actions has a hook for this named gollum. In case you are wondering, this is the name of the wiki engine in use. See more in the official documentation.

So, how does an action look like? How about this to put in your .github/workflows folder:

name: Recreate wiki summary page on wiki changes

on:
  gollum:
  workflow_dispatch:

jobs:
  create-wiki-summary:
    runs-on: ubuntu-latest

    steps:
      - name: Check out repo
        uses: actions/checkout@v2
      - name: Check out wiki
        uses: actions/checkout@v2
        with:
          repository: 'user/my-repo.wiki'
          ref: 'master'
          path: 'my-repo.wiki'
      - name: Update summary.md if needed
        run: ./create-summary.sh $GITHUB_WORKSPACE/my-repo.wiki
        working-directory: ./my-directory

So, what happens here? Basically there are three steps

  • Check out the repo where this has been triggered
  • Check out the wiki into the directory my-repo.wiki - a GitHub wiki is stored in a GitHub repository as well, so checking it out is easy
  • Run the script in my-directory/create-summary.sh and pass the path of the repo as argument

Lastly the workflow_dispatch event exists to be able to trigger this via the github actions tab of the repository.

The shell script (make sure it’s marked as executable) is extracting the last paragraph of each markdown file and appends it into another markdown file, so that the reader can possibly just look at that one instead of all pages individually:

#!/bin/bash

#########
# some debug output to check in case of failures
# also exit on any error
set -xe

cd $1

# Get the md5sum from the summary markdown file
md5=$(md5sum Summary.md)

# Run the summary
rm -f Summary.md
(
# exclude documents that you do not want to check
for i in $(find . -name '*.md' \
  '!' -name first-excluded-document.md \
  '!' -name further-excluded-document.md \
  '!' -name Summary.md | sort) ; do
  name=$(basename $i)
  name=${name/.md}
  cat $i | \
    # print everything after this point in the markdown
    sed -n -e '/## LAST PARAGRAPH TITLE/,$p' | \
    # replace title with name of the file
    sed -e 's@^## LAST PARAGRAPH TITLE@## '"$name"'@'
  echo
done
) > Summary.md

# Compare md5 sums
new_md5=$(md5sum Summary.md)

echo "Old md5 sum: $md5 ; New md5 sum: $new_md5"

if [ "$md5" != "$new_md5" ] ; then
  # this is required for the push to succeed
  git config --global user.email "team+github-action@elastic.co"
  git config --global user.name "Action McActionFace"
  git add Summary.md
  git commit -m "Update Summary.md at $(date)"
  git push origin master
fi

The shell script checks the md5sum of a certain markdown file, then goes on to create the summary, then checks the md5sum again, and only if those differ, the final markdown is committed.

There are two specialties here. First, the sed call. For every markdown file returnind from the find call, this gets run

cat $i | \
    # print everything after this point in the markdown
    sed -n -e '/## LAST PARAGRAPH TITLE/,$p' | \
    # replace title with name of the file
    sed -e 's@^## LAST PARAGRAPH TITLE@## '"$name"'@'

The first sed call returns everything till the end of the file, when ## LAST PARAGRAPH TITLE is found. This works in my case, because I only need to extract the last paragraph, but might differ in your use-case. The second part replaces the title with the name of file, so that it is easy to identify in the document.

The final part with all the git commands, ensures that the push is successful by setting the user name and emails plus creating a commit message for the wiki.

A new git commit should only be done if there have been actual changes to the part of the markdown that gets collected in the summary document - this is the reason for the md5 check.

That’s it. You could optimize this by inlining the shell script, so that it does not need to check out the repository, but I like this approach a little more than embed shell scripts in the github action.


Back to posts