Skip to content

Alert only when the health check fails from three runners - #52

Merged
haphantran merged 2 commits into
mainfrom
health-check-three-runners
Nov 10, 2026
Merged

haphantran merged 2 commits into
mainfrom
health-check-three-runners

Conversation

@haphantran

Copy link
Copy Markdown
Collaborator

GitHub-hosted runners are sometimes blackholed by the network in front of the VPS. From a single runner that looks the same as an outage. Between 2026-08-20 and 2026-09-22 the old check failed 30 times, mostly as isolated runs between successes.

  • health-probe.yml (new, reusable): probes /api/health up to three times and reports up or down with the reason (DNS failure, TCP timeout, TLS failure, non-200 answer) through outputs instead of the exit code. It also logs the runner's egress IP.
  • health-check.yml: probe, then re-check from a fresh runner after 60 s, then confirm from a third after 120 s, each only if the previous stage saw the app down. The workflow fails and notifies only when all three did.

Note: GitHub disabled the scheduled Health Check workflow for inactivity, so it needs re-enabling after merge.

GitHub-hosted runners are sometimes blackholed by the network in front of the VPS, which from one runner looks the same as an outage. The check now probes from a runner, re-checks from a second after 60 s and a third after 120 s when the previous one saw the app down, and fails the workflow only if all three did. The probe lives in a reusable health-probe.yml that reports up or down with the reason, such as a DNS failure, a TCP timeout or a non-200 answer.
Copilot AI balanced review requested due to automatic review settings November 9, 2026 22:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The workflow mislabels every curl exit 28 as a TCP connection timeout, potentially attributing a stalled application response to a runner or network problem.

1 open issue
What changed in this PR

This PR reduces false outage alerts caused by individual GitHub-hosted runners being unable to reach production. It replaces the single-runner health check with three sequential probes on separate runners.

Changes:

  • Adds a reusable probe with retries, health-response validation, diagnostic outputs, and egress-IP logging.
  • Rechecks failures after 60 seconds, then confirms after another 120 seconds.
  • Reports an outage only when all three probes return down.
File Description
.github/​workflows/​health-probe.yml Adds the reusable health probe and diagnostic reporting.
.github/​workflows/​health-check.yml Orchestrates the three-stage check and final outage alert.

Review effort: Balanced

Comment thread .github/workflows/health-probe.yml Outdated
case "$1" in
6) echo "DNS lookup failed" ;;
7) echo "could not connect to the host on port 443" ;;
28) echo "no answer: the TCP connection timed out" ;;
Exit 28 also fires when the 30 s request limit expires after the connection is up, so it can't be called a TCP connect timeout.
@haphantran
haphantran merged commit ca5502d into main Nov 10, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants