Scheduled GitHub Actions Workflow Silence and Failure Report avatar

Scheduled GitHub Actions Workflow Silence and Failure Report

Pricing

from $20.00 / 1,000 run starteds

Go to Apify Store
Scheduled GitHub Actions Workflow Silence and Failure Report

Scheduled GitHub Actions Workflow Silence and Failure Report

Watches scheduled GitHub Actions workflows and reports the ones that stopped to fire, that fail again and again, or that GitHub disabled for inactivity. One dataset record for each workflow plus one summary record. HTTP only, no browser, no proxy.

Pricing

from $20.00 / 1,000 run starteds

Rating

0.0

(0)

Developer

kingii98

kingii98

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

GitHub tells you when a workflow run fails. It does not tell you when a scheduled workflow stops to run at all. GitHub also disables a scheduled workflow in a repository without recent activity, and it sends no alert when it does so. An uptime monitor cannot see this, because the job that must fire is the thing that went silent.

This Actor reads the current state of your scheduled workflows from the public GitHub REST API and reports three conditions:

ConditionWhat it means
OverdueThe newest run is older than the interval that you declared for this schedule.
FailingThe newest runs failed, one after the other, up to your threshold.
DisabledGitHub set the workflow to a disabled state, usually disabled_inactivity.

Run it on an Apify schedule every hour or every 3 hours. It needs no browser, no proxy and no paid API. A GitHub token is optional and stays yours.

Input

FieldTypeDefaultDescription
workflowsarraythree public repositories1 to 100 records. Each record holds owner_repo, workflow_file and expected_max_interval_minutes.
githubTokenstring (secret)noneOptional. Necessary for private repositories. It also lifts the anonymous rate limit of 60 requests for each hour.
failureStreakThresholdinteger2The Actor raises a failure alert after this many failed runs in a row.
alertWebhookUrlstringemptyOptional. One public HTTPS URL. The Actor sends one JSON POST with every new alert of the run.
runEventFilterselectscheduleschedule counts only the runs that the cron trigger started. any counts every run.
runsPerWorkflowinteger10How many recent runs are read. The failure streak cannot become longer than this.
suppressRepeatAlertsbooleantrueKeeps one cursor for each workflow, so the same alert is not repeated on every tick.
stateStoreNamestringgha-schedule-monitor-stateName of the named key-value store that holds the cursors. Give two schedules two different names when they must alert on their own.
confirmSilencebooleantrueRead the run list a second time before a silence alert is raised. See False silence.
silenceConfirmDelaySecondsinteger3Pause before that second read. It happens once for the whole run.
timeoutSecondsinteger15Timeout for one call to the GitHub REST API.
requestsPerSecondinteger5Rate limit for the calls to api.github.com.
maxResponseBytesinteger2000000Hard cap on the bytes read from one API answer.

Example input

{
"workflows": [
{
"owner_repo": "acme/data-platform",
"workflow_file": "nightly-sync.yml",
"expected_max_interval_minutes": 1500
},
{
"owner_repo": "acme/infra",
"workflow_file": "backup.yml",
"expected_max_interval_minutes": 480
}
],
"failureStreakThreshold": 2,
"alertWebhookUrl": "https://hooks.example.com/gha-silence"
}

workflow_file is the file name of the workflow, such as nightly-sync.yml, or its numeric workflow id. A full path such as .github/workflows/nightly-sync.yml is also accepted and is reduced to the file name.

Set expected_max_interval_minutes a little above the real cadence of the cron. A GitHub schedule can start some minutes late when the runner queue is busy, so a daily job is well served by 1500 and not by 1440.

Output

One dataset record for each workflow:

FieldDescription
ownerRepo, workflowFile, workflowName, workflowId, workflowUrlIdentity of the workflow.
workflowStateactive, disabled_inactivity, disabled_manually or disabled_fork.
lastRunConclusion, lastRunStatus, lastRunAt, lastRunId, lastRunUrlThe newest finished run.
expectedMaxIntervalMinutes, minutesSinceLastRun, minutesOverdue, overdueThe silence check.
failureStreak, failureStreakThreshold, failingThe failure check.
disabledtrue when GitHub disabled the workflow.
alert, alertReasons, alertDelivered, alertSuppressedThe alert verdict. alertReasons holds overdue, failing, disabled or never-ran.
status, note, httpStatus, checkedAtOK, ALERT, or the reason why the workflow could not be read.

