feat(ci): add scheduled site reachability health check #2

Merged
peterswimm merged 1 commit from feat/site-health-check into master 2026-09-03 14:18:03 +00:00
Owner

Scope

Adds one new workflow file, .forgejo/workflows/site-health-check.yml. Does
not touch build-deploy.yml or pr-policy-check.yml.

An org-wide CI-coverage audit found that build-deploy.yml deploys on every
push to master but there's no scheduled check that the deployed domains are
actually still reachable in between deploys. This closes that gap with a
read-only reachability check, mirroring Toilville/toilville_rituals's
.forgejo/workflows/healthcheck.yml curl-based check() pattern.

What it checks

The four domains this repo builds for (from sites/*/site.json, matching the
build-deploy.yml matrix):

  • https://peterswimm.com
  • https://pulsewave.rip
  • https://toilville.dev
  • https://truechiptilldeath.com

Runs on a daily schedule (10 10 * * *, an off-peak UTC slot) plus
workflow_dispatch for manual runs. runs-on/container match the
reference workflow's [self-hosted, linux, x64] + alpine/curl:latest.

No Mailgun/alerting integrationfj actions secrets list returned no
repo-level secrets for this repo, so I couldn't confirm MAILGUN_* secrets
are provisioned here the way they are for the reference repo's healthcheck.
Per the org's simpler-checks convention, a failing/red scheduled run is the
signal; someone can layer alerting on later once secrets are confirmed.

Important caveat, worth a human look before merge: build-deploy.yml's
own header comment says it only ever rsyncs build output to a staging path
on toilville-forge — nginx cutover to actually serve traffic from that path
is a separate, manual, per-domain step. So depending on where each domain
currently stands in that migration, this check may currently be validating
the pre-existing (e.g. WordPress) origin rather than this repo's static
build output. That's still a legitimate reachability check worth having, but
it isn't "did the last deploy go live" — I called this out in the workflow's
own header comment too so it doesn't get misread later.

Testing

  • Validated the new file's YAML with python3 -c "import yaml; yaml.safe_load(...)"
    (parses cleanly) and with yamllint — the only findings are the same
    default-style warnings (80-char line length, missing --- doc start,
    on: truthy-key warning) that yamllint also raises against the existing
    healthcheck.yml and this repo's own build-deploy.yml, so nothing new.
  • Manually curled all four domains from outside the runner to sanity-check
    the expected status codes: toilville.dev returned 200. The other
    three (peterswimm.com, pulsewave.rip, truechiptilldeath.com)
    currently returned 403 from Cloudflare with body "Your request was
    blocked" — this reads like Cloudflare Bot Fight Mode/WAF flagging a
    non-browser client rather than an actual outage (the reference
    healthcheck.yml uses the same UA successfully against toilville.com,
    which sits on a less strict zone). I don't have a way to trigger the
    actual self-hosted runner pre-merge to confirm whether its egress gets
    the same treatment.
  • No existing tests or workflows touched, so no regression risk to the
    build/deploy path itself.

Impact Statement

  • Existing features — none affected; no existing workflow files
    modified.
  • Public APIs / contracts — none.
  • Schemas — none.
  • Data / artifacts — none; this workflow is read-only (curl GETs only).
  • Integrations — new: a scheduled Forgejo Actions job. No alerting
    integration added (see caveat above).
  • Mappings — none.
  • Backward compatibility — no impact; purely additive.

Needs human action before/after merge: please manually trigger
workflow_dispatch once merged and confirm the self-hosted runner doesn't
hit the same Cloudflare block I saw testing externally on
peterswimm.com/pulsewave.rip/truechiptilldeath.com. If it does, this
job will run red every night for reasons unrelated to actual site health,
and the fix is on the Cloudflare side (allowlist the runner's egress
IP/UA for those three zones), not in this workflow.

## Scope Adds one new workflow file, `.forgejo/workflows/site-health-check.yml`. Does not touch `build-deploy.yml` or `pr-policy-check.yml`. An org-wide CI-coverage audit found that `build-deploy.yml` deploys on every push to `master` but there's no scheduled check that the deployed domains are actually still reachable in between deploys. This closes that gap with a read-only reachability check, mirroring `Toilville/toilville_rituals`'s `.forgejo/workflows/healthcheck.yml` curl-based `check()` pattern. ## What it checks The four domains this repo builds for (from `sites/*/site.json`, matching the `build-deploy.yml` matrix): - `https://peterswimm.com` - `https://pulsewave.rip` - `https://toilville.dev` - `https://truechiptilldeath.com` Runs on a daily schedule (`10 10 * * *`, an off-peak UTC slot) plus `workflow_dispatch` for manual runs. `runs-on`/`container` match the reference workflow's `[self-hosted, linux, x64]` + `alpine/curl:latest`. **No Mailgun/alerting integration** — `fj actions secrets list` returned no repo-level secrets for this repo, so I couldn't confirm `MAILGUN_*` secrets are provisioned here the way they are for the reference repo's healthcheck. Per the org's simpler-checks convention, a failing/red scheduled run is the signal; someone can layer alerting on later once secrets are confirmed. **Important caveat, worth a human look before merge:** `build-deploy.yml`'s own header comment says it only ever rsyncs build output to a *staging* path on toilville-forge — nginx cutover to actually serve traffic from that path is a separate, manual, per-domain step. So depending on where each domain currently stands in that migration, this check may currently be validating the pre-existing (e.g. WordPress) origin rather than this repo's static build output. That's still a legitimate reachability check worth having, but it isn't "did the last deploy go live" — I called this out in the workflow's own header comment too so it doesn't get misread later. ## Testing - Validated the new file's YAML with `python3 -c "import yaml; yaml.safe_load(...)"` (parses cleanly) and with `yamllint` — the only findings are the same default-style warnings (80-char line length, missing `---` doc start, `on:` truthy-key warning) that `yamllint` also raises against the existing `healthcheck.yml` and this repo's own `build-deploy.yml`, so nothing new. - Manually curled all four domains from outside the runner to sanity-check the expected status codes: `toilville.dev` returned `200`. The other three (`peterswimm.com`, `pulsewave.rip`, `truechiptilldeath.com`) currently returned `403` from Cloudflare with body "Your request was blocked" — this reads like Cloudflare Bot Fight Mode/WAF flagging a non-browser client rather than an actual outage (the reference `healthcheck.yml` uses the same UA successfully against `toilville.com`, which sits on a less strict zone). I don't have a way to trigger the actual self-hosted runner pre-merge to confirm whether *its* egress gets the same treatment. - No existing tests or workflows touched, so no regression risk to the build/deploy path itself. ## Impact Statement - **Existing features** — none affected; no existing workflow files modified. - **Public APIs / contracts** — none. - **Schemas** — none. - **Data / artifacts** — none; this workflow is read-only (curl GETs only). - **Integrations** — new: a scheduled Forgejo Actions job. No alerting integration added (see caveat above). - **Mappings** — none. - **Backward compatibility** — no impact; purely additive. **Needs human action before/after merge:** please manually trigger `workflow_dispatch` once merged and confirm the self-hosted runner doesn't hit the same Cloudflare block I saw testing externally on `peterswimm.com`/`pulsewave.rip`/`truechiptilldeath.com`. If it does, this job will run red every night for reasons unrelated to actual site health, and the fix is on the Cloudflare side (allowlist the runner's egress IP/UA for those three zones), not in this workflow.
feat(ci): add scheduled site reachability health check
All checks were successful
PR policy check / policy-gate (pull_request) Successful in 0s
127b7c1bd7
build-deploy.yml deploys on every push but had zero scheduled coverage
checking whether the deployed domains are still reachable in between
deploys. Add a curl-based health check (mirrors toilville_rituals's
healthcheck.yml pattern) that runs daily plus on manual dispatch
against the four domains this repo builds for.
peterswimm deleted branch feat/site-health-check 2026-09-03 14:18:03 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Toilville/toilville-static-sites!2
No description provided.