Giddy-up with GitHub Actions
Published: 2022-09-02 05:22:56

Explore GitHub Actions with a CV generator ✨

## What is GitHub Actions?
GitHub Actions is a platform that can be used to [automate a build, test and deployment pipeline](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions). This platform has several components:

- **Events:** Something that happens in a GitHub repository (such as pushing to a branch, opening an issue or a pull request)that can trigger the start of a workflow.

- **Workflows:** An automated process that is configured to run once a trigger is fulfilled. They consist of one or more jobs.

- **Jobs:** A job consists of a series of steps that run in the order they are written, one after the other in the same runner. Multiple jobs could run parallelly. Each step in a job could be a shell script or an action.

- **Actions:** This is what happens in a workflow (a single step). They perform tasks that are complex and repetitive, therefore they can reduce repeated code in your workflow file.

- **Runners:** A runner is a server that runs the triggered workflow, and each runner will run a single job at a time.

---
This article focuses on a project that generates a CV using a python script that converts data in JSON files to a format for a LaTeX CV template, run automatically by a GitHub Actions workflow that also converts the generated .tex file to a CV in PDF format when changes are pushed to the `master` branch.

{% github methminug/CV-Generator %}

This project is not purely made from GitHub Actions workflows, but they are the core of what will be used to eventually generate the CV. In summary, the final workflow file will:

1. Be triggered to generate a new CV when changes are made to data in JSON files.
2. Run a Docker container that will run a Python script to convert data from the JSON files to a LaTeX template, then convert the file from the template to a PDF.
3. Commit the newly created PDF to the repository.

