From 377b79eb8551500bbc63afb1d88dfc86fe578c0f Mon Sep 17 00:00:00 2001 From: tjjfvi Date: Mon, 20 Mar 2023 15:16:51 -0400 Subject: [PATCH] ... --- server/capi.dev/delegator.ts | 46 +++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/server/capi.dev/delegator.ts b/server/capi.dev/delegator.ts index d999b7480..1329afaa3 100644 --- a/server/capi.dev/delegator.ts +++ b/server/capi.dev/delegator.ts @@ -4,23 +4,22 @@ import { f, handleErrors } from "../mod.ts" serve(handleErrors(handler)) -const delegateeProjectId = "70eddd08-c9b0-4cb3-b100-8c6facf52f1e" - +const ttl = 60_000 const shaAbbrevLength = 8 -const GITHUB_API_REPO = "https://api.github.com/repos/paritytech/capi" - const rTagVersion = /^v(\d+\.\d+\.\d+(?:-.+)?)$/ const rPrVersion = /^pr:(\d+)$/ - const rVersionedUrl = /^(?:\/@(.+?))?(\/.*)?$/ +const delegateeProjectId = "70eddd08-c9b0-4cb3-b100-8c6facf52f1e" +const githubApiBase = "https://api.github.com/repos/paritytech/capi" + const { signal } = new AbortController() async function handler(request: Request) { const url = new URL(request.url) const [, version, path = "/"] = rVersionedUrl.exec(url.pathname)! - if (!version) throw f.notFound() + if (!version) return f.redirect(`/@${await defaultVersion()}${path}`) const sha = await getSha(version) let normalizedVersion if (rTagVersion.test(version)) { @@ -39,8 +38,16 @@ async function handler(request: Request) { }) } -const shaTtl = 60_000 -const shaMemo = new TimedMemo(shaTtl, signal) +const defaultVersionMemo = new TimedMemo(ttl, signal) +async function defaultVersion() { + return await defaultVersionMemo.run(undefined, async () => { + const release = (await github(`releases/latest`)) + ?? (await github(`releases`))[0] + return release.tag_name + }) +} + +const shaMemo = new TimedMemo(ttl, signal) async function getSha(version: string): Promise { const ref = version .replace(rPrVersion, "pull/$1/head") @@ -48,28 +55,25 @@ async function getSha(version: string): Promise { .replace(/:/g, "/") return await shaMemo.run( ref, - async () => (await json(`${GITHUB_API_REPO}/commits/${ref}`)).sha, + async () => (await github(`commits/${ref}`)).sha, ) } -const deploymentTtl = 60_000 -const deploymentMemo = new TimedMemo(deploymentTtl, signal) +const deploymentMemo = new TimedMemo(ttl, signal) async function getDeployment(sha: string) { return await deploymentMemo.run(sha, async () => { - const deployments: GithubDeployment[] = await json( - `${GITHUB_API_REPO}/deployments?sha=${sha}`, - ) + const deployments = await github(`deployments?sha=${sha}`) const deployment = deployments.find((x) => x.payload.project_id === delegateeProjectId) if (!deployment) throw f.notFound() - const statuses: GithubStatus[] = await json(deployment.statuses_url) + const statuses = await github(deployment.statuses_url) const url = statuses.map((x) => x.environment_url).find((x) => x) if (!url) throw f.notFound() return url }) } -async function json(url: string) { - const response = await fetch(url) +async function github(url: string): Promise { + const response = await fetch(new URL(url, githubApiBase)) if (!response.ok) throw new Error(`${url}: invalid response`) return await response.json() } @@ -82,3 +86,11 @@ interface GithubDeployment { interface GithubStatus { environment_url?: string } + +interface GithubRelease { + tag_name: string +} + +interface GithubCommit { + sha: string +}