diff --git a/src/bin/keycloakify/keycloakify.ts b/src/bin/keycloakify/keycloakify.ts index 9599ad58..c92ec13f 100644 --- a/src/bin/keycloakify/keycloakify.ts +++ b/src/bin/keycloakify/keycloakify.ts @@ -58,7 +58,7 @@ export async function main() { case "keycloakify": logger.log("🫶 Let keycloakify do its thang"); await jar({ - "rootPath": pathJoin(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources"), + "rootPath": buildOptions.keycloakifyBuildDirPath, "version": buildOptions.themeVersion, "groupId": buildOptions.groupId, "artifactId": buildOptions.artifactId, diff --git a/src/bin/tools/jar.ts b/src/bin/tools/jar.ts index a87e9048..962f994e 100644 --- a/src/bin/tools/jar.ts +++ b/src/bin/tools/jar.ts @@ -1,4 +1,4 @@ -import { dirname, relative, sep } from "path"; +import { dirname, relative, sep, join } from "path"; import { createWriteStream } from "fs"; import walk from "./walk"; @@ -65,15 +65,23 @@ export async function jarStream({ groupId, artifactId, version, asyncPathGenerat * 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 { - for await (const fsPath of walk(rootPath)) { - const zipPath = relative(rootPath, fsPath).split(sep).join("/"); + 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 }); diff --git a/test/bin/jar.spec.ts b/test/bin/jar.spec.ts index 4499d664..65cf57f3 100644 --- a/test/bin/jar.spec.ts +++ b/test/bin/jar.spec.ts @@ -3,7 +3,7 @@ import { fromBuffer, Entry, ZipFile } from "yauzl"; import { it, describe, assert, afterAll } from "vitest"; import { Readable } from "stream"; import { tmpdir } from "os"; -import { mkdtemp, cp, mkdir, rm } from "fs/promises"; +import { mkdtemp, cp, mkdir, rm, writeFile } from "fs/promises"; import path from "path"; import { createReadStream } from "fs"; import walk from "keycloakify/bin/tools/walk"; @@ -98,12 +98,17 @@ describe("jar", () => { it("creates a jar from _real_ files without error", async () => { const tmp = await mkdtemp(path.join(tmpdir(), "kc-jar-test-")); - tmpDirs.push(tmp); - const rootPath = path.join(tmp, "src"); - const targetPath = path.join(tmp, "jar.jar"); - await mkdir(rootPath); - await cp(path.dirname(__dirname), rootPath, { recursive: true }); + tmpDirs.push(tmp); + + const rootPath = path.join(tmp, "root"); + const resourcesPath = path.join(tmp, "root", "src", "main", "resources"); + const targetPath = path.join(tmp, "jar.jar"); + + await mkdir(resourcesPath, { recursive: true }); + await writeFile(path.join(rootPath, "pom.xml"), "foo", "utf-8"); + + await cp(path.dirname(__dirname), resourcesPath, { recursive: true }); await jar({ ...coords, rootPath, targetPath }); @@ -114,11 +119,12 @@ describe("jar", () => { assert.isOk(entries.has("META-INF/MANIFEST.MF")); assert.isOk(entries.has("META-INF/maven/someGroupId/someArtifactId/pom.properties")); + assert.isOk(entries.has("META-INF/maven/someGroupId/someArtifactId/pom.xml")); - for await (const fsPath of walk(rootPath)) { + for await (const fsPath of walk(resourcesPath)) { if (!fsPath.endsWith(path.sep)) { - const rel = path.relative(rootPath, fsPath).replace(path.sep === "/" ? /\//g : /\\/g, "/"); - assert.isOk(zipPaths.includes(rel), `missing ${rel} (${rel}, ${zipPaths.join(", ")})`); + const rel = path.relative(resourcesPath, fsPath).replace(path.sep === "/" ? /\//g : /\\/g, "/"); + assert.isOk(zipPaths.includes(rel), `missing '${rel}' (${rel}, '${zipPaths.join("', '")}')`); } } });