feat: Compute the kubectl download version map at build time

- Allows for bundled kubectl config to be changed without code changes

- Introduce @k8slens/kubectl-versions

  - Compile time fetching of versions

- Update @swc/* packages

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton committed 2023-04-14 14:42:00 -04:00
1 parent 2debe61359
commit 0bd7b1fe92
26 files changed
+348 -70

No files matched your search

+1
View File
@@ -0,0 +1 @@
build/*.mjs
+9
View File
@@ -0,0 +1,9 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"jsc": {
"parser": {
"syntax": "typescript"
},
"target": "es2022"
}
}
+8
View File
@@ -0,0 +1,8 @@
# @k8slens/kubectl-versions
This package contains a JSON array of entries of the format ["MAJOR.MINOR", "MAJOR.MINOR.PATCH"].
This object represents the current (at time of building each release of this package)
greatest PATCH version for each "MAJOR.MINOR" version of `kubectl`.
This is done at compile time so that we don't have to worry about being able to access this data on user machines.
Furthermore, this is dynamic in that the previous method was to update the table by hand.
@@ -0,0 +1,63 @@
import fetch from "node-fetch";
import { TypedRegEx } from "typed-regex";
import { XMLParser } from "fast-xml-parser";
import semver from "semver";
import { writeFile } from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
const { SemVer } = semver;
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const expectedResponseForm = TypedRegEx("v(?<version>\\d+\\.\\d+\\.\\d+)");
async function requestGreatestKubectlPatchVersion(majorMinor: string): Promise<string | undefined> {
const response = await fetch(`https://dl.k8s.io/release/stable-${majorMinor}.txt`);
if (response.status !== 200) {
try {
const parser = new XMLParser();
const errorBody = parser.parse(await response.text());
throw new Error(`failed to get stable version for ${majorMinor}: ${errorBody?.Error?.Message ?? response.statusText}`);
} catch {
throw new Error(`failed to get stable version for ${majorMinor}: ${response.statusText}`);
}
}
const body = await response.text();
const match = expectedResponseForm.captures(body);
if (!match) {
throw new Error(`failed to get stable version for ${majorMinor}: unexpected response shape. body="${body}"`);
}
return match.version;
}
async function requestAllVersions(): Promise<[string, string][]> {
const greatestVersion = await requestGreatestKubectlPatchVersion("1");
if (!greatestVersion) {
return [];
}
const greatestSemVer = new SemVer(greatestVersion);
const majorMinorRequests = new Array<string>(greatestSemVer.minor + 1)
.fill("")
.map((value, index) => `1.${index}`)
.map(async (majorMinor) => [majorMinor, await requestGreatestKubectlPatchVersion(majorMinor)] as const);
return (await Promise.all(majorMinorRequests))
.filter((entry): entry is [string, string] => !!entry[1]);
}
async function main() {
const versions = await requestAllVersions();
await writeFile(path.join(__dirname, "versions.json"), JSON.stringify(versions, null, 4));
}
await main();
@@ -0,0 +1,110 @@
[
[
"1.0",
"1.0.7"
],
[
"1.1",
"1.1.8"
],
[
"1.2",
"1.2.7"
],
[
"1.3",
"1.3.10"
],
[
"1.4",
"1.4.12"
],
[
"1.5",
"1.5.8"
],
[
"1.6",
"1.6.13"
],
[
"1.7",
"1.7.16"
],
[
"1.8",
"1.8.15"
],
[
"1.9",
"1.9.11"
],
[
"1.10",
"1.10.13"
],
[
"1.11",
"1.11.10"
],
[
"1.12",
"1.12.10"
],
[
"1.13",
"1.13.12"
],
[
"1.14",
"1.14.10"
],
[
"1.15",
"1.15.12"
],
[
"1.16",
"1.16.15"
],
[
"1.17",
"1.17.17"
],
[
"1.18",
"1.18.20"
],
[
"1.19",
"1.19.16"
],
[
"1.20",
"1.20.15"
],
[
"1.21",
"1.21.14"
],
[
"1.22",
"1.22.17"
],
[
"1.23",
"1.23.16"
],
[
"1.24",
"1.24.10"
],
[
"1.25",
"1.25.6"
],
[
"1.26",
"1.26.1"
]
]
+3
View File
@@ -0,0 +1,3 @@
import raw from "./build/versions.json";
export const kubectlVersions = raw as [string, string][];
+1
View File
@@ -0,0 +1 @@
module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact;
+40
View File
@@ -0,0 +1,40 @@
{
"name": "@k8slens/kubectl-versions",
"private": false,
"version": "6.5.0-alpha.1",
"description": "Package of kubectl versions at build time",
"files": [
"dist"
],
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": {
"name": "OpenLens Authors",
"email": "info@k8slens.dev"
},
"license": "MIT",
"homepage": "https://github.com/lensapp/lens",
"scripts": {
"precompute-versions": "swc ./build/compute-versions.ts -o ./build/compute-versions.mjs",
"compute-versions": "node ./build/compute-versions.mjs",
"prebuild": "npm run compute-versions",
"build": "webpack",
"dev": "webpack --mode=development --watch",
"test": "jest --coverage --runInBand"
},
"peerDependencies": {
"@ogre-tools/injectable": "^15.1.1"
},
"devDependencies": {
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.44",
"fast-xml-parser": "^4.1.2",
"semver": "^7.3.8",
"ts-node": "^10.9.1",
"typed-regex": "^0.0.8"
}
}
+3
View File
@@ -0,0 +1,3 @@
{
"extends": "@k8slens/typescript/config/base.json"
}
@@ -0,0 +1 @@
module.exports = require("@k8slens/webpack").configForNode;