Skip to content

Version Control for your resume

Published:

In this blog post, I will discuss how to utilize version control and GitHub workflows for your LaTeX resume.

Table of Contents

Open Table of Contents

Introduction

Ever got tired of manually updating your resume every time you make a change? Or maybe you have multiple versions of your resume and you’re not sure which one is the most recent? This is where version control comes in handy. By utilizing version control, you can keep track of all the changes you make to your resume and easily revert back to a previous version if needed.

The Resume

I, like many other CS majors use the famous Jake’s Resume template for my resume. This template is written in LaTeX and is very easy to customize.

Jake's Resume

Setting up the Repository

The Workflow

The goal is to automatically compile the LaTeX file every time we push a change to the repository. Along with that, we also want to create a GitHub release (with the built PDF file) every time we push a new version of the resume. This way, you will always have access to all the pdf versions of your resume.

This is how the first few lines of your workflow file should look like:

name: Generate Resume

on:
  push:
    branches:
      - main

permissions:
  contents: write

jobs:

The build Job

build:
  runs-on: ubuntu-latest

  steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    - name: Build LaTeX environment
      uses: xu-cheng/latex-action@v3
      with:
        root_file: resume.tex

    - name: Upload artifact
      uses: actions/upload-artifact@v4
      with:
        name: resume
        path: resume.pdf

All we have to do here is to checkout the repository, build the LaTeX environment, and upload the built PDF file as an artifact. xu-cheng/latex-action is a GitHub action that can take care of the LaTeX compilation for us. It will use the specified root_file and compile it to a PDF file with the same name. We can then upload this PDF file as an artifact to use it in the subsequent jobs.

The version Job

This job can be as simple or as complex as you want. The purpose of this job is to simply emit a version number for the resume. You can use the commit hash, the date, or any other unique identifier as the version number. The below example snippet will use the current datetime as the version number.

version:
  runs-on: ubuntu-latest
  outputs:
    version: ${{ steps.version.outputs.version }}

  steps:
    - name: Set version
      id: version
      run: |
        datetime=$(date +'%Y-%m-%d+%H:%M:%S')
        version="v$datetime"
        echo "::set-output name=version::$version"

The release Job

This job will create a Git tag and a GitHub release every time we push a new version of the resume. The release will contain the built PDF file as an asset.

release:
  runs-on: ubuntu-latest
  needs: [build, version]

  steps:
    - name: Checkout repository
      uses: actions/checkout@v4
      with:
        ref: ${{ github.ref_name }}

    - name: Create a tag
      run: |
        git tag ${{ needs.version.outputs.version }}
        git push origin --tags

    - name: Download artifact
      uses: actions/download-artifact@v4
      with:
        name: resume
        path: out

    - name: Create release
      env:
        GH_TOKEN: ${{ github.token }}
      run: gh release create ${{ needs.version.outputs.version }} out/resume.pdf -t "Resume ${{ needs.version.outputs.version }}"

The deploy Job

This job’s purpose is to deploy the built PDF file to any cloud storage or web server. In my case, I will be deploying it to my website at this URL: cyril.pw/resume, this is done by committing the PDF file to a different repository of mine. You can modify this job to suit your needs. For example, you can save it in a public S3 bucket.

deploy:
  runs-on: ubuntu-latest
  needs: [build, version]

  steps:
    - name: Checkout repository
      uses: actions/checkout@v4
      with:
        repository: siriscmv/cyril.pw
        token: ${{ secrets.PAT }}

    - name: Download artifact
      uses: actions/download-artifact@v4
      with:
        name: resume
        path: public

    - name: Commit and push
      run: |
        git config --global user.email "[email protected]"
        git config --global user.name "Bot"
        git commit -am "[🔄] Resume ${{ needs.version.outputs.version }}"
        git push

The End

By following the above steps, you will have a fully automated workflow that will compile your LaTeX resume every time you push a change to the repository. It will also create a GitHub release with the built PDF file and deploy it to your website. This way, you will always have access to all the versions of your resume and you can easily revert back to a previous version if needed.

Below is a screenshot of the GitHub Actions workflow in action:

GitHub Action Workflow

The full workflow file is attached below for your reference:

name: Generate Resume

on:
  push:
    branches:
      - main

permissions:
  contents: write

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Build LaTeX environment
        uses: xu-cheng/latex-action@v3
        with:
          root_file: resume.tex

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: resume
          path: resume.pdf

  version:
    runs-on: ubuntu-latest

    outputs:
      version: "${{ steps.version.outputs.version }}"

    steps:
      - name: Set version
        id: version
        run: |
          datetime=$(date +'%Y-%m-%d+%H:%M:%S')
          version="v$datetime"
          echo "::set-output name=version::$version"

  release:
    runs-on: ubuntu-latest
    needs: [build, version]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          ref: "${{ github.ref_name }}"

      - name: Create a tag
        run: |
          git tag ${{ needs.version.outputs.version }}
          git push origin --tags

      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: resume
          path: out

      - name: Create release
        env:
          GH_TOKEN: "${{ github.token }}"
        run: |
          gh release create ${{ needs.version.outputs.version }} out/resume.pdf -t "Resume ${{ needs.version.outputs.version }}"

  deploy:
    runs-on: ubuntu-latest
    needs: [build, version]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          repository: siriscmv/cyril.pw
          token: "${{ secrets.PAT }}"

      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: resume
          path: public

      - name: Commit and push
        run: |
          git config --global user.email "[email protected]"
          git config --global user.name "Bot"
          git commit -am "[🔄] Resume ${{ needs.version.outputs.version }}"
          git push