And one summary record:

{
"recordType": "summary",
"totalWorkflows": 12,
"workflowsChecked": 12,
"overdueCount": 1,
"failingCount": 0,
"disabledCount": 1,
"alertCount": 2,
"alertsDelivered": 2,
"alertsSuppressed": 0,
"errorCount": 0,
"allOk": false,
"status": "ATTENTION",
"silenceConfirmations": 0,
"requestsSent": 24
}

Alerts

An alert is raised for every workflow that is overdue, failing or disabled. With suppressRepeatAlerts on, the Actor keeps one small cursor for each workflow in the named key-value store stateStoreName. The store must be named: the default key-value store of an Actor belongs to one run only, so a cursor written there would be lost before the next tick.

The cursor holds the last alerted run id and the last set of reasons, so an hourly schedule does not repeat the same alert on every tick. A new run, a changed set of reasons, or a workflow that recovered and then broke again, all raise a fresh alert. A suppressed repeat sends no webhook POST and is not charged again.

When alertWebhookUrl is set, the Actor sends one JSON POST for each run that holds every new alert of that run. The webhook must be a public HTTPS URL: loopback, private and reserved addresses are refused, and redirects are not followed. A webhook that does not answer is written into the summary note; it never fails the run, because the dataset already holds the same alerts.

False silence

GitHub answers the workflow run list from a replica that is sometimes weeks out of date. A stale answer names an old run as the newest one, which reads exactly like a schedule that stopped to fire. This is the one verdict that this Actor must not get wrong.

With confirmSilence on, a workflow that looks silent is read a second time before the alert is raised, and the newer of the two answers wins. The second read waits silenceConfirmDelaySeconds and carries Cache-Control: no-cache, because the run list is served with a cache lifetime of 60 seconds and a second read must not repeat the first page. The pause happens once for the whole run. A healthy workflow is read twice, as usual, and never pays for the third call.

Rate limit

Without a token, GitHub allows 60 requests for each hour from one IP address. The Actor sends 2 requests for each workflow, and one more for each workflow that looks silent, so an anonymous run covers about 30 healthy workflows in one hour. On shared infrastructure that budget is shared with everything else that leaves the same address, so an hourly schedule on more than a few workflows will meet the limit.

Supply your own githubToken to raise the limit to 5000 requests for each hour and to reach private repositories. The token is sent only to api.github.com.

A workflow that could not be read because of the rate limit is reported with status: "RATE_LIMITED", it is not charged as a check, and it does not raise a false silence alert. The run still ends SUCCEEDED.

Run outcome

A business verdict never fails the run. An overdue workflow, a failing workflow, a repository that cannot be read, an exhausted rate limit and a refused webhook URL are all reported in the dataset and in the status message, and the run ends SUCCEEDED. A FAILED run means a real malfunction, or an input that cannot be parsed.

Pricing: pay per event

EventUnitPrice
run-startedOne Actor run. Charged once, after the input is accepted.$0.02
workflow-checkedOne workflow read from the GitHub REST API and evaluated. A workflow that could not be read is not charged.$0.002
silence-or-failure-alertOne alert for an overdue, failing or disabled workflow, charged the first time it is raised. A suppressed repeat of the same alert is not charged again.$0.03

A team with 20 scheduled workflows on an hourly schedule pays about $0.96 for each day when everything is healthy. The default cap for the maximum total charge inside one run stops a runaway schedule.

Limits

  • HTTP only. No browser, no proxy, no CAPTCHA service and no paid API.
  • 1 to 100 workflows in one run.
  • Read only. The Actor sends GET calls to GitHub and never changes anything.
  • Redirects are not followed, and every answer is bounded in bytes and in time.

Development

uv sync
uv run pytest
uv run ruff check .