From b92c7d982618661f00ca65365792efdd56f347dd Mon Sep 17 00:00:00 2001 From: Sid Vishnoi <8426945+sidvishnoi@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:21:51 +0530 Subject: [PATCH] feat(/respec/builds): host latest release from npm (#442) --- routes/respec/builds/update.ts | 52 ++++++++++++++++++++++++++++++++++ routes/respec/index.ts | 14 +++++++++ scripts/update-data-sources.ts | 5 ++++ 3 files changed, 71 insertions(+) create mode 100644 routes/respec/builds/update.ts diff --git a/routes/respec/builds/update.ts b/routes/respec/builds/update.ts new file mode 100644 index 00000000..434939ac --- /dev/null +++ b/routes/respec/builds/update.ts @@ -0,0 +1,52 @@ +import path from "node:path"; +import { mkdir, readFile } from "node:fs/promises"; + +import type { Request, Response } from "express"; + +import { env } from "../../../utils/misc.js"; +import sh from "../../../utils/sh.js"; + +export const PKG_DIR = path.join(env("DATA_DIR"), "respec", "package"); + +export default async function route(req: Request, res: Response) { + res.type("text/plain"); + const action = req.body.action; + if (typeof action !== "string") { + return res.status(400).send("Missing 'action' in body"); + } + if (action !== "released") { + res.status(400); // Bad request + res.locals.reason = `action-not-released`; + const msg = `Webhook payload was for ${JSON.stringify(action)}, ignored.`; + return res.type("text/plain").send(msg); + } + + try { + await pullRelease(); + res.sendStatus(200); // ok + } catch (error) { + const { message = "", statusCode = 500 } = error; + console.error(`Failed to pull respec release: ${message.slice(0, 400)}...`); + res.status(statusCode); + res.send(message); + } +} + +export async function pullRelease() { + const start = Date.now(); + console.log("Pulling latest respec release..."); + + const dir = path.resolve(PKG_DIR, ".."); + await mkdir(dir, { recursive: true }); + await sh(`npm view respec dist.tarball | xargs curl -s | tar -xz --totals`, { + cwd: dir, + output: "stream", + }); + + const { version } = JSON.parse( + await readFile(path.join(PKG_DIR, "package.json"), "utf8"), + ); + console.log( + `Successfully pulled respec v${version} in ${Date.now() - start}ms.`, + ); +} diff --git a/routes/respec/index.ts b/routes/respec/index.ts index 8d7c421c..c7f6a0fb 100644 --- a/routes/respec/index.ts +++ b/routes/respec/index.ts @@ -1,6 +1,11 @@ +import path from "node:path"; import express from "express"; +import { env, ms } from "../../utils/misc.js"; +import authGithubWebhook from "../../utils/auth-github-webhook.js"; + import * as sizeRoute from "./size.js"; +import buildUpdateRoute, { PKG_DIR } from "./builds/update.js"; const router = express.Router({ mergeParams: true }); @@ -10,5 +15,14 @@ router.put( express.urlencoded({ extended: false, parameterLimit: 4, limit: "128b" }), sizeRoute.put, ); +router.use( + "/builds", + express.static(path.join(PKG_DIR, "builds"), { maxAge: ms("10m") }), +); +router.post( + "/builds/update", + authGithubWebhook(env("RESPEC_SECRET")), + buildUpdateRoute, +); export default router; diff --git a/scripts/update-data-sources.ts b/scripts/update-data-sources.ts index e6687cb3..2bd87959 100644 --- a/scripts/update-data-sources.ts +++ b/scripts/update-data-sources.ts @@ -3,6 +3,7 @@ import { mkdir } from "fs/promises"; import { env } from "../utils/misc.js"; import caniuse from "../routes/caniuse/lib/scraper.js"; import xref from "../routes/xref/lib/scraper.js"; +import { pullRelease } from "../routes/respec/builds/update.js"; import w3cGroupsList from "./update-w3c-groups-list.js"; // ensure the data directory exists @@ -19,3 +20,7 @@ console.groupEnd(); console.group("W3C Groups List"); await w3cGroupsList(); console.groupEnd(); + +console.group("Pull respec release"); +await pullRelease(); +console.groupEnd();