This commit is contained in:
Joseph Garrone 2024-12-17 10:44:24 +01:00
parent 70570faed6
commit 2b2bb20658
3 changed files with 56 additions and 58 deletions

View File

@ -5,9 +5,6 @@ import { readThisNpmPackageVersion } from "./tools/readThisNpmPackageVersion";
import * as child_process from "child_process"; import * as child_process from "child_process";
import { assertNoPnpmDlx } from "./tools/assertNoPnpmDlx"; import { assertNoPnpmDlx } from "./tools/assertNoPnpmDlx";
import { getBuildContext } from "./shared/buildContext"; import { getBuildContext } from "./shared/buildContext";
import { SemVer } from "./tools/SemVer";
import { assert, is } from "tsafe/assert";
import chalk from "chalk";
type CliCommandOptions = { type CliCommandOptions = {
projectDirPath: string | undefined; projectDirPath: string | undefined;
@ -137,47 +134,11 @@ program
handler: async ({ projectDirPath, keycloakVersion, port, realmJsonFilePath }) => { handler: async ({ projectDirPath, keycloakVersion, port, realmJsonFilePath }) => {
const { command } = await import("./start-keycloak"); const { command } = await import("./start-keycloak");
validate_keycloak_version: {
if (keycloakVersion === undefined) {
break validate_keycloak_version;
}
const isValidVersion = (() => {
if (typeof keycloakVersion === "number") {
return false;
}
try {
SemVer.parse(keycloakVersion);
} catch {
return false;
}
return;
})();
if (isValidVersion) {
break validate_keycloak_version;
}
console.log(
chalk.red(
[
`Invalid Keycloak version: ${keycloakVersion}`,
"It should be a valid semver version example: 26.0.4"
].join(" ")
)
);
process.exit(1);
}
assert(is<string | undefined>(keycloakVersion));
await command({ await command({
buildContext: getBuildContext({ projectDirPath }), buildContext: getBuildContext({ projectDirPath }),
cliCommandOptions: { cliCommandOptions: {
keycloakVersion, keycloakVersion:
keycloakVersion === undefined ? undefined : `${keycloakVersion}`,
port, port,
realmJsonFilePath realmJsonFilePath
} }

View File

@ -10,6 +10,7 @@ import { join as pathJoin, dirname as pathDirname } from "path";
import * as fs from "fs/promises"; import * as fs from "fs/promises";
import { existsAsync } from "../tools/fs.existsAsync"; import { existsAsync } from "../tools/fs.existsAsync";
import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion"; import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion";
import type { ReturnType } from "tsafe";
export type BuildContextLike = { export type BuildContextLike = {
fetchOptions: BuildContext["fetchOptions"]; fetchOptions: BuildContext["fetchOptions"];
@ -20,7 +21,10 @@ assert<BuildContext extends BuildContextLike ? true : false>;
export async function getSupportedDockerImageTags(params: { export async function getSupportedDockerImageTags(params: {
buildContext: BuildContextLike; buildContext: BuildContextLike;
}) { }): Promise<{
allSupportedTags: string[];
latestMajorTags: string[];
}> {
const { buildContext } = params; const { buildContext } = params;
{ {
@ -31,14 +35,14 @@ export async function getSupportedDockerImageTags(params: {
} }
} }
const tags: string[] = []; const tags_queryResponse: string[] = [];
await (async function callee(url: string) { await (async function callee(url: string) {
const r = await fetch(url, buildContext.fetchOptions); const r = await fetch(url, buildContext.fetchOptions);
await Promise.all([ await Promise.all([
(async () => { (async () => {
tags.push( tags_queryResponse.push(
...z ...z
.object({ .object({
tags: z.array(z.string()) tags: z.array(z.string())
@ -70,7 +74,9 @@ export async function getSupportedDockerImageTags(params: {
]); ]);
})("https://quay.io/v2/keycloak/keycloak/tags/list"); })("https://quay.io/v2/keycloak/keycloak/tags/list");
const arr = tags const supportedKeycloakMajorVersions = getSupportedKeycloakMajorVersions();
const allSupportedTags_withVersion = tags_queryResponse
.map(tag => ({ .map(tag => ({
tag, tag,
version: (() => { version: (() => {
@ -86,28 +92,35 @@ export async function getSupportedDockerImageTags(params: {
return undefined; return undefined;
} }
if (tag.split(".").length !== 3) {
return undefined;
}
if (!supportedKeycloakMajorVersions.includes(version.major)) {
return undefined;
}
return version; return version;
})() })()
})) }))
.map(({ tag, version }) => (version === undefined ? undefined : { tag, version })) .map(({ tag, version }) => (version === undefined ? undefined : { tag, version }))
.filter(exclude(undefined)); .filter(exclude(undefined))
.sort(({ version: a }, { version: b }) => SemVer.compare(b, a));
const versionByMajor: Record<number, SemVer | undefined> = {}; const latestTagByMajor: Record<number, SemVer | undefined> = {};
for (const { version } of arr) { for (const { version } of allSupportedTags_withVersion) {
const version_current = versionByMajor[version.major]; const version_current = latestTagByMajor[version.major];
if ( if (
version_current === undefined || version_current === undefined ||
SemVer.compare(version_current, version) === -1 SemVer.compare(version_current, version) === -1
) { ) {
versionByMajor[version.major] = version; latestTagByMajor[version.major] = version;
} }
} }
const supportedKeycloakMajorVersions = getSupportedKeycloakMajorVersions(); const latestMajorTags = Object.entries(latestTagByMajor)
const result = Object.entries(versionByMajor)
.sort(([a], [b]) => parseInt(b) - parseInt(a)) .sort(([a], [b]) => parseInt(b) - parseInt(a))
.map(([, version]) => version) .map(([, version]) => version)
.map(version => { .map(version => {
@ -121,16 +134,40 @@ export async function getSupportedDockerImageTags(params: {
}) })
.filter(exclude(undefined)); .filter(exclude(undefined));
const allSupportedTags = allSupportedTags_withVersion.map(({ tag }) => tag);
const result = {
latestMajorTags,
allSupportedTags
};
await setCachedValue({ cacheDirPath: buildContext.cacheDirPath, result }); await setCachedValue({ cacheDirPath: buildContext.cacheDirPath, result });
return result; return result;
} }
const { getCachedValue, setCachedValue } = (() => { const { getCachedValue, setCachedValue } = (() => {
type Result = ReturnType<typeof getSupportedDockerImageTags>;
const zResult = (() => {
type TargetType = Result;
const zTargetType = z.object({
allSupportedTags: z.array(z.string()),
latestMajorTags: z.array(z.string())
});
type InferredType = z.infer<typeof zTargetType>;
assert<Equals<TargetType, InferredType>>;
return id<z.ZodType<TargetType>>(zTargetType);
})();
type Cache = { type Cache = {
keycloakifyVersion: string; keycloakifyVersion: string;
time: number; time: number;
result: string[]; result: Result;
}; };
const zCache = (() => { const zCache = (() => {
@ -139,7 +176,7 @@ const { getCachedValue, setCachedValue } = (() => {
const zTargetType = z.object({ const zTargetType = z.object({
keycloakifyVersion: z.string(), keycloakifyVersion: z.string(),
time: z.number(), time: z.number(),
result: z.array(z.string()) result: zResult
}); });
type InferredType = z.infer<typeof zTargetType>; type InferredType = z.infer<typeof zTargetType>;

View File

@ -97,7 +97,7 @@ export async function command(params: {
const { cliCommandOptions, buildContext } = params; const { cliCommandOptions, buildContext } = params;
const availableTags = await getSupportedDockerImageTags({ const { allSupportedTags, latestMajorTags } = await getSupportedDockerImageTags({
buildContext buildContext
}); });
@ -105,7 +105,7 @@ export async function command(params: {
if (cliCommandOptions.keycloakVersion !== undefined) { if (cliCommandOptions.keycloakVersion !== undefined) {
const cliCommandOptions_keycloakVersion = cliCommandOptions.keycloakVersion; const cliCommandOptions_keycloakVersion = cliCommandOptions.keycloakVersion;
const tag = availableTags.find(tag => const tag = allSupportedTags.find(tag =>
tag.startsWith(cliCommandOptions_keycloakVersion) tag.startsWith(cliCommandOptions_keycloakVersion)
); );
@ -143,7 +143,7 @@ export async function command(params: {
); );
const { value: tag } = await cliSelect<string>({ const { value: tag } = await cliSelect<string>({
values: availableTags values: latestMajorTags
}).catch(() => { }).catch(() => {
process.exit(-1); process.exit(-1);
}); });