Lesson 6 / 25

Scheduled Workflows

Cron in UTC.

Five-field cron, best effort

The schedule trigger uses five-field cron syntax in UTC. Scheduled runs use the default branch's workflow file, can be delayed during busy periods, and are disabled automatically in public repositories after a long period without activity. Use schedules for nightly builds, dependency audits and cleanup. Avoid the top of the hour, when load is highest, and make scheduled jobs idempotent.

Errors caught by actionlint, run

I checked this workflow with actionlint 1.7.12 (actionlint -oneline .github/workflows/broken.yml); the output and exit code are copied from that run. actionlint validates syntax, expressions, job dependencies and known actions offline; shellcheck was not installed, so shell scripts inside run: were not linted. The workflow was not executed on GitHub. actionlint finds three mistakes: hour 25 in the cron expression, a misspelled matrix property (nodee), and a needs: reference to a job that does not exist (biuld).

name: Broken

on:
  schedule:
    - cron: "0 25 * * *"

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [20, 22]
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.nodee }}
  deploy:
    needs: biuld
    runs-on: ubuntu-latest
    steps:
      - run: echo deploying

Output:

.github/workflows/broken.yml:5:13: invalid CRON format "0 25 * * *" in schedule event: end of range (25) above maximum (23): 25 [events]
.github/workflows/broken.yml:16:29: property "nodee" is not defined in object type {node: number} [expression]
.github/workflows/broken.yml:17:3: job "deploy" needs job "biuld" which does not exist in this workflow [job-needs]
(exit code 1)

Convert to UTC

A 09:00 IST job is 03:30 UTC: write "30 3 * * *".

Quick check: Which time zone do GitHub Actions cron schedules use?

  • US Pacific time
  • The repository owner's local time
  • The runner's local time
  • UTC
Answer

UTC — Always UTC.