import AppQueries from "../domain/AppQueries"; import { UpdateDefinition } from "../domain/projections/ApplicationUpdates"; import Caprover, { Application } from "../services/Caprover"; import DockerHub from "../services/DockerHub"; import Human from "../services/Human"; import Layout, { html } from "../ui/Layout"; const UpdateForm = (application: Application, latestVersions: string[]) => { // sort by number of "dots" in the version to have the most specific version first latestVersions.sort((a, b) => { return b.split(".").length - a.split(".").length; }); return html`
`; }; const FreeUpdateForm = (application: Application) => { return html`
`; }; const PendingUpdates = ( application: Application, pendingUpdates: UpdateDefinition[], logs: string ) => { if (pendingUpdates.length === 0) { return ""; } return html`

Pending updates

${logs}
`; }; const Page = ( application: Application, latestVersions: string[], pendingUpdates: UpdateDefinition[], logs: string ) => { return html`

Updating ${application.name}

${PendingUpdates(application, pendingUpdates, logs)}
Last deployment
${application.lastDeployedAt.toLocaleString("fr-FR")}
Current version
${application.dockerImage ? `Docker hub ${application.dockerImage.name}:${application.dockerImage.tag} ` : `${application.imageName}… check yourself!`}
Latest versions
${latestVersions.length === 0 ? "No version found" : UpdateForm(application, latestVersions)}
Manual update
${FreeUpdateForm(application)}
`; }; export default async ( req: Request, caprover: Caprover, dockerHub: DockerHub, human: Human, queries: AppQueries ): Promise => { if (req.method === "POST") { const body = await req.formData(); switch (body.get("action")) { case "update": const appName = body.get("appName") as string; await caprover.updateApplication( appName, body.get("version") as string ); const url = new URL(req.url); url.searchParams.set("name", appName); return new Response(null, { status: 301, headers: { Location: url.toString() }, }); case "mark-as-updated": human.markApplicationAsUpdated(body.get("appName") as string); return new Response(null, { status: 301, headers: { Location: "/applications" }, }); default: throw new Error(`Unsupported action ${body.get("action")}`); } } const applications = await caprover.getApps(); const nameFilter = new URL(req.url).searchParams.get("name"); const appToUpdate = applications .filter((app) => { // can we help to update this app? return app.dockerImage; }) .find((app) => { return nameFilter ? app.name === nameFilter : app.isOlderThan(30); }); if (!appToUpdate) { return new Response(Layout(html`

No application to update 🎉

`), { headers: { "Content-Type": "text/html" }, }); } const latestVersions = await dockerHub.getLatestVersions( appToUpdate.dockerImage!.name ); const pendingUpdates = queries.pendingApplicationUpdates(appToUpdate.name); let logs = ""; if (pendingUpdates.length > 0) { logs = await caprover.getLogs(appToUpdate.name); } return new Response( Layout(Page(appToUpdate, latestVersions, pendingUpdates, logs)), { headers: { "Content-Type": "text/html" }, } ); };