Skip to content
Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Latest commit

Β 

History

325 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“… Schedule Workflow Runs Action

Schedule your GitHub Actions workflows to run at a future date and time! 🀯

This works using the schedule event to poll GitHub variables which are used as our database for scheduling.

Flow Diagram
flowchart LR
    A([`workflow_dispatch`]) --> H[Create scheduled workflow]
    W([`schedule`]) ---> I
    B([`other`]) ---> I
    H --> I[Fetch scheduled workflows]
    I --> P((For Each\nscheduled\nworkflow))
    P --> Q{Is it time to run\nscheduled workflow?}
    Q --> |yes| R[Run scheduled workflow]
    R --> S[Delete scheduled workflow]
    S --> V{Have we waited\n`wait-ms`?}
    V --> |no| T[Wait\n`wait-delay-ms`]
    T --> I
    V --> |yes| U[Write job summary]
    Q --> |no| V
Loading
chrome_ou3bXfy6SL.mp4

Usage

Create a workflow (eg: .github/workflows/schedule.yml) and copy the example below. Ensure you've setup the authentication and inputs correctly.

⚠️ Runner requirements

v1.5 and the floating v1 tag run on the Node 24 Actions runtime. GitHub-hosted runners have defaulted to Node 24 since June 2026, so if you use ubuntu-latest, windows-latest, or macos-latest there is nothing to do.

Node 24 is not available everywhere, though. Per GitHub's Node 20 deprecation notice, it does not support:

Environment Status
macOS 13.4 and older ❌ Not supported
Self-hosted ARM32 runners ❌ No official Node 24 build

If you're on either of those, pin to v1.3, the last release that runs on node20:

      - uses: austenstone/schedule@v1.3

Be aware of what you give up: v1.3 predates the fix for due workflows being skipped, so when two or more schedules come due in the same poll it only dispatches every other one. The rest wait for the next poll. It is not affected by the v1.3–main scheduling outage fixed in v1.4.

Node 20 is scheduled for removal from GitHub-hosted runners in fall 2026, so treat v1.3 as a stopgap rather than a destination.

πŸ”‘ Authentication

GitHub App

Personal Access Token (PAT)

You need to create a Personal Access Token (PAT) with the repo scope and add it to your repository secrets.

Fine-grained access tokens

The token must have the following permission set:

  • actions_variables:write
  • actions:write

⏩ Example

This workflow runs on a schedule event every hour and spends <1min checking the schedule for any pending workflows to run.

To schedule a workflow, manually do a workflow_dispatch by going to "Actions > πŸ“… Schedule Workflow Dispatch", type when you want the workflow to run, and click Run workflow.

Inputs

  • Replace the workflow input with the name, path, or id of the workflow you want to run
  • Change the timezone input to your timezone

Important

Make sure you've set your PAT to the TOKEN secret in your repository settings.

name: πŸ“… Schedule Workflow Dispatch
on:
  schedule:
    - cron: '0 */1 * * *' # every hour
  workflow_dispatch:
    inputs:
      date:
        description: 'Date to run the workflow'
        required: true
        type: string
        default: 'in 1 hour'
concurrency:
  group: schedule${{ github.event.inputs.date }}
  cancel-in-progress: true

permissions: {}

jobs:
  schedule:
    name: πŸ“… Schedule
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: austenstone/schedule@v1
        with:
          github-token: ${{ secrets.TOKEN }}
          date: ${{ github.event.inputs.date }}
          workflow: 'basic.yml'
          timezone: 'US/Eastern' # US/Central, US/Pacific
          wait-ms: 45000

The job needs no GITHUB_TOKEN permissions of its own because scheduling is done with the TOKEN secret, so permissions: {} is the correct least privilege here.

Where schedules are stored

Schedules live in repository variables named _SCHEDULE_<workflow-id>_<timestamp>_<uuid>. The action creates one when you schedule a workflow and deletes it once the run is dispatched, so nothing needs cleaning up by hand.

Timezone

The timezone is set to US/Eastern by default. You can change this to your timezone. EX: US/Central, US/Pacific, etc.

          timezone: 'US/Eastern'

Changing when to check the schedule

The schedule event is used to check for scheduled workflow runs. You can change the cron to run at a different interval.

on:
  schedule:
    - cron: '0 */1 * * *'

The action also has the ability to continue running the workflow and polling for a specific amount of time. This is useful if you want to run the workflow at a specific time and then continue running the workflow for a specific amount of time.

In the example below we spend 5 minutes checking the schedule every 20 seconds:

        with:
          wait-ms: 300000 # Check for 5 minutes
          wait-delay-ms: 20000 # Wait 20 seconds between checks

Tip

You may want to consider that for billing GitHub jobs are rounded up to the nearest minute.

Selecting the workflow to run

Pass in the workflow you want to run. This can be the name, path, or id of the workflow.

          workflow: 'basic.yml'

You could provide options for workflows to run. This does interfere with the workflow inputs you might want to pass in.

      workflow:
        description: 'Workflow to run at schedule time'
        required: true
        type: choice
        options:
          - 'basic.yml'
          - 'codeql.yml'
...
        with:
          workflow: ${{ inputs.workflow }}

Passing Workflow Inputs

You can provide the workflow_dispatch inputs you want to provide by using the inputs input.

        with:
          inputs: '{"name": "Austen"}'

or from the inputs themselves.

        with:
          inputs: ${{ toJson(github.event.inputs) }}

➑️ Inputs

Various inputs are defined in action.yml:

Name Description Default
github-token The GitHub token used to create an authenticated client ${{ github.token }}
workflow Workflow to run at schedule time. Only required when scheduling.
date Date to run the workflow ${{ github.event.inputs.date }}
wait-ms Milliseconds to wait 0
wait-delay-ms Milliseconds to wait between checks on the schedule 20000
ref Branch to run the workflow on ${{ github.ref }}
owner Optional repository owner to run the workflow on. ${{ github.repository_owner }}
repo Optional repository name to run the workflow on. ${{ github.repository }}
timezone Timezone to use for the schedule US/Eastern
inputs Inputs to pass to the workflow ${{ toJson(github.event.inputs) }}
inputs-ignore Inputs to ignore when passing to the workflow date,workflow

Further help

To get more help on the Actions see the documentation.

About

Schedule GitHub Actions Events to happen in the future! πŸ“…

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

26 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages