Skip to content
LastPing
GUIDE · GITHUB ACTIONS SCHEDULED · FREE

Monitor scheduled GitHub Actions: catch the silent 60-day disable

GitHub disables schedule: workflows in public repositories after 60 days of inactivity. At most, the person who last changed the cron line may get a warning email. One signed workflow_run webhook catches that, plus failed and hung scheduled runs, with zero YAML changes. Free for individuals, no monitor cap.

Your assistant can do this for you

Monitor my scheduled GitHub Actions workflows with LastPing

On this page
  1. The three ways your scheduled workflow disappears.
  2. Setup: one webhook, about two minutes
  3. What this specifically catches for scheduled workflows
  4. Questions people ask
This page is specifically about schedule: triggers. For general GitHub Actions monitoring (all triggers, webhook setup, failure log detail), see the GitHub Actions monitoring guide. This page focuses on the unique problems of the cron / scheduled workflow pattern.

The three ways your scheduled workflow disappears.

A workflow with a schedule: trigger is fundamentally different from a push-triggered workflow. It runs on a cadence, by itself, and its failures alert almost nobody.

The 60-day disable

GitHub silently stops it

After 60 days with no commits, pull requests, releases, or other activity in a public repository, GitHub automatically disables all schedule: workflows. GitHub may email a warning beforehand to the person who last changed the cron line; the disable itself sends no notification. The Actions tab still shows the workflow; it simply doesn't fire.

The wrong-person email

Alert goes nowhere useful

When a scheduled run fails, GitHub emails only the person who last committed to the workflow file's cron expression. That's often whoever set it up years ago: someone who left, whose email filter buries it, or who is on vacation when it matters.

The hung run

Starts, never finishes

A scheduled run that starts and never completes (stuck step, hung network call, infinite retry) is not a failure yet, so no failure email fires. GitHub's job timeout will eventually kill it, but by then you've missed the window where it mattered.

Setup: one webhook, about two minutes

The same webhook approach as the general GitHub Actions guide, but the key detail for scheduled workflows is the expected schedule window you configure in LastPing, which is what catches the 60-day disable.

Create a CI check in LastPing with your cron schedule

In the console, create a monitor, choose CI pipeline, and pick GitHub Actions. Set the expected schedule to match your workflow's schedule: cron expression (e.g. daily at midnight) plus a grace window (e.g. 30 minutes). This is the window after which a missing run signal opens an incident. Copy the webhook URL and one-time secret.

https://ping.lastping.dev/ci/github/<check-id>

Register the webhook in your repository

On GitHub: Settings → Webhooks → Add webhook.

  • Payload URL: the webhook URL from step 1
  • Content type: application/json
  • Secret: the one-time secret from step 1
  • Events: "Let me select individual events" → tick Workflow runs and Workflow jobs
  • Workflow jobs is what supplies the failing step name ({failing_stage}) in alerts; workflow_run alone cannot, and the field renders empty without it.

Optionally, configure the check to filter to the specific workflow name and branch so only your nightly/scheduled workflow counts against the expected cadence.

Optional: attach failure log to the incident

Add an if: failure() step to your scheduled workflow that POSTs up to 64 KB of context to the detail endpoint. The failure reason is stored on the open incident, so the alert shows where it broke, not just that it broke.

LASTPING_CI_SECRET is the same CI secret this monitor's webhook signs with: reveal it under the monitor's CI settings in the console (the reveal is password-gated) and save it as a repository secret. Sending it also lifts the throttle: without the token, detail posts are limited to 60 per 15 minutes per monitor; with it, there is no limit.

The trailing || true is not decoration: this step only runs on a job that has already failed, and a hiccup reporting the failure (a rate limit, a deleted monitor) must never be what turns the job red a second time.

# optional last step — scheduled workflow
- name: Report failure detail to LastPing
  if: failure()
  env:
    LASTPING_CI_SECRET: ${{ secrets.LASTPING_CI_SECRET }}
    LASTPING_CHECK_ID: ${{ secrets.LASTPING_CHECK_ID }}
    DETAIL: ${{ github.workflow }} / ${{ github.job }} failed on ${{ github.ref_name }} — run ${{ github.run_id }}
  run: |
    curl -fsS -X POST -H "Content-Type: text/plain" \
      -H "X-LastPing-Token: $LASTPING_CI_SECRET" \
      --data "$DETAIL" \
      "https://ping.lastping.dev/ci/$LASTPING_CHECK_ID/detail" || true

