Skip to content

feat: add /health endpoint + Docker HEALTHCHECK#20

Merged
heznpc merged 1 commit intomainfrom
feat/healthcheck-endpoint
Apr 23, 2026
Merged

feat: add /health endpoint + Docker HEALTHCHECK#20
heznpc merged 1 commit intomainfrom
feat/healthcheck-endpoint

Conversation

@heznpc
Copy link
Copy Markdown
Member

@heznpc heznpc commented Apr 23, 2026

Summary

Mirrors the pattern just landed in discord-bot-starter (#24) so Fly.io / Railway / Docker can detect a crashed or disconnected bot.

  • src/lib/health.js — zero-dep http server. Readiness is bot.isRunning() in polling mode and bot.isInited() in webhook mode. Exports both createHealthServer (standalone) and createHealthHandler (mount on an existing server).
  • src/index.js — polling mode runs a standalone health server on HEALTH_PORT; webhook mode mounts /health on the existing grammY webhookCallback server instead of spawning a second listener (keeps the container single-port — important for Fly.io [[http_service]] and Railway's one-port-per-service model).
  • DockerfileEXPOSE 3000 + HEALTHCHECK wget --spider. Alpine ships wget, no extra package.
  • .env.exampleHEALTH_PORT=3000 with a comment.
  • READMEs (EN + KR) — new Health Check section with Fly.io [[http_service.checks]] + Railway instructions.

Tests

  • tests/health.test.js (new) — ephemeral-port (port: 0) integration tests against a real http.get client. Covers 200 + JSON shape when ready, 503 when not, 404 for unknown paths, and in webhook-mount mode also verifies fallback delegation so /health doesn't shadow the webhook route.
  • tests/commands.test.js — audit finding: the previous file was structural identity checks only (toHaveProperty('name')). Upgraded /start and /help to real mock-ctx unit tests (reply-text assertion, error-swallow check, and a /help test that runs the real loader and asserts every registered command appears in the reply). Structural checks retained so new commands keep getting shape-validated.

All 14 tests pass locally; lint clean.

Test plan

  • npm run lint clean
  • npm test all green locally (14/14)
  • CI green on PR
  • Manually verified: docker build + docker run shows (healthy) within the start-period (left to the reviewer — local Docker smoke test)

Implementation notes for reviewers

  • Polling mode uses bot.isRunning(), which flips true as soon as bot.start() enters its polling loop (before onStart fires) — exactly the readiness semantics we want for orchestrators.
  • Webhook mode uses bot.isInited() because the bot never calls .start()setWebhook is a one-shot API call. isInited() goes true after grammY auto-fetches bot identity on the first update.
  • Shutdown order: close health server → close webhook server (if any) → bot.stop()process.exit(0).

Mirrors the pattern recently shipped in discord-bot-starter (#24) so
Fly.io / Railway / Docker can detect a crashed or disconnected bot.

- `src/lib/health.js` — zero-dep http server. Readiness reads
  `bot.isRunning()` in polling mode and `bot.isInited()` in webhook
  mode. Also exports `createHealthHandler` so webhook mode can mount
  /health on the existing webhook server instead of opening a second
  port.
- `src/index.js` — polling mode spins up a standalone health server on
  HEALTH_PORT; webhook mode composes /health onto the webhookCallback
  handler. Shutdown closes both cleanly.
- `Dockerfile` — `EXPOSE 3000` + `HEALTHCHECK wget --spider` on
  HEALTH_PORT. Alpine ships wget, so no extra package.
- `.env.example` — document HEALTH_PORT.
- READMEs (EN + KR) — new Health Check section with Fly.io
  `[[http_service.checks]]` + Railway snippets.
- `tests/health.test.js` — ephemeral-port integration tests for
  200/503/404 in polling mode plus 200/503 + fallback delegation in
  webhook-mount mode.
- `tests/commands.test.js` — existing structural tests were identity
  checks. Upgraded with real mock-ctx unit tests for /start (reply
  text + error-swallow) and /help (real loader feeds real command
  list into the reply). Structure checks retained.
@heznpc heznpc merged commit ed79363 into main Apr 23, 2026
3 checks passed
@heznpc heznpc deleted the feat/healthcheck-endpoint branch April 23, 2026 19:08
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.

1 participant