GitHub Actions and Cron: A Powerful Duo
Run workflows automatically on a schedule without needing a push or manual trigger.
GitHub Actions cron schedules are evaluated in UTC, not in your local timezone.
Add workflow_dispatch so you can test scheduled workflows without waiting for the next cron run.
GitHub Actions lets you automate repetitive tasks directly from your repository. That can mean running tests, publishing reports, deploying code, or handling small maintenance jobs on a fixed schedule.
One of the most useful triggers for that is cron scheduling. Instead of waiting for a push, pull request, or manual run, you can tell GitHub to run a workflow at a defined interval.
This is simple once the pieces click: a workflow file, an on.schedule trigger, and a cron expression that says when the automation should fire.
Setting Up a Scheduled Workflow
Workflow files live inside the .github/workflows/ directory of your repository. The on section defines what triggers the workflow.
name: Daily Report
on:
schedule:
- cron: '0 9 * * *' # every day at 9:00 AM UTC
jobs:
run-report:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run report script
run: python generate_report.py
All cron schedules in GitHub Actions are evaluated in UTC. If you want the workflow to run at a local time, you need to convert that time into UTC yourself.
on.schedule. You must account for the UTC offset manually.
Reading Cron Expressions
A GitHub Actions cron expression uses five fields:
# ┌─────────── minute (0–59)
# │ ┌───────── hour (0–23, UTC)
# │ │ ┌─────── day of month (1–31)
# │ │ │ ┌───── month (1–12)
# │ │ │ │ ┌─── day of week (0–6, Sunday = 0)
# │ │ │ │ │
* * * * *
A * means “every value for that field.”
| Expression | Meaning |
|---|---|
0 0 * * * |
Every day at midnight UTC |
0 9 * * * |
Every day at 9:00 AM UTC |
30 15 * * 1-5 |
3:30 PM UTC, Monday through Friday |
0 0 * * 0 |
Every Sunday at midnight UTC |
0 0 1 * * |
First day of every month at midnight UTC |
*/15 * * * * |
Every 15 minutes |
0 8,17 * * 1-5 |
8:00 AM and 5:00 PM UTC on weekdays |
Combining Schedule with Other Triggers
A scheduled workflow does not have to rely on cron alone. A common pattern is to combine schedule with push or workflow_dispatch.
on:
schedule:
- cron: '0 9 * * *'
push:
branches:
- main
workflow_dispatch:
This makes the workflow easier to test. You do not need to wait until the next scheduled time just to see whether it works.
The manual run button from
workflow_dispatchis one of the easiest ways to debug a scheduled workflow.
Using More Than One Schedule
You can define multiple cron expressions for the same workflow when different days need different timing.
on:
schedule:
- cron: '0 9 * * 1-5' # weekdays at 9 AM UTC
- cron: '0 12 * * 0,6' # weekends at noon UTC
This is useful when a workflow should run more often during the week and differently on weekends.
Important Limits and Gotchas
- Scheduled workflows are disabled after 60 days of inactivity in public repositories.
- Timing is approximate. GitHub may run scheduled workflows later than expected during high load.
- The shortest supported interval is 5 minutes.
- Scheduled workflows run from the default branch.
A Practical Example: Weekly Dependency Check
name: Weekly Dependency Check
on:
schedule:
- cron: '0 8 * * 1' # every Monday at 8:00 AM UTC
workflow_dispatch:
jobs:
check-dependencies:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install pip-outdated
run: pip install pip-outdated
- name: Check for outdated packages
run: pip-outdated requirements.txt
This is a good example of routine automation: a predictable weekly check that also remains manually runnable when needed.
Frequently Asked Questions
These are the practical questions people usually have when they first start using cron in GitHub Actions.
Are GitHub Actions cron schedules based on my local timezone?
No. Scheduled workflows use UTC, so local-time runs must be converted manually.
What is the shortest interval GitHub Actions allows?
The shortest supported schedule is once every 5 minutes.
Do scheduled workflows run exactly on time?
Not always. They can run later than expected, especially during periods of high GitHub load.
Why should I add workflow_dispatch to a scheduled workflow?
Because it gives you a manual run button, which makes testing and debugging much easier.
Can one workflow have more than one cron schedule?
Yes. You can list multiple cron expressions under schedule.
What branch does a scheduled workflow run from?
Scheduled workflows run from the repository’s default branch.
What happens if a repository sits inactive for a long time?
In a public repository, scheduled workflows can be automatically disabled after 60 days of inactivity.
What is the simplest beginner rule here?
Verify the cron expression, remember everything is UTC, and always add a manual trigger for testing.
Conclusion
Cron scheduling in GitHub Actions is straightforward once you understand the five-field syntax and the UTC-only rule.
The biggest habits worth keeping are simple: verify cron expressions before you trust them, add workflow_dispatch so you can test manually, and remember that scheduled workflows are reliable for recurring automation but not for exact second-level timing.
With those boundaries in mind, scheduled workflows are one of the easiest ways to automate recurring repository tasks without building extra infrastructure.
Comments