Using Github Actions To Run Scheduled Jobs
Tags: programming, productivity, github
Published: 2021-12-02 07:46:55

Github actions, a tool that is used to automate certain manual and repetitive tasks that developers often perform everyday on the job, if you are not already using using Github actions to automate anything and everything you can in your workflow, you are really losing a lot of expensive developer time. If you already use them thumbs up, cause you are a super developer. In this article we will explore how we can use Github actions to automate some tasks at a certain point in time, this is quite different from the events on which we normally run our jobs, e.g [push, pull], rather we use a scheduler, with the help of cron syntax to specify when that job should be run. Let's dig in.

## What is Github Actions?

Most people will say Github actions is a CI/CD platform, and that is quite true because the entire idea of automation is geared towards CI/CD, CI which stands for Continuous Integration, is involved with adding new code to existing code base, while CD  Continuous Delivery is concerned with deploying the new code base to production environment. With this being established, how does it fit into the entire picture? 

I work with firebase sometimes and there are times when i need to deploy a website to firebase hosting, personally I can't remember when last I ran `firebase deploy`, It makes me more productive because most of the time my focus is on writing code, I don't need to worry about deploying it because It's already been taken care of, less distractions, more attention to the task at hand. I have a full article showing you how to setup Github actions with firebase, you can check it out [here.](https://dev.to/kalashin1/automate-the-hell-out-of-your-code-3j42)

I will briefly describe the syntax of Github actions,

```yaml
name: Deploy_To_Firebase ## Name of the job

on: [push, pull_request] ## Event to trigger workflow

jobs: ## One or more jobs that can run concurrently
  deploy: ## name of the job
    runs-on: ubuntu-latest  ## A machine to run the job one
    steps: ## Steps involved in running the job
    - uses: actions/checkout@master ## We can also use another github action with
    - uses: actions/setup-node@master  ## by using the - uses.
      with: ## We can choose one or more runtime to install
        node-version: '10.x' ## we can pick a version or a list of versions
    - run: npm install ## this are actual commands that we would run on our machine
     - run: npm run build 
    - uses: w9jds/firebase-action@master
      with:
        args: deploy --only hosting:lpm-admin-app 
      env:
        FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
```

The code block above is really a simplified version of a Github action, each action is a `yaml` file that should live insdie `root/.github/workflows/workflow.yaml` where root is the root level of your project we can name each workflow what we ever we like. 

## Cron Scheduler

**Cron** is a utility program that lets users input commands for scheduling tasks repeatedly at a specific time. Tasks scheduled in cron are called **cron jobs**. Users can determine what kind of task they want to automate and when it should be executed. Cron is a background process executing non-interactive jobs, always idle, waiting for a command to request it to perform a particular task. The command can be input on any computer on the network. Check out this article to learn more about [cron]('https://www.hostinger.com/tutorials/cron-job').

The cron syntax is quite funny we just use numbers to specify a date we want to run a certain script. let's look at it

```tex
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of the month (1 - 31)
│ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
│ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
* * * * *
```

As seen in the code block above we have five values which we can pass in, and let's go over them together,

* the first value represents the minute of the hour we want the cron job to run, it cant be more than 59 and starts at 0.
* The second value is the hour we want the job to run, since we only have 24hrs, it starts at 0 and stops at 23. It's a zero based index.
* The third value is the day of the month we want to run the job on, we have one to 31 days, keep in mind months that have less than this number of days, we can use a comma to specify a list of days.
* The fourth value is the particular month we want to run the job on, it starts at 1 and ends at 12.
* The last value represents the day of the week we want to run the job, we have 7 days in a week so it starts at 1 and ends at 7. 

Do not leave any of the fields blank, instead use an asterisk `*` to match any value for a particular field, to write a crontab(also used in place cron) that will run on 31st of December 2021, it would look something like this.

```text
"59 23 31 12 *"
```

The above value represents 11:59pm 31st December 2021 on any day, if we had used a number instead of an asterisk we would schedule the job to on 31st and that other day of the same week that 31st fell on. You can use the [crontab guru](https://crontab.guru) to generate a crontab with less stress, now let's mix that with Github action to schedule the above job to run every midnight. Let's write the crontab to match every midnight first so we understand that.

```tex
"0 0 * * *"
```

The first 0 for the first minute, the second 0 is for the the first hour of the day, while the 3 three asterisks match any day and any month  and any other day of the week. Basically, every midnight. Mixing that with Github actions, our `yaml` file would look very much like this.

```yaml
name: Deploy_To_Firebase 

on:
  schedule: ## Schedule the job to run at a particular time.
    # * is a special character in YAML so you have to quote this string
    - cron:  '0 0 * * *'

jobs:
  deploy: 
    runs-on: ubuntu-latest  
    steps: 
    - uses: actions/checkout@master 
    - uses: actions/setup-node@master  
      with: 
        node-version: '10.x' 
    - run: npm install 
     - run: npm run build 
    - uses: w9jds/firebase-action@master
      with:
        args: deploy --only hosting:lpm-admin-app 
      env:
        FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
```

Now all we have to do to deploy this code every midnight is just to save, commit and push it up to github and have a good night's rest. Hope you learnt something from this. See you in the next one.