3 min read

Serverless LaTeX resume generation with GitHub Actions

Recently while searching for my next professional challenge I took the time to polish my resume.
Serverless LaTeX resume generation with GitHub Actions
A (not very) funny meme so I have a thumbnail for the post

Recently while searching for my next professional challenge I took the time to polish my resume.

I had two important factors in mind:

  1. The resume should be version controlled
  2. It should be pretty

The basics

The first constraint ruled out basic word processing tools like Word or Google Docs as although they do have some form of version control, but it’s very platform-specific and clunky to use to say the least.

After years of classical conditioning, as a developer whenever I think version control my Pavlovian reflex is always Git. Git is amazing at version controlling text documents and a resume is, well, just a text document. But plain text is not pretty enough to satisfy my second constraint.

Which brings us to TeX/LaTeX.

TeX is both a program (which does the typesetting, tex-core) and format (a set of macros that the engine uses, plain-tex). Looked at in either way, TeX gives you the basics only. If you read the source for The TeXBook, you’ll see that Knuth wrote more macros to be able to typeset the book, and made a format for that.

LaTeX is a generalised set of macros to let you do many things. Most people don’t want to have to program TeX, especially to set up things like sections, title pages, bibliographies and so on. LaTeX provides all of that: these are the ‘macros’ that it is made up of. (source)

Automating things

After a few hours of playing around with LaTeX, I quickly realised that spinning up a deployment environment is more complicated than the time I want to spend on it so I turned to Docker.

I have created a simple Dockerfile based on Ubuntu that does the dirty work and suddenly my platform specific (thanks m1 mac!) issues were gone.FROM ubuntu:latestRUN apt-get update && apt-get upgrade -y \
   && apt-get install texlive-latex-base texlive-xetex texlive-latex-extra texlive-fonts-recommended xzdec -yWORKDIR /dataENTRYPOINT [ "/bin/sh", "-c", "xelatex -output-directory=out resume.tex"]

I also wanted to “deploy” the resume somewhere so I wouldn’t have to always keep the latest version on hand. I didn’t want to utilise any hosting service for this as I wanted to keep it as simple as possible.

Enter Github Actions

As I’m already using Github, my idea was that I just automate the compilation step with it’s built-in CI/CD framework and save the results straight back into the repository, so I will always be able to use a link to the latest version.

Thankfully this was generally painless to achieve with the following Github Actions workflow:name: Update that resume!on: pushjobs:
   runs-on: ubuntu-latest
   name: A job to generate CV pdf on push
   - name: Checkout
     uses: actions/checkout@v2
   - name: Run CV generation
     uses: ./ # Uses an action in the root directory- name: Commit files
     id: commit
     run: |
       git config --local user.email "action@github.com"
       git config --local user.name "github-actions"
       git add --all
       if [-z "$(git status --porcelain)"]; then
          echo "::set-output name=push::false"
          git commit -m "Updated Resume via GH Actions." -a
          echo "::set-output name=push::true"
     shell: bash
   - name: Push changes
     if: steps.commit.outputs.push == 'true'
     uses: ad-m/github-push-action@master
        github_token: ${{ secrets.GITHUB_TOKEN }}

The workflow is triggered on a push event and firstly it checks out the commit then builds the rendered resume using the action in the root folder.

The action is defined in action.yml and looks like this:name: 'Build LaTeX resume PDF'
description: 'Commit to master to trigger auto build, pdf in out folder'
 using: 'docker'
 image: 'Dockerfile'

All that happens here is that our Dockerfile gets built & ran.

The next step in the workflow is some magic which makes Github Actions commit the new files generated by the previous step back into the repository.

The job takes around 1:20 seconds to run in total.

Github Actions job results

Bonus — move to the cloud

The last annoying step was having to pull/push changes to/from the remote repo after adding my changes to the raw document. This was not very cloud-native of me.

By utilising the built-in web-based editor on Github my new workflow to update my resume looks like this:

  1. Head over to https://github.com/danthelion/resume
  2. Press “.” (the dot button invokes the editor and loads the current repository)
  3. Update the raw document
  4. Commit my changes and watch GitHub generate a fresh, beautiful .pdf version of my resume and commit it back to the repository under https://github.com/danthelion/resume/blob/master/out/resume.pdf


Did I save time by doing this? Probably not. Was it fun? Yep!

Probably the funniest part is that after all this I ended up joining a company that uses a resume-less interview process (👋 Brooklyn Data!).

Ps. The resume template currently in the repo is from https://github.com/posquit0/Awesome-CV, thank you posquit0, amazing stuff!