What this specifically catches for scheduled workflows

The webhook covers the failures that GitHub's built-in notifications miss.

  • The 60-day silent disable: no workflow_run event arrives in the expected window; the schedule window deadline passes → incident opens. This is the case GitHub never notifies you about.
  • Failed scheduled runs: workflow_run arrives with conclusion: failure; incident opens with link to the run and failure detail if you added the optional step.
  • Hung scheduled runs: a run that starts but never completes within the completion window; the overrun opens an incident before GitHub's job timeout fires.
  • Alert to the right people: LastPing alerts your configured destinations (email, Slack, Discord, Telegram, webhook, ntfy, Pushover, Microsoft Teams, Google Chat), not just the last cron committer.
  • Recovery: the next successful run closes the incident automatically. No manual reset.

For all GitHub Actions workflows (not just scheduled), see the general GitHub Actions monitoring guide. For cron jobs, Kubernetes jobs, and systemd timers, see the monitoring guides index. AI agents that run on a schedule can also self-register their own monitors via MCP.

Questions people ask

Front-loaded answers: the most important fact first.

  • Why did my GitHub Actions scheduled workflow stop running?

    GitHub automatically disables schedule: workflows in public repositories after 60 days without any commits, pull requests, or other repository activity. GitHub may email a warning beforehand to the person who last changed the cron line, but nothing reaches your team, and the disable itself sends no notification. The workflow YAML is still there and the cron expression is still defined, but the trigger simply stops firing. The only way to detect this from outside is a dead-man's-switch monitor that expects a run signal at your cron cadence and opens an incident when the signal doesn't arrive.

  • How is this page different from /monitor/github-actions/?

    The general GitHub Actions monitoring guide covers all workflow types including push-triggered, pull-request, and manual workflows. This page focuses specifically on the schedule: trigger: the 60-day silent disable, the notification gap (only the last cron-committer gets emailed), and why the webhook approach with an expected-schedule window is the right solution for scheduled-only monitoring.

  • Does GitHub warn you before disabling a scheduled workflow?

    Not reliably. GitHub may email a warning beforehand to the person who last changed the cron line, but nothing reaches your team, and there is no UI indicator that a workflow is approaching the limit. The workflow status page shows successful runs up until the last run, then nothing. There is no 'workflow disabled' event and no notification when the disable happens. The only signal is the absence of runs, which requires an external monitor to detect.

  • Why does this need a schedule window, not just a webhook?

    A webhook fires when a run happens. If the run never happens (60-day disable, network issue at GitHub's side, cron drift), no webhook fires. The expected schedule window in LastPing is the key mechanism: if the run signal doesn't arrive within [cron period + grace], an incident opens regardless of whether the webhook ever fired.

  • Does the monitoring work without changing the workflow YAML?

    Yes. The primary monitoring mechanism is a signed workflow_run webhook registered once in repository Settings > Webhooks. LastPing receives a delivery every time the workflow runs (or should run), verifies the HMAC signature, and tracks the expected schedule externally. No YAML change is needed. Optionally, an if: failure() step can attach the failure log to the incident, but the monitoring itself is YAML-free.

  • What does LastPing alert on for scheduled GitHub Actions?

    Three signals: (1) a workflow_run event arrives with conclusion: failure (the run failed); (2) a workflow_run event arrives with conclusion: null after the timeout (the run hung); (3) no workflow_run event arrives within the expected schedule window plus grace (the run never started, which includes the 60-day silent disable case).

  • How do I re-enable a 60-day disabled workflow?

    Re-enable it explicitly: Actions → your workflow → Enable workflow in the GitHub UI, gh workflow enable <workflow> from the GitHub CLI, or the REST API's enable endpoint. These are the routes GitHub documents; a new commit is not one of them. With a LastPing monitor, you find out it's disabled before it's been silent for days.

  • Is this free?

    Yes. LastPing is free for individuals, and CI/CD monitoring is a first-class feature with no monitor cap. See the general GitHub Actions guide for setup details, or compare free cron monitoring tools.

FREE FOR INDIVIDUALS · FULLY HOSTED

Your nightly backup is one quiet repo away from disappearing.

One webhook now beats finding out 60 days later. First alert wired up in about two minutes, and LastPing monitors itself the same way.