A scheduled workflow that does not run leaves no failed job
One curl step is enough.
GitHub scheduled workflows are cron with extra excuses. The docs are clear: schedules can be delayed or skipped on inactive repos. A workflow that deploys, syncs data or rotates something still needs a signal when it did not run.
Add a last step
- name: Ping success
if: success() run: curl -fsS -m 10 --retry 5 ${{ secrets.PING_URL }}
Keep the URL in a secret. Add a matching /fail step on failure if you want the alert before grace.
Repo inactivity
If nobody pushes, GitHub may pause schedules. That is exactly the case where you still want the heartbeat, and also a reminder that the repo needs a commit or a different runner.
Self-hosted runners
If the workflow needs a runner that is down, you get no job, so no ping. The check going late is the alert. Do not rely only on GitHub's email for "actions are failing".
FAQ
Can I use the GitHub Checks API instead?
You can build that. A ping is less code and works the same as your server cron jobs, so on-call has one pattern.
What period should I set?
Match the workflow cron. Daily workflow: 24h period plus a grace that covers queue delay, often 30 to 60 minutes.