DEV Community

Cover image for Run cron job free with GitHub Action 💸
Max Shen for Repohistory

Posted on

Run cron job free with GitHub Action 💸

Cron jobs are useful for setting up automated tasks that run periodically. While several services offer cron job functionality, they often have limitations.

For instance, Vercel's Cron Job in its free tier offers:

  • 2 cron jobs total, each triggered once per day
  • 10 seconds maximum duration for each cron job

This 10-second limit can be restrictive. During my work on Repohistory, I needed a cron job to fetch users' repo traffic data daily. As the user base grew, completing this task within 10 seconds became unfeasible.

That's why I explored an alternative solution for cron jobs.

GitHub Action

GitHub Actions is a CI/CD platform that allows you to execute workflows triggered by any GitHub events. This feature is particularly useful for tasks like building and deploying your website following a new commit.

A workflow in GitHub Actions is an automated process defined in YAML. These workflows are stored in the .github/workflows directory of your repository and follow a specific structure.

Here's an example of a workflow file that prints the content of hello_world.txt when a new commit is pushed to the repository:

name: hello-world
on: push
jobs: 
  hello-world-job:
    runs-on: ubuntu-latest
    steps: 
      - name: Check out repository code
        uses: actions/checkout@v3
      - run: echo "$(cat hello_world.txt)"
Enter fullscreen mode Exit fullscreen mode

You can learn more about the detail on GitHub Resources.

The key part of a workflow is the on, which specifies the GitHub events that will activate the workflow. In the above example, the event is push, meaning the workflow runs on any commit push.

An additional event type is schedule, which is ideal for cron jobs.

Cron job on GitHub Action

The schedule event allows workflows to run at scheduled times, defined using cron syntax. For example, this configuration triggers a workflow every day at 5:30 AM and 5:30 PM:

on:
  schedule:
    - cron:  '30 5,17 * * *'
Enter fullscreen mode Exit fullscreen mode

The limits for GitHub Actions are generous:

  • 20 concurrent jobs
  • 6 hours maximum duration per job

These limits are typically more than sufficient for most tasks.

A practical example

For Repohistory, I implemented a GitHub Action to run a cron job. The src/cron.ts script fetches and saves users' repo traffic data to a database. To keep the data up to date, it runs three times a day:

// src/cron.ts
import updateTraffic from './services/updateTraffic';
import { app } from './utils/octokit';

app.eachInstallation(({ installation }) => {
  updateTraffic(installation.id);
});
Enter fullscreen mode Exit fullscreen mode

Let's go through the workflow file step by step. I first set the cron to '0 */8 * * *' so the workflow runs 3 times everyday ( on 00:00, 08:00, 16:00 ):

name: Cron Job

on:
  schedule:
    - cron: '0 */8 * * *'
Enter fullscreen mode Exit fullscreen mode

This workflow only has one job that is executing src/cron.ts, so the first few steps is to check out the repo and set up Node.js:

jobs:
  execute-script:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
Enter fullscreen mode Exit fullscreen mode

Then install the dependencies of my project:

      - name: Install dependencies
        run: npm install
Enter fullscreen mode Exit fullscreen mode

Finally compiles the TypeScript file and then execute it. Because the job use GitHub and Supabase API so I also pass some environment variables into it:

      - name: Compile TypeScript file
        run: npx tsc src/cron.ts --outDir dist

      - name: Run the compiled script
        env:
          NEXT_PUBLIC_APP_ID: ${{ secrets.NEXT_PUBLIC_APP_ID }}
          NEXT_PUBLIC_PRIVATE_KEY: ${{ secrets.NEXT_PUBLIC_PRIVATE_KEY }}
          NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
          NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
        run: node dist/cron.js
Enter fullscreen mode Exit fullscreen mode

You can see the complete workflow file here.


That's pretty much about how I run free cron job on GitHub Action when building Repohistory! Feel free to check this project out on GitHub!

Top comments (0)