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.
Setting up the Repository
- Create a new Git repository on GitHub, let’s call it
resume
. - Clone the repository to your local machine.
- Put the source latex file (
resume.tex
) in the root of the repository. - Create a
.github/workflows
directory in the root of the repository. - Create a new workflow file in the
.github/workflows
directory, let’s call itresume.yml
.
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.
- The workflow will trigger on every push to a specific branch (let’s say
main
). - It will have 4 jobs. Namely
build
,version
,release
, anddeploy
. - We also have to add write permissions for
contents
in order to be able to create a Git tag and push it.
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:
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