Just for fun, I decided to try making a CI/CD pipeline for my CV. This post will be a bit rough and jumbled, sorry about that, probably would have been better to split this into several posts. Anyhow, here’s how I did it.
Before I used to just update my CV via ShareLatex, so I didn’t have any Latex packages installed on my system. Installing Latex is usually a confusing mess of packages, so I figured using docker might be a good fit. In addition I knew that CircleCI takes a docker image to launch it’s jobs in, so I could reuse it later.
Luckily I found that someone else had made a docker image for xelatex. With some adjustments I made my own image that contained everything I needed for compiling my tex files.
Then I uploaded it to docker hub for free (since it’s open source).
With the previously mentioned docker image I defined a CircleCI job step as follows.
build_pdf:
docker:
- image: tethik/xelatex:latest
steps:
- checkout
- run: make
- attach_workspace:
at: .
- persist_to_workspace:
root: .
paths:
- cv.pdf
The persist_to_workspace
step saves the pdf so that it can be reused later in the deploy
job using the attach_workspace
step. The current attach_workspace
step in the config above coming before the persist_to_workspace
is to collect some
scripted parts of the CV that I try to generate automatically. More on this later.
For CD (Continuous Delivery) part of the process I needed somewhere to publish the document. I do have my own domains and servers, but I’d rather not have to give access to CircleCI to ssh or ftp into these. The hacky and cheap solution was to just reuse the same github repository and enable the Github pages feature. To do this I enabled Github Pages on the master branch, which I kept empty except for the final pdf output. Then I set up another step in the CircleCI config to commit and push the new pdf file to the master branch.
The CircleCI config step looks like this.
deploy:
docker:
- image: circleci/node:8.9
steps:
- checkout
- attach_workspace:
at: .
- run: .circleci/deploy.sh
The deploy script itself looks like this.
#!/bin/sh
git config --global user.email "circleci@blacknode.se"
git config --global user.name "CircleCI Deployment"
mv cv.pdf ..
git fetch --all
git reset --hard origin/develop
git checkout master
mv ../cv.pdf .
git add cv.pdf
git commit -m "PDF build $CIRCLE_SHA1"
git push origin master
By default CircleCI generates a key on your github repo which only has READ access. To get around this I created a new ssh key and added it as a deploy key to the github repository. Then I removed the original key from the CircleCI project configuration, and added the new ssh key that I generated.
The final step was to add the redirect from my main homepage (this site) to the github pages link where the document would be hosted. Since the server is running Apache I could use the following config.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.)cv$ https://tethik.github.io/curriculum-vitae/cv.pdf
RewriteRule ^curriculum-vitae https://tethik.github.io/curriculum-vitae/cv.pdf
</IfModule>
It’s a bit hacky, but it works :)
The next fun step I wanted to do was add some parts to the document that would be automatically generated. Because writing CVs is boring and too manual. For now though I just coded something simple: A script that summarizes all my pull requests made on Github that are in some sense Open Source. i.e. not to repos that I own myself or repos that were created for e.g. schoolwork.
To organize the LateX files I set up the repo as follows. I wanted to keep the generated files separate from the main latex file that I copied from before.
partials/ -> generated tex files.
src/github/ -> python script that generates into partials/
cv.tex
Inside the main cv.tex
file I could then refer to the scripted content using the subfile
package.
\subsection{Github Open Source Contributions}
\subfile{partials/pull_requests}
Inside the src/
folder I mean to keep scripts that generate the partials. The src/github/
folder
contains a script that generates a pull_requests.tex
into the partials/
folder. It talks the to Github GraphQL API and summarizes the info into a table.
I added the following CircleCI job config. This goes before the previously defined build_pdf
step.
build_partials:
docker:
- image: kennethreitz/pipenv
steps:
- checkout
- run:
command: pipenv install
working_directory: ~/project/src/github/
- run:
command: pipenv run make
working_directory: ~/project/src/github/
- persist_to_workspace:
root: .
paths:
- partials/
Again I persist_to_workspace
to keep the resulting partial/*.tex
files. Pipenv handles the python dependencies beautifully.
The github api key and a blacklist of repos to ignore is passed through environment variables.
This is what the table looks like in the PDF.
In the future I’d like to add more content that’s automatically generated. E.g. pypi and npm packages published, total github commit stats etc.
You can find the repository here, the latest pdf built by the pipline here, and the CircleCI project here.
I still need to update my CV though.