This repository contains a GitHub Actions workflow that checks the availability of one or more configured HTTP endpoints on a fixed schedule and on manual demand.
The workflow is defined in:
.github/workflows/heartbeat.yml
The workflow name is heartbeat.
Create a GitHub Actions repository secret named:
SERVICE_ENDPOINT
Set its value to the endpoint URL that should be checked.
A single endpoint is valid:
<endpoint-url-1>
Multiple endpoints are also valid. Store one URL per line in the same secret:
<endpoint-url-1>
<endpoint-url-2>
<endpoint-url-3>
To add the secret:
- Open the repository on GitHub.
- Go to
Settings. - Open
Secrets and variables. - Select
Actions. - Create a new repository secret named
SERVICE_ENDPOINT. - Store one endpoint URL per line as the secret value.
No endpoint URL is stored in the workflow file.
The workflow reads SERVICE_ENDPOINT line by line.
Each non-empty line is treated as one target. Blank lines are ignored. Windows-style line endings are normalized automatically.
The workflow checks every target before exiting:
- If every target is
OKorDEGRADED, the workflow succeeds. - If at least one target is
FAILEDorTIMEOUT, the workflow fails. DEGRADEDdoes not fail the workflow.
This allows cold starts or scale-from-zero starts to complete successfully when the endpoint eventually returns a 2xx response within the timeout window.
Endpoint URLs are not printed in logs or in the workflow summary. Targets are identified only by numeric order: 1, 2, 3, and so on.
The workflow runs in two ways:
- Automatically every 5 minutes through the cron schedule.
- Manually from the GitHub Actions UI with
workflow_dispatch.
To run it manually:
- Open the
Actionstab in the repository. - Select the
heartbeatworkflow. - Click
Run workflow.
GitHub Actions scheduled workflows use UTC and support a minimum interval of 5 minutes.
The heartbeat job runs on ubuntu-latest and uses the native curl command available on the runner.
The check performs an HTTP GET request against each URL stored in SERVICE_ENDPOINT.
The request uses:
--max-time 60
This limits the total request duration to 60 seconds. This gives slow cold starts time to complete while still failing endpoints that do not respond within a bounded window.
For every checked endpoint, the workflow records:
- Execution timestamp in ISO8601 UTC format.
- Target number.
- HTTP status code.
- Response time in milliseconds.
- Downloaded response size in bytes.
- Final result.
The response time and response size are collected through curl --write-out.
The workflow classifies each run with one of these outcomes:
| Outcome | Meaning | Job Result |
|---|---|---|
OK |
The endpoint returned a 2xx status and responded in less than 2000 ms. | Success |
DEGRADED |
The endpoint returned a 2xx status but took 2000 ms or more. | Success |
FAILED |
The endpoint did not return a 2xx status, or curl failed before receiving a valid response. |
Failure |
TIMEOUT |
The request exceeded the 60 second timeout. | Failure |
If at least one endpoint is FAILED or TIMEOUT, the job exits with status code 1, so GitHub Actions marks the workflow run as failed.
Each run writes a Markdown table to the GitHub Actions run summary through:
$GITHUB_STEP_SUMMARY
The summary table contains:
| Timestamp | Target | Status | Response Time (ms) | Size (bytes) | Esito |
|---|
This table is visible in the Summary tab of each workflow run.
The Target column is a neutral numeric index based on the order of URLs in SERVICE_ENDPOINT. Endpoint URLs are not printed in logs or in the summary.
When the workflow fails with FAILED or TIMEOUT, GitHub marks the run as failed. Repository notification settings determine who receives failure emails or other alerts.
The workflow keeps the endpoint value outside the repository by reading it from SERVICE_ENDPOINT.
The workflow file does not contain:
- Hardcoded URLs.
- Service names.
- Domain names.
- Infrastructure-specific comments.
- Third-party actions.