From 5f260ced65605d1007788f93d51775f6bde6cfe4 Mon Sep 17 00:00:00 2001 From: Leonardo Vieira Date: Mon, 22 Jun 2026 19:31:38 -0300 Subject: [PATCH 1/2] fix(consumers): serve /health on the Bolt receiver for Railway healthcheck Railway gates deploys by probing $PORT/health, and the Slack Bolt receiver is the server bound to $PORT (3004). The /health endpoint only existed on the separate webhook server (WEBHOOK_API_PORT, 3003), which Railway never probes, so the healthcheck 404'd and dev deploys failed (replicas never became healthy). Add a /health custom route to the Bolt HTTPReceiver so the probe on $PORT returns 200 and deploys can complete. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/consumers/src/clients/slack.client.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps/consumers/src/clients/slack.client.ts b/apps/consumers/src/clients/slack.client.ts index 09db973e..1ac29f6a 100644 --- a/apps/consumers/src/clients/slack.client.ts +++ b/apps/consumers/src/clients/slack.client.ts @@ -75,6 +75,20 @@ export class SlackClient implements SlackClientInterface { signingSecret, endpoints: '/slack/events', processBeforeResponse: true, + // Railway's healthcheck hits $PORT/health, and this Bolt receiver is the one + // bound to $PORT. The real /health lives on the separate webhook server + // (WEBHOOK_API_PORT), which Railway does not probe, so the check 404s and the + // deploy never goes live. Expose /health here too so the probe on $PORT gets 200. + customRoutes: [ + { + path: '/health', + method: ['GET'], + handler: (_req, res) => { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ status: 'ok' })); + }, + }, + ], }), installationStore, authorize: async (source) => { From a245bf1c52b1a364404ecae423e00b707c24f211 Mon Sep 17 00:00:00 2001 From: Leonardo Vieira <69486932+LeonardoVieira1630@users.noreply.github.com> Date: Mon, 22 Jun 2026 19:35:49 -0300 Subject: [PATCH 2/2] Update slack.client.ts --- apps/consumers/src/clients/slack.client.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/consumers/src/clients/slack.client.ts b/apps/consumers/src/clients/slack.client.ts index 1ac29f6a..824d3871 100644 --- a/apps/consumers/src/clients/slack.client.ts +++ b/apps/consumers/src/clients/slack.client.ts @@ -75,10 +75,6 @@ export class SlackClient implements SlackClientInterface { signingSecret, endpoints: '/slack/events', processBeforeResponse: true, - // Railway's healthcheck hits $PORT/health, and this Bolt receiver is the one - // bound to $PORT. The real /health lives on the separate webhook server - // (WEBHOOK_API_PORT), which Railway does not probe, so the check 404s and the - // deploy never goes live. Expose /health here too so the probe on $PORT gets 200. customRoutes: [ { path: '/health', @@ -357,4 +353,4 @@ class InMemorySessionStorage implements SlackSessionStorage { has(userId: string): boolean { return this.sessions.has(userId); } -} \ No newline at end of file +}