From 5af8d67b62f86b102dbaa3e5a69eba6378d01016 Mon Sep 17 00:00:00 2001 From: garronej Date: Mon, 4 Sep 2023 00:25:36 +0200 Subject: [PATCH] Refactor and update docker script --- .../bringInAccountV1.ts | 94 +++++++++++++ .../generateJavaStackFiles.ts | 124 +++++------------- .../generateStartKeycloakTestingContainer.ts | 36 +++-- src/bin/keycloakify/keycloakify.ts | 8 +- 4 files changed, 145 insertions(+), 117 deletions(-) create mode 100644 src/bin/keycloakify/generateJavaStackFiles/bringInAccountV1.ts diff --git a/src/bin/keycloakify/generateJavaStackFiles/bringInAccountV1.ts b/src/bin/keycloakify/generateJavaStackFiles/bringInAccountV1.ts new file mode 100644 index 00000000..6a6db6a9 --- /dev/null +++ b/src/bin/keycloakify/generateJavaStackFiles/bringInAccountV1.ts @@ -0,0 +1,94 @@ +import * as fs from "fs"; +import { join as pathJoin, dirname as pathDirname } from "path"; +import { assert } from "tsafe/assert"; +import { Reflect } from "tsafe/Reflect"; +import type { BuildOptions } from "../BuildOptions"; +import { resources_common, lastKeycloakVersionWithAccountV1 } from "../../constants"; +import { downloadBuiltinKeycloakTheme } from "../../download-builtin-keycloak-theme"; +import { transformCodebase } from "../../tools/transformCodebase"; + +export type BuildOptionsLike = { + keycloakifyBuildDirPath: string; + cacheDirPath: string; +}; + +{ + const buildOptions = Reflect(); + + assert(); +} + +export const accountV1 = "account-v1"; + +export async function bringInAccountV1(params: { buildOptions: BuildOptionsLike }) { + const { buildOptions } = params; + + const builtinKeycloakThemeTmpDirPath = pathJoin(buildOptions.keycloakifyBuildDirPath, "..", "tmp_yxdE2_builtin_keycloak_theme"); + + await downloadBuiltinKeycloakTheme({ + "destDirPath": builtinKeycloakThemeTmpDirPath, + "keycloakVersion": lastKeycloakVersionWithAccountV1, + buildOptions + }); + + const accountV1DirPath = pathJoin(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources", "theme", accountV1, "account"); + + transformCodebase({ + "srcDirPath": pathJoin(builtinKeycloakThemeTmpDirPath, "base", "account"), + "destDirPath": accountV1DirPath + }); + + const commonResourceFilePaths = [ + "node_modules/patternfly/dist/css/patternfly.min.css", + "node_modules/patternfly/dist/css/patternfly-additions.min.css" + ]; + + for (const relativeFilePath of commonResourceFilePaths.map(path => pathJoin(...path.split("/")))) { + const destFilePath = pathJoin(accountV1DirPath, "resources", resources_common, relativeFilePath); + + fs.mkdirSync(pathDirname(destFilePath), { "recursive": true }); + + fs.cpSync(pathJoin(builtinKeycloakThemeTmpDirPath, "keycloak", "common", "resources", relativeFilePath), destFilePath); + } + + const resourceFilePaths = ["css/account.css"]; + + for (const relativeFilePath of resourceFilePaths.map(path => pathJoin(...path.split("/")))) { + const destFilePath = pathJoin(accountV1DirPath, "resources", relativeFilePath); + + fs.mkdirSync(pathDirname(destFilePath), { "recursive": true }); + + fs.cpSync(pathJoin(builtinKeycloakThemeTmpDirPath, "keycloak", "account", "resources", relativeFilePath), destFilePath); + } + + fs.rmSync(builtinKeycloakThemeTmpDirPath, { "recursive": true }); + + fs.writeFileSync( + pathJoin(accountV1DirPath, "theme.properties"), + Buffer.from( + [ + "accountResourceProvider=org.keycloak.services.resources.account.AccountFormService", + "", + "locales=ar,ca,cs,da,de,en,es,fr,fi,hu,it,ja,lt,nl,no,pl,pt-BR,ru,sk,sv,tr,zh-CN", + "", + "styles=" + [...resourceFilePaths, ...commonResourceFilePaths.map(path => `resources_common/${path}`)].join(" "), + "", + "##### css classes for form buttons", + "# main class used for all buttons", + "kcButtonClass=btn", + "# classes defining priority of the button - primary or default (there is typically only one priority button for the form)", + "kcButtonPrimaryClass=btn-primary", + "kcButtonDefaultClass=btn-default", + "# classes defining size of the button", + "kcButtonLargeClass=btn-lg", + "" + ].join("\n"), + "utf8" + ) + ); + + transformCodebase({ + "srcDirPath": pathJoin(__dirname, "account-v1-java"), + "destDirPath": pathJoin(buildOptions.keycloakifyBuildDirPath, "src", "main", "java", "org", "keycloak") + }); +} diff --git a/src/bin/keycloakify/generateJavaStackFiles/generateJavaStackFiles.ts b/src/bin/keycloakify/generateJavaStackFiles/generateJavaStackFiles.ts index 727a0084..307e990d 100644 --- a/src/bin/keycloakify/generateJavaStackFiles/generateJavaStackFiles.ts +++ b/src/bin/keycloakify/generateJavaStackFiles/generateJavaStackFiles.ts @@ -3,9 +3,8 @@ import { join as pathJoin, dirname as pathDirname } from "path"; import { assert } from "tsafe/assert"; import { Reflect } from "tsafe/Reflect"; import type { BuildOptions } from "../BuildOptions"; -import { type ThemeType, resources_common, lastKeycloakVersionWithAccountV1 } from "../../constants"; -import { downloadBuiltinKeycloakTheme } from "../../download-builtin-keycloak-theme"; -import { transformCodebase } from "../../tools/transformCodebase"; +import { type ThemeType } from "../../constants"; +import { bringInAccountV1, accountV1 } from "./bringInAccountV1"; export type BuildOptionsLike = { themeName: string; @@ -14,6 +13,7 @@ export type BuildOptionsLike = { artifactId: string; themeVersion: string; cacheDirPath: string; + keycloakifyBuildDirPath: string; }; { @@ -23,13 +23,12 @@ export type BuildOptionsLike = { } export async function generateJavaStackFiles(params: { - keycloakThemeBuildingDirPath: string; implementedThemeTypes: Record; buildOptions: BuildOptionsLike; }): Promise<{ jarFilePath: string; }> { - const { keycloakThemeBuildingDirPath, implementedThemeTypes, buildOptions } = params; + const { implementedThemeTypes, buildOptions } = params; { const { pomFileCode } = (function generatePomFileCode(): { @@ -151,84 +150,15 @@ export async function generateJavaStackFiles(params: { return { pomFileCode }; })(); - fs.writeFileSync(pathJoin(keycloakThemeBuildingDirPath, "pom.xml"), Buffer.from(pomFileCode, "utf8")); + fs.writeFileSync(pathJoin(buildOptions.keycloakifyBuildDirPath, "pom.xml"), Buffer.from(pomFileCode, "utf8")); } - const accountV1 = "account-v1"; - - { - const builtinKeycloakThemeTmpDirPath = pathJoin(keycloakThemeBuildingDirPath, "..", "tmp_yxdE2_builtin_keycloak_theme"); - - await downloadBuiltinKeycloakTheme({ - "destDirPath": builtinKeycloakThemeTmpDirPath, - "keycloakVersion": lastKeycloakVersionWithAccountV1, - buildOptions - }); - - const accountV1DirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", accountV1, "account"); - - transformCodebase({ - "srcDirPath": pathJoin(builtinKeycloakThemeTmpDirPath, "base", "account"), - "destDirPath": accountV1DirPath - }); - - const commonResourceFilePaths = [ - "node_modules/patternfly/dist/css/patternfly.min.css", - "node_modules/patternfly/dist/css/patternfly-additions.min.css" - ]; - - for (const relativeFilePath of commonResourceFilePaths.map(path => pathJoin(...path.split("/")))) { - const destFilePath = pathJoin(accountV1DirPath, "resources", resources_common, relativeFilePath); - - fs.mkdirSync(pathDirname(destFilePath), { "recursive": true }); - - fs.cpSync(pathJoin(builtinKeycloakThemeTmpDirPath, "keycloak", "common", "resources", relativeFilePath), destFilePath); - } - - const resourceFilePaths = ["css/account.css"]; - - for (const relativeFilePath of resourceFilePaths.map(path => pathJoin(...path.split("/")))) { - const destFilePath = pathJoin(accountV1DirPath, "resources", relativeFilePath); - - fs.mkdirSync(pathDirname(destFilePath), { "recursive": true }); - - fs.cpSync(pathJoin(builtinKeycloakThemeTmpDirPath, "keycloak", "account", "resources", relativeFilePath), destFilePath); - } - - fs.rmSync(builtinKeycloakThemeTmpDirPath, { "recursive": true }); - - fs.writeFileSync( - pathJoin(accountV1DirPath, "theme.properties"), - Buffer.from( - [ - "accountResourceProvider=org.keycloak.services.resources.account.AccountFormService", - "", - "locales=ar,ca,cs,da,de,en,es,fr,fi,hu,it,ja,lt,nl,no,pl,pt-BR,ru,sk,sv,tr,zh-CN", - "", - "styles=" + [...resourceFilePaths, ...commonResourceFilePaths.map(path => `resources_common/${path}`)].join(" "), - "", - "##### css classes for form buttons", - "# main class used for all buttons", - "kcButtonClass=btn", - "# classes defining priority of the button - primary or default (there is typically only one priority button for the form)", - "kcButtonPrimaryClass=btn-primary", - "kcButtonDefaultClass=btn-default", - "# classes defining size of the button", - "kcButtonLargeClass=btn-lg", - "" - ].join("\n"), - "utf8" - ) - ); + if (implementedThemeTypes.account) { + await bringInAccountV1({ buildOptions }); } - transformCodebase({ - "srcDirPath": pathJoin(__dirname, "account-v1-java"), - "destDirPath": pathJoin(keycloakThemeBuildingDirPath, "src", "main", "java", "org", "keycloak") - }); - { - const themeManifestFilePath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "META-INF", "keycloak-themes.json"); + const themeManifestFilePath = pathJoin(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources", "META-INF", "keycloak-themes.json"); try { fs.mkdirSync(pathDirname(themeManifestFilePath)); @@ -240,16 +170,32 @@ export async function generateJavaStackFiles(params: { JSON.stringify( { "themes": [ - { - "name": accountV1, - "types": ["account"] - }, - ...[buildOptions.themeName, ...buildOptions.extraThemeNames].map(themeName => ({ - "name": themeName, - "types": Object.entries(implementedThemeTypes) - .filter(([, isImplemented]) => isImplemented) - .map(([themeType]) => themeType) - })) + ...(!implementedThemeTypes.account + ? [] + : [ + { + "name": accountV1, + "types": ["account"] + } + ]), + ...[buildOptions.themeName, ...buildOptions.extraThemeNames] + .map(themeName => [ + { + "name": themeName, + "types": Object.entries(implementedThemeTypes) + .filter(([, isImplemented]) => isImplemented) + .map(([themeType]) => themeType) + }, + ...(!implementedThemeTypes.account + ? [] + : [ + { + "name": `${themeName}_retrocompatible`, + "types": ["account"] + } + ]) + ]) + .flat() ] }, null, @@ -261,6 +207,6 @@ export async function generateJavaStackFiles(params: { } return { - "jarFilePath": pathJoin(keycloakThemeBuildingDirPath, "target", `${buildOptions.artifactId}-${buildOptions.themeVersion}.jar`) + "jarFilePath": pathJoin(buildOptions.keycloakifyBuildDirPath, "target", `${buildOptions.artifactId}-${buildOptions.themeVersion}.jar`) }; } diff --git a/src/bin/keycloakify/generateStartKeycloakTestingContainer.ts b/src/bin/keycloakify/generateStartKeycloakTestingContainer.ts index 76622466..8e0c7df2 100644 --- a/src/bin/keycloakify/generateStartKeycloakTestingContainer.ts +++ b/src/bin/keycloakify/generateStartKeycloakTestingContainer.ts @@ -5,8 +5,7 @@ import { Reflect } from "tsafe/Reflect"; import type { BuildOptions } from "./BuildOptions"; export type BuildOptionsLike = { - themeName: string; - extraThemeNames: string[]; + keycloakifyBuildDirPath: string; }; { @@ -20,39 +19,34 @@ generateStartKeycloakTestingContainer.basename = "start_keycloak_testing_contain const containerName = "keycloak-testing-container"; /** Files for being able to run a hot reload keycloak container */ -export function generateStartKeycloakTestingContainer(params: { - keycloakVersion: string; - keycloakThemeBuildingDirPath: string; - buildOptions: BuildOptionsLike; -}) { - const { - keycloakThemeBuildingDirPath, - keycloakVersion, - buildOptions: { themeName, extraThemeNames } - } = params; +export function generateStartKeycloakTestingContainer(params: { keycloakVersion: string; buildOptions: BuildOptionsLike }) { + const { keycloakVersion, buildOptions } = params; + + const themeRelativeDirPath = pathJoin("src", "main", "resources", "theme"); + const themeDirPath = pathJoin(buildOptions.keycloakifyBuildDirPath, themeRelativeDirPath); fs.writeFileSync( - pathJoin(keycloakThemeBuildingDirPath, generateStartKeycloakTestingContainer.basename), + pathJoin(buildOptions.keycloakifyBuildDirPath, generateStartKeycloakTestingContainer.basename), Buffer.from( [ "#!/usr/bin/env bash", "", `docker rm ${containerName} || true`, "", - `cd "${keycloakThemeBuildingDirPath.replace(/\\/g, "/")}"`, + `cd "${buildOptions.keycloakifyBuildDirPath}"`, "", "docker run \\", " -p 8080:8080 \\", ` --name ${containerName} \\`, " -e KEYCLOAK_ADMIN=admin \\", " -e KEYCLOAK_ADMIN_PASSWORD=admin \\", - ...[themeName, ...extraThemeNames].map( - themeName => - ` -v "${pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", themeName).replace( - /\\/g, - "/" - )}":"/opt/keycloak/themes/${themeName}":rw \\` - ), + ...fs + .readdirSync(themeDirPath) + .filter(name => fs.lstatSync(pathJoin(themeDirPath, name)).isDirectory()) + .map( + themeName => + ` -v "${pathJoin(".", themeRelativeDirPath, themeName).replace(/\\/g, "/")}":"/opt/keycloak/themes/${themeName}":rw \\` + ), ` -it quay.io/keycloak/keycloak:${keycloakVersion} \\`, ` start-dev --features=declarative-user-profile`, "" diff --git a/src/bin/keycloakify/keycloakify.ts b/src/bin/keycloakify/keycloakify.ts index bd141e6d..af05f9d0 100644 --- a/src/bin/keycloakify/keycloakify.ts +++ b/src/bin/keycloakify/keycloakify.ts @@ -45,7 +45,6 @@ export async function main() { } const { jarFilePath } = await generateJavaStackFiles({ - "keycloakThemeBuildingDirPath": buildOptions.keycloakifyBuildDirPath, "implementedThemeTypes": (() => { const implementedThemeTypes = { "login": false, @@ -65,11 +64,7 @@ export async function main() { buildOptions }); - create_jar: { - if (!buildOptions.doCreateJar) { - break create_jar; - } - + if (buildOptions.doCreateJar) { child_process.execSync("mvn package", { "cwd": buildOptions.keycloakifyBuildDirPath }); } @@ -77,7 +72,6 @@ export async function main() { const containerKeycloakVersion = "21.1.2"; generateStartKeycloakTestingContainer({ - keycloakThemeBuildingDirPath: buildOptions.keycloakifyBuildDirPath, "keycloakVersion": containerKeycloakVersion, buildOptions });