Creating a Reusable GitHub Action to Automatically Format a README for a TIL Repository
2020-04-26

TIL Auto-Format README Action on Github Marketplace
cflynn07/til

TIL Repo Example

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.

.github/workflows/action.yml
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: cflynn07/github-action-til-autoformat-readme@1.1.0
      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][1], and he was
          apparently inspired by Josh Branchaud's [TIL collection][2].
        footer: |
          [1]: https://simonwillison.net/2020/Apr/20/self-rewriting-readme/
          [2]: https://github.com/jbranchaud/til
        list_most_recent: 2

The action writes the README.md file to the repo, commits and pushes it back.

I built the action with Go and used a multi-stage build to keep the resulting image as small as possible by using an alpine image with the built binary.

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 in the 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.

Back to Top


Back to Top