How to schedule Python scripts with GitHub Actions
Learn how you can schedule and run Python scripts for free using GitHub Actions and cron syntax.
Learn how you can schedule and run Python scripts for free using GitHub Actions and cron syntax.
I created a python-github-action-template you can use to get started quickly. It demonstrates the following:
- How to schedule Python scripts with a GitHub Action
- How to use dependencies from a
requirements.txt
- How to use secret environment variables (e.g. for an API Token)
- How to add the changes to the repository
The example script from the template runs once a week to get the weather from an API, logs the weather to a file, and commit and pushes the updated log file to the repository.
If you want to know how everything works, read on.
#more
You can also watch the video instead:
Trigger GitHub Actions with cron syntax¶
GitHub Actions can be triggered by many different events.
The schedule event allows you to trigger a workflow at a scheduled time. You can schedule a workflow to run at specific UTC times using cron syntax:
on:
schedule:
- cron: '0 10 * * *'
# This runs at 10:00 AM UTC each day.
# * is a special character in YAML so you have to quote this string
The generous free tier includes 2,000 minutes per month, which is more than enough run many scripts multiple times a day.
If you don't know how cron syntax work, I'll have a quick refresher at the end of this article.
Schedule Python scripts with GitHub Actions¶
In your repository, implement your script (e.g. main.py
). Optionally, you can save third-party dependencies in requirements.txt
.
To then schedule your Python script we need to do the following steps inside the GitHub Action:
- Define the cron syntax
- Checkout the repository so that the runner has access to the files
- Use the setup-python action to set up a Python environment
- Optionally, install required packages stored in
requirements.txt
- Run the script
Below is a minimal GitHub Actions file to schedule and run a Python scrip. Store this file under .github/workflows/actions.yml
in your directory:
name: run main.py
on:
schedule:
- cron: '0 0 * * 1' # At 00:00 on Monday
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repo content
uses: actions/checkout@v2 # checkout the repository content
- name: setup python
uses: actions/setup-python@v4
with:
python-version: '3.10' # install the python version needed
- name: install python packages
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: execute py script # run main.py
run: python main.py
Use Secrets / API Tokens in GitHub Actions¶
Sometimes you want to store secret environment variables, e.g., for API Tokens. This is also simple:
Step 1: Add a new secret in your repository¶
You find this in your repository under:
Settings -> Secrets -> GitHub Actions -> New repository secret
Step 2: Use secret in GitHub Action¶
Now you can use this secret in your GitHub Action and pass it to the enviroment:
# ...
jobs:
# ...
- name: execute py script # run main.py
env:
SOME_SECRET: ${{ secrets.SOME_SECRET }}
run: python main.py
Step 3: Access secrets in Python code¶
And then you can access the secret in your Python code by accessing the environment variables:
import os
try:
SOME_SECRET = os.environ["SOME_SECRET"]
except KeyError:
SOME_SECRET = "Token not available!"
# or raise an error if it's not available so that the workflow fails
Automatically push changes to repository with GitHub Actions¶
If your script makes file changes inside the repository, you can automatically commit and push them with your GitHub Action.
For example, in the example template the script logs the weather to a file, and then pushes the changes with the updated log file.
To commit and push changes in your GitHub Action, add these lines. Notice that we add --allow-empty
to the git commit command in order to not have an error if there are no changes.
# ...
jobs:
# ...
- name: execute py script # run main.py
env:
SOME_SECRET: ${{ secrets.SOME_SECRET }}
run: python main.py
- name: commit files
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add -A
git diff-index --quiet HEAD || (git commit -a -m "updated files" --allow-empty)
- name: push changes
uses: ad-m/github-push-action@v0.6.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: main
At the start of each workflow run, GitHub automatically creates a unique GITHUB_TOKEN
secret to use in your workflow, so you don't have to create it yourself.
Putting it all together¶
This is the complete actions.yml
file from the repository template:
name: run main.py
on:
schedule:
- cron: '0 0 * * 1' # At 00:00 on Monday
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repo content
uses: actions/checkout@v2 # checkout the repository content
- name: setup python
uses: actions/setup-python@v4
with:
python-version: '3.10' # install the python version needed
- name: install python packages
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: execute py script # run main.py
env:
SOME_SECRET: ${{ secrets.SOME_SECRET }}
run: python main.py
- name: commit files
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add -A
git diff-index --quiet HEAD || (git commit -a -m "updated logs" --allow-empty)
- name: push changes
uses: ad-m/github-push-action@v0.6.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: main
Cron syntax refresher¶
Here's a quick refresher on how to use cron syntax.
The syntax is this: 'minute hour day-of-month month day-of-week'
Allowed values are:
- 0-59 for minute
- 0-23 for hour
- 1-31 for day-of-month
- 1-12 for month
- 0-6 for day-of-week (0 = Sunday)
You can use special characters:
*
any value,
value list separator-
range of values/
step values
Some examples:
* * * * *
: At every minute (every minute, every hour, every day, every month, every weekday)0 10 * * *
: At 10:00 AM each day0 10 * * 0
: At 10:00 AM on each Monday0 0 1,15 * *
At 00:00 on 1st and 15th each month0 0 * * 1-3
: At 00:00 from Monday through Wednesday0 0 1/2 * *
: At 00:00 on every 2nd day from 1 through 31
A great website to quickly check the scheduled time with a cron syntax is https://crontab.guru.
I hope you enjoyed the read!
FREE VS Code / PyCharm Extensions I Use
✅ Write cleaner code with Sourcery, instant refactoring suggestions: Link*
Python Problem-Solving Bootcamp
🚀 Solve 42 programming puzzles over the course of 21 days: Link*