Basics of GitHub Actions

Basics of GitHub Actions

As a developer you have a lot of tasks to automate for example to trigger automated tests for a pull request or to run a cron job for the source code. With Github Actions you can run workflows that can perform these tasks as set/triggered. It also helps you in creating automation pipelines for continuous integration and continuous delivery(CI/CD).

It is a useful tool for developers to automate repetative tasks, for Quality Engineers to test the product, for Platform Engineers to create the infrastructure deployment pipelines and for SRE (Site Reliability Engineers) to deploy in production. Today we will go through basics of github actions and create a workflow.

💭 what is a workflow in github actions?

A workflow is basically a configuration yaml file that contains the flow of the automation that you want to set. It is majorly divided into three parts:

  • Trigger event of Workflow: Here you can set the event or time at which you want to trigger the workflow. For example, you can trigger the steps in the workflow whenever someone creates a PR or push the code for the repo to run the automated test cases. Or you can trigger it as a cronjob like every monday at 9:15 AM you want to scan your code for vulnerabilities.

  • Jobs and steps: It contains the configuration and the steps to run in the job. For example to use a ubuntu machine to run the tasks and then checkout the code, set the environment variables and run some shell commands. You can have multiple jobs in a workflow and multiple steps in a single job.

    You can divide the steps into different jobs based on requirements. There are a few reasons why one should have multiple jobs in a GitHub Actions workflow:

    • To parallelize tasks. Multiple jobs can run in parallel, which can speed up the overall workflow. For example, you could have one job run your unit tests and another job run your integration tests.
    • To isolate tasks. If one job fails, it won’t affect the other jobs. This can be useful for preventing cascading failures. For example, you could have one job build your code and another job deploy your code. If the build job fails, the deployment job won’t run.
    • To use different environments. You can use different jobs to run tasks on different machines or operating systems. For example, you could have one job run your tests on Linux and another job run your tests on Windows.
    • To reuse jobs. You can reuse jobs in different workflows. This can help you to keep your workflows DRY (don’t repeat yourself).
  • Post Workflow: After running all the required steps generally there are post workflow commands such as to upload the artifacts or test reports back to Github or cleaning up the build files.

Let’s create a workflow to see all these in action.

import requests

print("Hello Github Actions!")

def quote():
    url = "https://api.quotable.io/random"

    response = requests.get(url)
    print(response.status_code)
    quote = response.json()
    return quote['content']

print(quote())

So here I have a basic python script which is using requests module to get a quote from this API. Lets try to run this locally and also i will save the output in a file called quote.txt

python3 hello.py > quote.txt

I have created a repository on github with the same file. Below is the requirements.txt file which contains the list of packages I need to run my application. For this one I only need the requests package.

requests==2.28.2

I have opened this repository on GitHub. Now go to Actions. Here you can see the some of the preconfigured workflows. Either you can choose any of these and customize them or create a new one yourself.

Let’s name it workflow.yml.

Events

name: Quote Workflow
on: 
  workflow_dispatch:
  schedule:
  - cron: '30 3 * * 1-5'

Name the workflow as “Quote Workflow”.

Now I need to set when to run the workflow. If you check the documentation you will find there are lots of events defined. First i have added workflow_dispatch because I want to run the workflow manually. But let’s suppose I need my quote delivered at 9 AM daily. So I will use the schedule trigger and set the cron to “30 3 * * 1-5”. So this will trigger the workflow on weekdays at 9AM local time or 3:30 AM UTC. Keep in mind that the cron always takes time in UTC so you need to adjust the cron according to your local time. Just like here I have reduced 5 hr 30 mins for IST time zone.

Job

Now coming to the next part of the workflow, the jobs.

jobs: 
  Run-python-script:
    runs-on: ubuntu-latest

Here we will specify the name of the job(‘Run-python-script’) to be run.

Then we need to specify the machine OS on which we need to run this particular job. There are many options available but I am going with ‘ubuntu-latest’.

Steps

After defining the machine we can start with the steps. First we will define the steps inside job to setup the required environment.

  1. We first need to checkout the code in the ubuntu machine.
    steps: 
      - uses: actions/checkout@v3
    
  1. Then I will setup a particular version of python.
          - uses: actions/setup-python@v3
              with:
              python-version: '3.10'
              architecture: 'x64'
      
  1. Next I need to install my requirements from requirements.txt file. I will run the pip install command. Here i will name it as Installing the dependencies.
        - run: echo "Installing requirements.."
        - name: Install dependencies
            run: pip install -r requirements.txt 
    
  1. Next I will try to run my script. So I will just write the shell command, that I have used locally and save the output of script in a txt file.
            - run: echo "Triggering script."
            - name: Running Script
                run: python3 hello.py > artifact.txt 
    

Remember, here we are not using “uses” because that is for predefined action. But here we will use “run” to run the shell command.

If you are facing difficulty then you can watch the video below:

  1. Now after this file(‘quote.txt’) is created, to retrieve this file as artifact we will use the following step. I will set the parameters here as name and path of the artifact. Also i will set the retention period. This is the period for which the Github will retain or store the artifact created using this build. So I will set it for 1 day. If you set it to zero then the it will follow the retention policy of the repository which you can find in the Github settings.
    - uses: actions/upload-artifact@v3
      with:
        name: quote
        path: ./artifact.txt
      retention-days: 1

Now you can save the changes in your workflow file and then run the workflow from the Actions tab.

Here is the complete workflow file for your reference.

name: Quote Workflow
on: 
  workflow_dispatch:
  schedule:
  - cron: '40 3 * * 1-5'
jobs: 
  Run-python-script:
    runs-on: ubuntu-latest
    steps: 
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v3
        with:
          python-version: '3.10'
          architecture: 'x64'
      - run: echo "Installing requirements.."
      - name: Install dependencies
        run: pip install -r requirements.txt 
      - run: echo "Triggering script."
      - name: Running Script
        run: python3 hello.py > artifact.txt
      - uses: actions/upload-artifact@v3
        with:
          name: quote
          path: ./artifact.txt
            retention-days: 1 

Conclusion

GitHub Actions is a powerful tool that can help you to automate your workflows and improve your development process. By using multiple jobs in your workflows, you can parallelize tasks, isolate tasks, use different environments, and reuse jobs. This can help you to improve the performance, reliability, and maintainability of your workflows.