From be8ced9fbe46cf07cec399e4801b694d032ead84 Mon Sep 17 00:00:00 2001 From: Ken Sternberg Date: Fri, 1 Nov 2024 16:13:52 -0700 Subject: [PATCH] website: add a script to automatically replace the list of available schemas. This script, `list-blueprint-schemas`, is a blunt and fragile object, but it can get the work done. Every time it is run, it will get a list of all version tags from Git, compare them to all the available schemas available by version, and print out a copy of `./website/docs/customize/blueprints/v1/structure.md` where it has replaced the existing `Available Older Blueprint Schemas` collapse block with the most up-to-date version. I will have to talk to @beryju and @tanberry to find out what they want done with this; would it be fine to just run this at build time *before* the site is compiled, replacing the structure.md file with this dynamic block, or can we generate it separately and [include it as a markdown extension](https://stackoverflow.com/questions/65741307/how-to-include-import-markdown-file-content-in-docusaurus-v2)? --- website/scripts/list-blueprint-schemas.mjs | 59 ++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 website/scripts/list-blueprint-schemas.mjs diff --git a/website/scripts/list-blueprint-schemas.mjs b/website/scripts/list-blueprint-schemas.mjs new file mode 100644 index 0000000000..d1697eb7bd --- /dev/null +++ b/website/scripts/list-blueprint-schemas.mjs @@ -0,0 +1,59 @@ +import { execSync } from "child_process"; +import { fileURLToPath } from "url"; +import { readFileSync } from "fs"; +import path from "path"; + +const __dirname = fileURLToPath(new URL(".", import.meta.url)); +const structureFilePath = path.join(__dirname, "../docs/customize/blueprints/v1/structure.md"); + +const cmd = ["git", "ls-remote", "--tags", "origin"].join(" "); +const tagblob = execSync(cmd, { encoding: "utf8" }); +const itsadate = /\d{4}\.\d{1,2}\.\d{1,2}$/; +const sortfn = (d1, d2) => { + const [y1, m1, y2, m2] = [d1[0], d1[1], d2[0], d2[1]].map((s) => parseInt(s, 10)); + return y1 < y2 ? 1 : y1 > y2 ? -1 : m1 < m2 ? 1 : m1 > m2 ? -1 : 0; +}; + +const taglines = tagblob + .split("\n") + .filter((line) => itsadate.test(line)) + .map((line) => + line + .split("\t")[1] + .replace("refs/tags/version/", "") + .replace(/\.\d{1,2}$/, "") + .split("."), + ) + .toSorted(sortfn) + .map(([a, b]) => `${a}-${b}`) + .reduce((acc, a) => (acc.includes(a) ? acc : [...acc, a]), []); + +const results = await Promise.allSettled( + taglines.map((version) => + fetch(`https://version-${version}.goauthentik.io/blueprints/schema.json`, { + method: "HEAD", + }), + ), +); + +const version = /version-(\d{4}-\d{1,2})/; + +const valid = results + .filter((result) => result.status === "fulfilled" && result.value.status === 200) + .map((result) => result.value.url) + .map((url) => { + const thedate = version.exec(url)[1]; + return `- [Version ${thedate}](${url})`; + }); + +const structurefile = readFileSync(structureFilePath, "utf-8"); +const schemablock = /.*?<\/Collapse>/m; + +console.log( + structurefile.replace( + schemablock, + ` +${valid.join("\n")} +`, + ), +);