introduce options to choose a bundle strategy

Pick from 'none', 'keycloakify' or 'mvn', default to 'mvn'. 'none' will
not create a jar, 'keycloakify' will create a jar file using only tools
available to native nodejs, no additional  system library required.
Choosing 'mvn' will behave as before, starting maven in a subprocess.

The bundler can be chosen in `package.json` or via `KEYCLOAKIFY_BUNDLER`
env var.

This commit also adds `KEYCLOAKIFY_GROUP_ID` and
`KEYCLOAKIFY_ARTIFACT_ID` env vars, which will be used to
define group id and artifact id in pom.xml and pom.properties, if given.
This commit is contained in:
Waldemar Reusch
2023-02-03 14:28:06 +01:00
parent 2b87c35058
commit f4a547df11
3 changed files with 44 additions and 17 deletions

View File

@ -4,6 +4,8 @@ import type { Equals } from "tsafe";
import { id } from "tsafe/id"; import { id } from "tsafe/id";
import { parse as urlParse } from "url"; import { parse as urlParse } from "url";
const BUNDLERS = ["mvn", "keycloakify", "none"] as const;
type Bundler = typeof BUNDLERS[number];
type ParsedPackageJson = { type ParsedPackageJson = {
name: string; name: string;
version: string; version: string;
@ -12,6 +14,9 @@ type ParsedPackageJson = {
extraPages?: string[]; extraPages?: string[];
extraThemeProperties?: string[]; extraThemeProperties?: string[];
areAppAndKeycloakServerSharingSameDomain?: boolean; areAppAndKeycloakServerSharingSameDomain?: boolean;
artifactId?: string;
groupId?: string;
bundler?: Bundler;
}; };
}; };
@ -23,7 +28,10 @@ const zParsedPackageJson = z.object({
.object({ .object({
"extraPages": z.array(z.string()).optional(), "extraPages": z.array(z.string()).optional(),
"extraThemeProperties": z.array(z.string()).optional(), "extraThemeProperties": z.array(z.string()).optional(),
"areAppAndKeycloakServerSharingSameDomain": z.boolean().optional() "areAppAndKeycloakServerSharingSameDomain": z.boolean().optional(),
"artifactId": z.string().optional(),
"groupId": z.string().optional(),
"bundler": z.enum(BUNDLERS).optional()
}) })
.optional() .optional()
}); });
@ -40,8 +48,9 @@ export namespace BuildOptions {
themeName: string; themeName: string;
extraPages?: string[]; extraPages?: string[];
extraThemeProperties?: string[]; extraThemeProperties?: string[];
//NOTE: Only for the pom.xml file, questionable utility...
groupId: string; groupId: string;
artifactId?: string;
bundler?: Bundler;
}; };
export type Standalone = Common & { export type Standalone = Common & {
@ -108,7 +117,7 @@ export function readBuildOptions(params: {
const common: BuildOptions.Common = (() => { const common: BuildOptions.Common = (() => {
const { name, keycloakify = {}, version, homepage } = parsedPackageJson; const { name, keycloakify = {}, version, homepage } = parsedPackageJson;
const { extraPages, extraThemeProperties } = keycloakify ?? {}; const { extraPages, extraThemeProperties, groupId, artifactId, bundler } = keycloakify ?? {};
const themeName = name const themeName = name
.replace(/^@(.*)/, "$1") .replace(/^@(.*)/, "$1")
@ -117,10 +126,14 @@ export function readBuildOptions(params: {
return { return {
themeName, themeName,
"bundler": (process.env.KEYCLOAKIFY_BUNDLER ?? bundler) as Bundler | undefined,
"artifactId": process.env.KEYCLOAKIFY_ARTIFACT_ID ?? artifactId,
"groupId": (() => { "groupId": (() => {
const fallbackGroupId = `${themeName}.keycloak`; const fallbackGroupId = `${themeName}.keycloak`;
return ( return (
process.env.KEYCLOAKIFY_GROUP_ID ??
groupId ??
(!homepage (!homepage
? fallbackGroupId ? fallbackGroupId
: urlParse(homepage) : urlParse(homepage)
@ -130,7 +143,7 @@ export function readBuildOptions(params: {
.join(".") ?? fallbackGroupId) + ".keycloak" .join(".") ?? fallbackGroupId) + ".keycloak"
); );
})(), })(),
"version": version, "version": process.env.KEYCLOAKFIY_VERSION ?? version,
extraPages, extraPages,
extraThemeProperties, extraThemeProperties,
isSilent isSilent

View File

@ -7,6 +7,8 @@ import type { BuildOptions } from "./BuildOptions";
export type BuildOptionsLike = { export type BuildOptionsLike = {
themeName: string; themeName: string;
groupId: string; groupId: string;
artifactId?: string;
version: string;
}; };
{ {
@ -16,7 +18,6 @@ export type BuildOptionsLike = {
} }
export function generateJavaStackFiles(params: { export function generateJavaStackFiles(params: {
version: string;
keycloakThemeBuildingDirPath: string; keycloakThemeBuildingDirPath: string;
doBundlesEmailTemplate: boolean; doBundlesEmailTemplate: boolean;
buildOptions: BuildOptionsLike; buildOptions: BuildOptionsLike;
@ -24,18 +25,17 @@ export function generateJavaStackFiles(params: {
jarFilePath: string; jarFilePath: string;
} { } {
const { const {
version, buildOptions: { groupId, themeName, version, artifactId },
buildOptions: { groupId, themeName },
keycloakThemeBuildingDirPath, keycloakThemeBuildingDirPath,
doBundlesEmailTemplate doBundlesEmailTemplate
} = params; } = params;
const finalArtifactId = artifactId ?? `${themeName}-keycloak-theme`;
{ {
const { pomFileCode } = (function generatePomFileCode(): { const { pomFileCode } = (function generatePomFileCode(): {
pomFileCode: string; pomFileCode: string;
} { } {
const artefactId = `${themeName}-keycloak-theme`;
const pomFileCode = [ const pomFileCode = [
`<?xml version="1.0"?>`, `<?xml version="1.0"?>`,
`<project xmlns="http://maven.apache.org/POM/4.0.0"`, `<project xmlns="http://maven.apache.org/POM/4.0.0"`,
@ -43,9 +43,9 @@ export function generateJavaStackFiles(params: {
` xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">`, ` xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">`,
` <modelVersion>4.0.0</modelVersion>`, ` <modelVersion>4.0.0</modelVersion>`,
` <groupId>${groupId}</groupId>`, ` <groupId>${groupId}</groupId>`,
` <artifactId>${artefactId}</artifactId>`, ` <artifactId>${finalArtifactId}</artifactId>`,
` <version>${version}</version>`, ` <version>${version}</version>`,
` <name>${artefactId}</name>`, ` <name>${finalArtifactId}</name>`,
` <description />`, ` <description />`,
`</project>` `</project>`
].join("\n"); ].join("\n");
@ -84,6 +84,6 @@ export function generateJavaStackFiles(params: {
} }
return { return {
"jarFilePath": pathJoin(keycloakThemeBuildingDirPath, "target", `${themeName}-${version}.jar`) "jarFilePath": pathJoin(keycloakThemeBuildingDirPath, "target", `${finalArtifactId}-${version}.jar`)
}; };
} }

View File

@ -7,6 +7,7 @@ import * as fs from "fs";
import { readBuildOptions } from "./BuildOptions"; import { readBuildOptions } from "./BuildOptions";
import { getLogger } from "../tools/logger"; import { getLogger } from "../tools/logger";
import { getCliOptions } from "../tools/cliOptions"; import { getCliOptions } from "../tools/cliOptions";
import jar from "../tools/jar";
const reactProjectDirPath = process.cwd(); const reactProjectDirPath = process.cwd();
@ -45,17 +46,30 @@ export async function main() {
}); });
const { jarFilePath } = generateJavaStackFiles({ const { jarFilePath } = generateJavaStackFiles({
"version": buildOptions.version,
keycloakThemeBuildingDirPath, keycloakThemeBuildingDirPath,
doBundlesEmailTemplate, doBundlesEmailTemplate,
buildOptions buildOptions
}); });
if (buildOptions.bundler === "none") {
logger.log("😱 Skipping bundling step, there will be no jar");
} else if (buildOptions.bundler === "keycloakify") {
logger.log("🫶 Let keycloakify do its thang");
await jar({
"rootPath": keycloakThemeBuildingDirPath,
"version": buildOptions.version,
"groupId": buildOptions.groupId,
"artifactId": buildOptions.artifactId || `${buildOptions.themeName}-keycloak-theme`,
"targetPath": jarFilePath
});
} else {
logger.log("🫙 Run maven to deliver a jar");
child_process.execSync("mvn package", { child_process.execSync("mvn package", {
"cwd": keycloakThemeBuildingDirPath "cwd": keycloakThemeBuildingDirPath
}); });
}
//We want, however, to test in a container running the latest Keycloak version // We want, however, to test in a container running the latest Keycloak version
const containerKeycloakVersion = "20.0.1"; const containerKeycloakVersion = "20.0.1";
generateStartKeycloakTestingContainer({ generateStartKeycloakTestingContainer({