Creating a Reusable GitHub Action to Automatically Format a README for a TIL Repository
While doing my daily browsing of Hacker News, I came across this post (Hacker News) by Simon Wilson on the merits of writing small, actionable TILs “Today I Learned’s.” and how he leverages GitHub Actions to automatically generate a README file based on the contents of his TIL repository (simonw/til).
I like the idea of a TIL repo and using GitHub Actions to automate indexing. Other people use GitHub actions to index their TIL repository READMEs, however all the examples I could find used GitHub Actions to run a script that was included in their repository. This works but it seemed like a reusable GitHub Action that could be quickly dropped into a TIL repo would be useful for many people.
I’ve been using GitHub actions for a few months and I’ve found it to be useful. Free and easy to use CI/CD platforms that integrate with GitHub event hooks to run arbitrary code on push events have existed for years. The niceness of GitHub Actions is the tight integration with GitHub and the focus on encouraging users to create an ecosystem of small, reusable discrete “Actions” that can be dropped into others’ workflows. The fact that these actions can essentially be docker containers that receive a repository mounted as a volume inside the container makes it very easy to build reliably consistent actions.
This is how the action can be added to a TIL repo.
name: Build README on: push: branches: - master paths-ignore: - README.md jobs: build: runs-on: ubuntu-latest steps: - name: Check out repo uses: actions/checkout@v2 with: # necessary for github-action-til-autoformat-readme fetch-depth: 0 - name: Autoformat README uses: firstname.lastname@example.org with: description: | A collection of concrete writeups of small things I learn daily while working and researching. My goal is to work in public. I was inspired to start this repository after reading Simon Wilson's [Hacker News post], and he was apparently inspired by Josh Branchaud's [TIL collection]. footer: | : https://simonwillison.net/2020/Apr/20/self-rewriting-readme/ : https://github.com/jbranchaud/til list_most_recent: 2
The action writes the README.md file to the repo, commits and pushes it back.
FROM golang:1.14 as builder WORKDIR /go/src/app COPY . . RUN go build -mod=vendor -o /go/bin/main . FROM alpine:latest WORKDIR /root RUN apk update && apk add git COPY --from=builder /go/bin/main ./main COPY --from=builder /go/src/app/README.md.tmpl ./README.md.tmpl COPY --from=builder /go/src/app/entrypoint.sh ./entrypoint.sh ENTRYPOINT [ "/root/entrypoint.sh" ]
When the GitHub Actions runner runs a reusable action, it essentially builds
the docker image from scratch each time based on the action’s Dockerfile.
Building the above Dockerfile for each GitHub Action run is a little slow and
also isn’t necessary. Instead, in the repository that holds my GitHub action I
have a GitHub Action workflow that builds, tags and pushes a base image to
Docker Hub whenever a new release/tag is created. That base image is referenced
Dockerfile in the action repository root:
FROM cflynnus/github-action-til-autoformat-readme:1.1.0 #tagged base image ENV TEMPLATE_PATH “/root/README.md.tmpl” ENV REPO_PATH “/github/workspace”
This way, when this action is run in a workflow the runner only has to build this workflow which is much faster than the multi-stage build. The resulting image is ~14Mb.