For a bit of background, [LaTeX](https://www.latex-project.org/) is a software system widely used to create academic documents, allowing creators to focus on the content while LaTeX handles the formatting. Templates for LaTeX documents make things even faster, making it an ideal option for creating a document like a CV where a more time and effort must be put into the content rather than the format.

The LaTeX template used here is Awesome CV by posquit0, and can be found at: [github.com/posquit0/Awesome-CV](https://github.com/posquit0/Awesome-CV)

Thank you for this cool template!

---

As this article focuses on actions and workflow files, the content of the Python scripts will not be discussed here, but in short, they replace placeholder text in the LaTeX template with data from JSON files that contain actual data for the CV.

So, let’s jump into the workflow file!

### Parts of a workflow file
A workflow is a file written in YAML syntax.

GitHub Actions recognizes workflow files to run by checking specifically for a directory named `.github/workflows` in the branch that you want the workflow to be triggered from (the `master` branch in this case).

The main parts of a workflow file are:

1. Name (optional)
2. Trigger
3. Jobs

The name given to a workflow is what will appear when the workflow is shown in the Actions tab of the GitHub repository. The name is configured at the top of the file by the statement:
```yaml
name: Update CV
```
The trigger is what will cause this workflow to start running. A trigger can be multiple events or a single event. The following statement configures the workflow to run when a push is made to any branch or when someone forks the repository.
```yaml
on: [push, fork]
```

Next, comes the jobs sections which group together all the jobs that will run in the workflow.
```yaml
jobs:
   <Name of first job>:
      . . .
```

### Building the workflow file
The gist of this generator is that when data in a set of JSON files in the `master` branch is updated, a new CV should be created according to the updated data in the files.

Therefore, we would want the CV generating workflow to run each time any changes are pushed to the `master` branch of the repository.
```yaml
name: Update CV
on:
   push:
      branches: [ "master" ]
```

As explained previously, the `on:` section defines the trigger event, and the trigger event of this workflow is a push to a branch, so `push:` is used.

The `push:` event has a filter called `branches:` which allows us to configure the workflow to be triggered only when there is a push event made to a specific branch or branches. In this case, the workflow will only start when a push is made to the `master` branch of the repository.

Moving onto the `jobs:` section of the workflow file, our goals are to:

1. Checkout the current branch.
2. Generate a CV.
3. Commit the changes.
4. Push the changes to master branch.

s these steps have to take place one after the other, they can all be defined as consecutive steps of one job. Each new step will be marked with a hyphen (`-`).

To set the environment for running this job, the following lines under the `jobs:` section will be added to the file:

```yaml
name: Update CV
on:
   push:
      branches: [ "master" ]
jobs:
   update_cv:
      runs-on: ubuntu-latest
      
      steps:
      - . . .
```

Here, `update_cv` is the name given to the job that will run the previously mentioned steps. Note that `Update CV` is the name of the **workflow** that runs a **job** named `update_cv`.

Next, the `update_cv` job is configured to run on the latest version of an Ubuntu Linux runner as defined by `runs-on:` . This job will run on a virtual machine hosted by GitHub.

Then, the steps will be added in the order of execution under `steps:` .

#### 1. Checkout current branch
This step is necessary to make the contents repository accessible to the workflow. This is important as we will be using a private action in this repository later on in this job. Therefore a checkout action should be used any time a workflow will run against the repository’s code.

```yaml
. . .
jobs:
   update_cv:
      runs-on: ubuntu-latest
      
      steps:
      - uses: actions/checkout@v3
```

The step used to checkout the repository uses the action, Checkout V3, from the GitHub Marketplace, and uses the `uses:` keyword to define the action that will be used in this specific step.

#### 2. Generating the CV
Next is the step that runs the script to generate the CV and convert it to a PDF, this will be run in a Docker container, so first we will be building a docker container action to be executed in this step. This action will be defined in a separate YAML file in the repository, named `generate-cv.yaml`.

##### The Docker container action
To start the Docker container and run the actions code, a Docker image should be specified.

The docker image can be specified in two ways:

1. As a Dockerfile in the repository.

2. Using an image from the public Docker registry.

For this example, we will be using a Dockerfile created in the root directory of the repository.

Therefore, the action in the `generate-cv.yaml` file (which is also in the root directory) will be:
```yaml
name: 'Generate CV'
runs:
   using: 'docker'
   image: 'Dockerfile'
```
According to the code, this action will be run using `‘docker’` since it is a Docker action, and an image will be built from `‘Dockerfile’` and the commands will be run in a new container using this image.

Now, the Docker container action created can be used as a private action in the next step of the `update_cv` job of our workflow file.
```yaml
. . .
jobs:
   update_cv:
      runs-on: ubuntu-latest
      
      steps:
      - uses: actions/checkout@v3
      - name: Generate CV
        uses: ./
```

The private action’s name `Generate CV` is given to the `name:` keyword in this step. Since this step uses an action in the root directory, a path of `./` is given to the `uses:` keyword.

This step will run the Python script that would update the LaTeX template file, create a .tex file from the updated LaTeX template file and finally create a PDF file of the CV from the .tex file.

####3. Commit the changes
Next, the newly created PDF file and updates to the LaTeX template file should be committed.

This can be done by via git commands.
```yaml
. . .
jobs:
   update_cv:
      runs-on: ubuntu-latest
      
      steps:
      - uses: actions/checkout@v3
      - name: Generate CV
        uses: ./
      - name: Commit generated PDF
        run: |
           git config --local user.email "action@github.com"
           git config --local user.name "github-actions"
           git add --all
           git commit -m "CV updated via GH Actions" -a
        shell: bash
```
The first two commands configure the GitHub Actions bot to commit to the repository.

Then, all the changes are committed by the bot under a new commit with the commit message `"CV updated via GH Actions"` .

These commands are executed using `bash` which is the default shell on non-Windows platforms.

####4. Push the changes to branch
Finally, the commit made should be pushed to the master branch.

The third party action [GitHub Push](https://github.com/marketplace/actions/github-push) from the GitHub Marketplace will be used for this.

```yaml
. . .
jobs:
   update_cv:
      runs-on: ubuntu-latest
      
      steps:
      - uses: actions/checkout@v3
      - name: Generate CV
        uses: ./
      - name: Commit generated PDF
        run: |
           git config --local user.email "action@github.com"
           git config --local user.name "github-actions"
           git add --all
           git commit -m "CV updated via GH Actions" -a
        shell: bash
      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
           github_token: ${{ secrets.GITHUB_TOKEN }}
```

The keyword `with:` groups the inputs sent to the GitHub Push action. As a repository has not been given as input, the changes will be pushed to the `master` branch of the current repository.

The input for `github_token` used here is a unique [GITHUB_TOKEN secret](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow) that GitHub automatically creates at the start of each workflow run, which can be used to authenticate on behalf of GitHub Actions.

A repository scoped [personal access token](https://medium.com/sliitwif/giddy-up-with-github-actions-2d3b74c1b6fa) could also be used as the `github_token` input instead.

---

And that concludes our job for our GitHub Actions workflow!

The complete codebase can be found in the repository linked below, so feel free to [fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) it, make some changes to the JSON files in the `/sections` directory and watch this workflow spring to action!

{% github methminug/CV-Generator %}

**_Till next time, happy coding!_**

---

- _Dog cartoon vector created by catalyststuff — [www.freepik.com](https://www.freepik.com/vectors/dog-cartoon)_