Monitor GitHub Actions — and get told why a run failed
Point one signed workflow_run
webhook from your repository at LastPing — zero changes to your
workflow YAML. Every run reports in; a run that fails, hangs, or never
starts opens an incident, alerts you where you work, and deep-links to
the run. Free for individuals, no monitor cap.
Scheduled workflows fail silently. By design.
If you run a nightly build, a scraper, a DB backup, or a cert renewal on a GitHub Actions schedule, three failure modes are waiting for you — and GitHub tells you about none of them reliably.
The 60-day silent disable
GitHub automatically disables schedule-triggered
workflows after 60 days without repository activity. No error, no
email — your nightly backup just stops existing.
Email to the wrong person
A failed scheduled run only notifies the user who last touched the workflow's cron — often a teammate who left, or you, in an inbox filter you stopped reading months ago.
The hung run
A run that starts and never finishes — stuck runner, hung step, infinite retry — notifies nobody. It isn't a failure yet, so no failure email ever comes.
Adding a curl ping step to each workflow (the classic
heartbeat approach) fixes none of the hard cases: the step never
executes when the runner hangs or when the schedule was silently
disabled. The fix is to listen to GitHub's own run signal instead —
and to expect it on a schedule, so absence is an alert too.
Setup: one webhook, about two minutes
No YAML changes, no agent, no GitHub App permissions — a plain repository webhook, HMAC-verified on every delivery.
Create a CI check in LastPing
In the console, create a check, choose Monitor a CI/CD pipeline, and select GitHub. Give it the same schedule as your workflow (e.g. daily with a grace window) so a run that never starts is caught too. Copy the webhook URL and the one-time secret shown on screen.
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 (untick the pre-selected Pushes)
Done — every run now reports in
LastPing verifies each delivery's HMAC signature against your
secret, then classifies the run: success, failure, started.
Branch and workflow filters let you count only the runs you care
about (say, main and the workflow named
nightly-backup). Alerts go to email by default —
your verified address is attached automatically — and to
Telegram, Slack, Discord, or a signed webhook if you add them.
Optional: attach the failure reason to the incident
One if: failure() step POSTs a log excerpt (up to
64 KB, plain text) to the check's detail endpoint. It's
stored on the open incident and shown in the console — so the
alert doesn't just say "it broke," it shows why. The body is
never logged server-side.
What this catches
The same durable detection engine as LastPing's cron monitoring — deadlines live in the database, so a restart never misses a due check.
- Failed runs — incident opens with a deep link to the exact run, plus the failure detail if you added the optional step.
- Hung runs — the run started but never completed; the completion signal doesn't arrive in the window, and that silence opens an incident.
- Runs that never start — including scheduled workflows GitHub silently disabled after 60 days of repo inactivity. No run signal in the expected window → incident.
- Recovery — the next successful run closes the incident and sends a recovery notice automatically. No manual reset.
- Flap protection — a run that fails and immediately recovers within the damping window doesn't page you.
Prefer the classic style? You can still end any workflow job with
curl -fsS https://ping.lastping.dev/<id> as a plain
heartbeat — it works, and it's the right tool for scripts inside
a run. Just know its limits: it can't see hung runs or disabled
schedules. The webhook can. GitLab CI
and Jenkins are supported the same way —
or see the copy-paste guides for cron,
Kubernetes, systemd, and more.
Questions people ask
Front-loaded answers — the most important fact first.
-
How do I get alerted when a GitHub Actions workflow fails?
Point one signed
workflow_runwebhook from your repository at LastPing (Settings → Webhooks → Add webhook) — zero changes to your workflow YAML. Every run reports in; a failed, hung, or never-started run opens an incident and alerts you by email, Telegram, Slack, Discord, or webhook, with a deep link to the run. Free, no monitor cap. -
Why did my scheduled GitHub Action stop running?
GitHub automatically disables scheduled workflows after 60 days without repository activity, and it does this silently. Failed scheduled runs also only email the user who last touched the workflow's cron schedule, and a run that hangs notifies nobody. A dead-man's-switch monitor catches all three cases: it expects a run signal on your schedule and opens an incident when the signal doesn't arrive.
-
Do I need to change my workflow YAML?
No. Monitoring uses GitHub's own
workflow_runwebhook, registered once per repository in Settings → Webhooks. Optionally, a one-lineif: failure()step attaches the failure log excerpt to the incident — but the monitoring itself needs zero YAML changes. -
Does this work for private repositories?
Yes. GitHub delivers repository webhooks for private repositories exactly as for public ones. LastPing verifies each delivery against your webhook secret (HMAC signature) before processing, and never needs read access to your code.
-
Is this free?
Yes. CI/CD monitoring is a first-class free feature — no monitor cap. GitLab CI and Jenkins are supported the same way. See how LastPing compares to Healthchecks.io and Cronitor.
Your next silent failure is already scheduled.
One webhook now beats a post-mortem later. First alert wired up in about two minutes — and LastPing monitors itself the same way.