Introduce a Cloudflare health worker (#2499)

This PR introduces a new Cloudflare worker for health checks.

At the moment the worker only translates Updown webhooks into Discord
webhooks. In the future we can teach this worker to check more things.

### Change Type

- [x] `internal` — Any other changes that don't affect the published
package

---------

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
Dan Groshev 2024-01-29 09:47:50 +00:00 committed by GitHub
parent a1e242ae3a
commit 3a3248a636
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 428 additions and 7 deletions

View file

@ -12,6 +12,7 @@ import { makeEnv } from './lib/makeEnv'
import { nicelog } from './lib/nicelog'
const worker = path.relative(process.cwd(), path.resolve(__dirname, '../apps/dotcom-worker'))
const healthWorker = path.relative(process.cwd(), path.resolve(__dirname, '../apps/health-worker'))
const assetUpload = path.relative(
process.cwd(),
path.resolve(__dirname, '../apps/dotcom-asset-upload')
@ -26,6 +27,8 @@ const env = makeEnv([
'CLOUDFLARE_ACCOUNT_ID',
'CLOUDFLARE_API_TOKEN',
'DISCORD_DEPLOY_WEBHOOK_URL',
'DISCORD_HEALTH_WEBHOOK_URL',
'HEALTH_WORKER_UPDOWN_WEBHOOK_PATH',
'GC_MAPS_API_KEY',
'RELEASE_COMMIT_HASH',
'SENTRY_AUTH_TOKEN',
@ -73,7 +76,7 @@ async function main() {
await discordMessage(`--- **${env.TLDRAW_ENV} deploy pre-flight** ---`)
await discordStep('[1/6] setting up deploy', async () => {
await discordStep('[1/7] setting up deploy', async () => {
// make sure the tldraw .css files are built:
await exec('yarn', ['lazy', 'prebuild'])
@ -83,15 +86,16 @@ async function main() {
// deploy pre-flight steps:
// 1. get the dotcom app ready to go (env vars and pre-build)
await discordStep('[2/6] building dotcom app', async () => {
await discordStep('[2/7] building dotcom app', async () => {
await createSentryRelease()
await prepareDotcomApp()
await uploadSourceMaps()
await coalesceWithPreviousAssets(`${dotcom}/.vercel/output/static/assets`)
})
await discordStep('[3/6] cloudflare deploy dry run', async () => {
await discordStep('[3/7] cloudflare deploy dry run', async () => {
await deployAssetUploadWorker({ dryRun: true })
await deployHealthWorker({ dryRun: true })
await deployTlsyncWorker({ dryRun: true })
})
@ -100,16 +104,19 @@ async function main() {
await discordMessage(`--- **pre-flight complete, starting real deploy** ---`)
// 2. deploy the cloudflare workers:
await discordStep('[4/6] deploying asset uploader to cloudflare', async () => {
await discordStep('[4/7] deploying asset uploader to cloudflare', async () => {
await deployAssetUploadWorker({ dryRun: false })
})
await discordStep('[5/6] deploying multiplayer worker to cloudflare', async () => {
await discordStep('[5/7] deploying multiplayer worker to cloudflare', async () => {
await deployTlsyncWorker({ dryRun: false })
})
await discordStep('[6/7] deploying health worker to cloudflare', async () => {
await deployHealthWorker({ dryRun: false })
})
// 3. deploy the pre-build dotcom app:
const { deploymentUrl, inspectUrl } = await discordStep(
'[6/6] deploying dotcom app to vercel',
'[7/7] deploying dotcom app to vercel',
async () => {
return await deploySpa()
}
@ -119,7 +126,7 @@ async function main() {
if (previewId) {
const aliasDomain = `${previewId}-preview-deploy.tldraw.com`
await discordStep('[7/6] aliasing preview deployment', async () => {
await discordStep('[8/7] aliasing preview deployment', async () => {
await vercelCli('alias', ['set', deploymentUrl, aliasDomain])
})
@ -217,6 +224,41 @@ name = "${previewId}-tldraw-multiplayer"`
)
}
let didUpdateHealthWorker = false
async function deployHealthWorker({ dryRun }: { dryRun: boolean }) {
if (previewId && !didUpdateHealthWorker) {
appendFileSync(
join(healthWorker, 'wrangler.toml'),
`
[env.preview]
name = "${previewId}-tldraw-health"`
)
didUpdateHealthWorker = true
}
await exec(
'yarn',
[
'wrangler',
'deploy',
dryRun ? '--dry-run' : null,
'--env',
env.TLDRAW_ENV,
'--var',
`DISCORD_HEALTH_WEBHOOK_URL:${env.DISCORD_HEALTH_WEBHOOK_URL}`,
'--var',
`HEALTH_WORKER_UPDOWN_WEBHOOK_PATH:${env.HEALTH_WORKER_UPDOWN_WEBHOOK_PATH}`,
],
{
pwd: healthWorker,
env: {
NODE_ENV: 'production',
// wrangler needs CI=1 set to prevent it from trying to do interactive prompts
CI: '1',
},
}
)
}
type ExecOpts = NonNullable<Parameters<typeof exec>[2]>
async function vercelCli(command: string, args: string[], opts?: ExecOpts) {
return exec(