Remove inhouse bundler, we actually need Maven to build now

This commit is contained in:
garronej 2023-09-03 21:10:20 +02:00
parent 21d6d27435
commit 8c3e9ff192
5 changed files with 19 additions and 161 deletions

View File

@ -1,9 +1,5 @@
import { assert } from "tsafe/assert";
import { id } from "tsafe/id";
import { parse as urlParse } from "url"; import { parse as urlParse } from "url";
import { typeGuard } from "tsafe/typeGuard"; import { getParsedPackageJson } from "./parsedPackageJson";
import { symToStr } from "tsafe/symToStr";
import { bundlers, getParsedPackageJson, type Bundler } from "./parsedPackageJson";
import { join as pathJoin, sep as pathSep } from "path"; import { join as pathJoin, sep as pathSep } from "path";
import parseArgv from "minimist"; import parseArgv from "minimist";
@ -16,7 +12,7 @@ export type BuildOptions = {
extraThemeProperties: string[] | undefined; extraThemeProperties: string[] | undefined;
groupId: string; groupId: string;
artifactId: string; artifactId: string;
bundler: Bundler; doCreateJar: boolean;
loginThemeResourcesFromKeycloakVersion: string; loginThemeResourcesFromKeycloakVersion: string;
/** Directory of your built react project. Defaults to {cwd}/build */ /** Directory of your built react project. Defaults to {cwd}/build */
reactAppBuildDirPath: string; reactAppBuildDirPath: string;
@ -42,7 +38,14 @@ export function readBuildOptions(params: { projectDirPath: string; processArgv:
const { name, keycloakify = {}, version, homepage } = parsedPackageJson; const { name, keycloakify = {}, version, homepage } = parsedPackageJson;
const { extraThemeProperties, groupId, artifactId, bundler, loginThemeResourcesFromKeycloakVersion, extraThemeNames = [] } = keycloakify ?? {}; const {
extraThemeProperties,
groupId,
artifactId,
doCreateJar,
loginThemeResourcesFromKeycloakVersion,
extraThemeNames = []
} = keycloakify ?? {};
const themeName = const themeName =
keycloakify.themeName ?? keycloakify.themeName ??
@ -54,16 +57,7 @@ export function readBuildOptions(params: { projectDirPath: string; processArgv:
return { return {
themeName, themeName,
extraThemeNames, extraThemeNames,
"bundler": (() => { "doCreateJar": doCreateJar ?? true,
const { KEYCLOAKIFY_BUNDLER } = process.env;
assert(
typeGuard<Bundler | undefined>(KEYCLOAKIFY_BUNDLER, [undefined, ...id<readonly string[]>(bundlers)].includes(KEYCLOAKIFY_BUNDLER)),
`${symToStr({ KEYCLOAKIFY_BUNDLER })} should be one of ${bundlers.join(", ")}`
);
return KEYCLOAKIFY_BUNDLER ?? bundler ?? "keycloakify";
})(),
"artifactId": process.env.KEYCLOAKIFY_ARTIFACT_ID ?? artifactId ?? `${themeName}-keycloak-theme`, "artifactId": process.env.KEYCLOAKIFY_ARTIFACT_ID ?? artifactId ?? `${themeName}-keycloak-theme`,
"groupId": (() => { "groupId": (() => {
const fallbackGroupId = `${themeName}.keycloak`; const fallbackGroupId = `${themeName}.keycloak`;

View File

@ -6,9 +6,7 @@ import { generateStartKeycloakTestingContainer } from "./generateStartKeycloakTe
import * as fs from "fs"; import * as fs from "fs";
import { readBuildOptions } from "./BuildOptions"; import { readBuildOptions } from "./BuildOptions";
import { getLogger } from "../tools/logger"; import { getLogger } from "../tools/logger";
import jar from "../tools/jar";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import { Equals } from "tsafe";
import { getThemeSrcDirPath } from "../getSrcDirPath"; import { getThemeSrcDirPath } from "../getSrcDirPath";
import { getProjectRoot } from "../tools/getProjectRoot"; import { getProjectRoot } from "../tools/getProjectRoot";
import { objectKeys } from "tsafe/objectKeys"; import { objectKeys } from "tsafe/objectKeys";
@ -71,26 +69,12 @@ export async function main() {
buildOptions buildOptions
}); });
switch (buildOptions.bundler) { create_jar: {
case "none": if (!buildOptions.doCreateJar) {
logger.log("😱 Skipping bundling step, there will be no jar"); break create_jar;
break; }
case "keycloakify":
logger.log("🫶 Let keycloakify do its thang"); child_process.execSync("mvn package", { "cwd": buildOptions.keycloakifyBuildDirPath });
await jar({
"rootPath": buildOptions.keycloakifyBuildDirPath,
"version": buildOptions.themeVersion,
"groupId": buildOptions.groupId,
"artifactId": buildOptions.artifactId,
"targetPath": jarFilePath
});
break;
case "mvn":
logger.log("🫙 Run maven to deliver a jar");
child_process.execSync("mvn package", { "cwd": buildOptions.keycloakifyBuildDirPath });
break;
default:
assert<Equals<typeof buildOptions.bundler, never>>(false);
} }
// 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

View File

@ -4,8 +4,6 @@ import type { Equals } from "tsafe";
import { z } from "zod"; import { z } from "zod";
import { pathJoin } from "../tools/pathJoin"; import { pathJoin } from "../tools/pathJoin";
export const bundlers = ["mvn", "keycloakify", "none"] as const;
export type Bundler = (typeof bundlers)[number];
export type ParsedPackageJson = { export type ParsedPackageJson = {
name: string; name: string;
version?: string; version?: string;
@ -15,7 +13,7 @@ export type ParsedPackageJson = {
areAppAndKeycloakServerSharingSameDomain?: boolean; areAppAndKeycloakServerSharingSameDomain?: boolean;
artifactId?: string; artifactId?: string;
groupId?: string; groupId?: string;
bundler?: Bundler; doCreateJar?: boolean;
loginThemeResourcesFromKeycloakVersion?: string; loginThemeResourcesFromKeycloakVersion?: string;
reactAppBuildDirPath?: string; reactAppBuildDirPath?: string;
keycloakifyBuildDirPath?: string; keycloakifyBuildDirPath?: string;
@ -34,7 +32,7 @@ export const zParsedPackageJson = z.object({
"areAppAndKeycloakServerSharingSameDomain": z.boolean().optional(), "areAppAndKeycloakServerSharingSameDomain": z.boolean().optional(),
"artifactId": z.string().optional(), "artifactId": z.string().optional(),
"groupId": z.string().optional(), "groupId": z.string().optional(),
"bundler": z.enum(bundlers).optional(), "doCreateJar": z.boolean().optional(),
"loginThemeResourcesFromKeycloakVersion": z.string().optional(), "loginThemeResourcesFromKeycloakVersion": z.string().optional(),
"reactAppBuildDirPath": z.string().optional(), "reactAppBuildDirPath": z.string().optional(),
"keycloakifyBuildDirPath": z.string().optional(), "keycloakifyBuildDirPath": z.string().optional(),

View File

@ -1,99 +0,0 @@
import { dirname, relative, sep, join } from "path";
import { createWriteStream } from "fs";
import walk from "./walk";
import { ZipFile } from "yazl";
import { mkdir } from "fs/promises";
import trimIndent from "./trimIndent";
export type ZipEntry = { zipPath: string } & ({ fsPath: string } | { buffer: Buffer });
export type ZipEntryGenerator = AsyncGenerator<ZipEntry, void, unknown>;
type CommonJarArgs = {
groupId: string;
artifactId: string;
version: string;
};
export type JarStreamArgs = CommonJarArgs & {
asyncPathGeneratorFn(): ZipEntryGenerator;
};
export type JarArgs = CommonJarArgs & {
targetPath: string;
rootPath: string;
};
export async function jarStream({ groupId, artifactId, version, asyncPathGeneratorFn }: JarStreamArgs) {
const manifestPath = "META-INF/MANIFEST.MF";
const manifestData = Buffer.from(trimIndent`
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Keycloakify
Built-By: unknown
Build-Jdk: 19.0.0
`);
const pomPropsPath = `META-INF/maven/${groupId}/${artifactId}/pom.properties`;
const pomPropsData = Buffer.from(trimIndent`
# Generated by keycloakify
# ${new Date()}
artifactId=${artifactId}
groupId=${groupId}
version=${version}
`);
const zipFile = new ZipFile();
for await (const entry of asyncPathGeneratorFn()) {
if ("buffer" in entry) {
zipFile.addBuffer(entry.buffer, entry.zipPath);
} else if ("fsPath" in entry) {
if (entry.fsPath.endsWith(sep)) {
zipFile.addEmptyDirectory(entry.zipPath);
} else {
zipFile.addFile(entry.fsPath, entry.zipPath);
}
}
}
zipFile.addBuffer(manifestData, manifestPath);
zipFile.addBuffer(pomPropsData, pomPropsPath);
zipFile.end();
return zipFile;
}
/**
* Create a jar archive, using the resources found at `rootPath` (a directory) and write the
* archive to `targetPath` (a file). Use `groupId`, `artifactId` and `version` to define
* the contents of the pom.properties file which is going to be added to the archive.
* The root directory is expectedto have a conventional maven/gradle folder structure with a
* single `pom.xml` file at the root and a `src/main/resources` directory containing all
* application resources.
*/
export default async function jar({ groupId, artifactId, version, rootPath, targetPath }: JarArgs) {
await mkdir(dirname(targetPath), { recursive: true });
const asyncPathGeneratorFn = async function* (): ZipEntryGenerator {
const resourcesPath = join(rootPath, "src", "main", "resources");
for await (const fsPath of walk(resourcesPath)) {
const zipPath = relative(resourcesPath, fsPath).split(sep).join("/");
yield { fsPath, zipPath };
}
yield {
fsPath: join(rootPath, "pom.xml"),
zipPath: `META-INF/maven/${groupId}/${artifactId}/pom.xml`
};
};
const zipFile = await jarStream({ groupId, artifactId, version, asyncPathGeneratorFn });
await new Promise<void>(async (resolve, reject) => {
zipFile.outputStream
.pipe(createWriteStream(targetPath, { encoding: "binary" }))
.on("close", () => resolve())
.on("error", e => reject(e));
});
}

View File

@ -1,19 +0,0 @@
import { readdir } from "fs/promises";
import { resolve, sep } from "path";
/**
* Asynchronously and recursively walk a directory tree, yielding every file and directory
* found. Directory paths will _always_ end with a path separator.
*
* @param root the starting directory
* @returns AsyncGenerator
*/
export default async function* walk(root: string): AsyncGenerator<string, void, unknown> {
for (const entry of await readdir(root, { withFileTypes: true })) {
const absolutePath = resolve(root, entry.name);
if (entry.isDirectory()) {
yield absolutePath.endsWith(sep) ? absolutePath : absolutePath + sep;
yield* walk(absolutePath);
} else yield absolutePath.endsWith(sep) ? absolutePath.substring(0, absolutePath.length - 1) : absolutePath;
}
}