From b78cfe4f1b8216af27ca611868b91ecac30c9b0a Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 15:54:01 +0200 Subject: [PATCH 01/13] Add support for single klib --- src/targets/__tests__/maven.test.ts | 38 +++++++++- src/targets/maven.ts | 111 +++++++++++++++++++++------- 2 files changed, 121 insertions(+), 28 deletions(-) diff --git a/src/targets/__tests__/maven.test.ts b/src/targets/__tests__/maven.test.ts index 9b051e66..00849a23 100644 --- a/src/targets/__tests__/maven.test.ts +++ b/src/targets/__tests__/maven.test.ts @@ -75,6 +75,7 @@ function getFullTargetConfig(): any { kmp: { rootDistDirRegex: '/distDir/', appleDistDirRegex: '/apple-distDir/', + klibDistDirRegex: '/klib-distDir/', }, }; } @@ -258,6 +259,7 @@ describe('Maven target configuration', () => { expect(typeof mvnTarget.config.android.fileReplacerStr).toBe('string'); expect(typeof mvnTarget.config.kmp.rootDistDirRegex).toBe('string'); expect(typeof mvnTarget.config.kmp.appleDistDirRegex).toBe('string'); + expect(typeof mvnTarget.config.kmp.klibDistDirRegex).toBe('string'); }); test('import GPG private key if one is present in the environment', async () => { @@ -294,6 +296,38 @@ describe('publish', () => { describe('transform KMP artifacts', () => { const tmpDirName = 'tmpDir'; + test('transform klib-only target side artifacts', async () => { + (withTempDir as jest.MockedFunction).mockImplementation( + async cb => { + return await cb(tmpDirName); + } + ); + + const mvnTarget = createMavenTarget(getFullTargetConfig()); + const files: Record = { + javadocFile: `${tmpDirName}-javadoc.jar`, + sourcesFile: `${tmpDirName}-sources.jar`, + klibFiles: [ + `${tmpDirName}.klib`, + ], + allFile: '', + metadataFile: ``, + moduleFile: `${tmpDirName}.module`, + }; + const { + sideArtifacts, + classifiers, + types, + } = mvnTarget.transformKmpSideArtifacts(false, false, true, files); + expect(sideArtifacts).toEqual( + `${files.javadocFile},${files.sourcesFile},${files.klibFiles},${files.moduleFile}` + ); + expect(classifiers).toEqual( + 'javadoc,sources,,' + ); + expect(types).toEqual('jar,jar,klib,module'); + }); + test('transform apple target side artifacts', async () => { (withTempDir as jest.MockedFunction).mockImplementation( async cb => { @@ -317,7 +351,7 @@ describe('transform KMP artifacts', () => { sideArtifacts, classifiers, types, - } = mvnTarget.transformKmpSideArtifacts(false, true, files); + } = mvnTarget.transformKmpSideArtifacts(false, true, false, files); expect(sideArtifacts).toEqual( `${files.javadocFile},${files.sourcesFile},${files.klibFiles},${files.metadataFile},${files.moduleFile}` ); @@ -348,7 +382,7 @@ describe('transform KMP artifacts', () => { sideArtifacts, classifiers, types, - } = mvnTarget.transformKmpSideArtifacts(true, false, files); + } = mvnTarget.transformKmpSideArtifacts(true, false, false, files); expect(sideArtifacts).toEqual( `${files.javadocFile},${files.sourcesFile},${files.allFile},${files.kotlinToolingMetadataFile},${files.moduleFile}` ); diff --git a/src/targets/maven.ts b/src/targets/maven.ts index 1edb502e..1108faea 100644 --- a/src/targets/maven.ts +++ b/src/targets/maven.ts @@ -64,6 +64,7 @@ type KotlinMultiplatformFields = { | { appleDistDirRegex: RegExp; rootDistDirRegex: RegExp; + klibDistDirRegex: RegExp; }; }; @@ -170,10 +171,17 @@ export class MavenTarget extends BaseTarget { ); } + if (!this.config.kmp.klibDistDirRegex) { + throw new ConfigurationError( + 'Required klib configuration for Kotlin Multiplatform is incorrect. See the documentation for more details.' + ); + } + return { kmp: { appleDistDirRegex: stringToRegexp(this.config.kmp.appleDistDirRegex), rootDistDirRegex: stringToRegexp(this.config.kmp.rootDistDirRegex), + klibDistDirRegex: stringToRegexp(this.config.kmp.klibDistDirRegex), }, }; } @@ -376,13 +384,16 @@ export class MavenTarget extends BaseTarget { const isAppleDistDir = this.mavenConfig.kmp.appleDistDirRegex.test( moduleName ); + const isKlibOnly = this.mavenConfig.kmp.klibDistDirRegex.test( + moduleName + ); const files = await this.getFilesForKmpMavenPomDist(distDir); const { targetFile, pomFile } = files; const { sideArtifacts, classifiers, types, - } = this.transformKmpSideArtifacts(isRootDistDir, isAppleDistDir, files); + } = this.transformKmpSideArtifacts(isRootDistDir, isAppleDistDir, isKlibOnly, files); await retrySpawnProcess(this.mavenConfig.mavenCliPath, [ 'gpg:sign-and-deploy-file', @@ -418,6 +429,7 @@ export class MavenTarget extends BaseTarget { * * @param isRootDistDir boolean indicating whether the distDir is the root distDir * @param isAppleDistDir boolean indicating whether the distDir is the Apple distDir + * @param isKlibOnly boolean indicating whether the distDir is the klib-only distDir * @param files an object containing the input files, as described above * @returns a Record with three fields: * - sideArtifacts: a comma-separated string listing the paths to all generated "side artifacts" @@ -427,6 +439,7 @@ export class MavenTarget extends BaseTarget { public transformKmpSideArtifacts( isRootDistDir: boolean, isAppleDistDir: boolean, + isKlibOnly: boolean, files: Record ): Record { const { @@ -447,25 +460,38 @@ export class MavenTarget extends BaseTarget { types += ',jar,json'; classifiers += ',all,kotlin-tooling-metadata'; } else if (isAppleDistDir) { - if (klibFiles) { - sideArtifacts += `,${klibFiles}`; - - // In order to upload cinterop klib files we need to extract the classifier from the file name. - // e.g: "sentry-kotlin-multiplatform-iosarm64-0.0.1-cinterop-Sentry.klib", - // the classifier is "cinterop-Sentry". - for (let i = 0; i < klibFiles.length; i++) { - const input = klibFiles[i]; - const start = input.indexOf('cinterop'); - const end = input.indexOf('.klib', start); - const classifier = input.substring(start, end); - - types += ',klib'; - classifiers += `,${classifier}`; - } + if (!Array.isArray(klibFiles)) { + throw new ConfigurationError( + 'klib files in apple distributions must be an array' + ); } + sideArtifacts += `,${klibFiles}`; + + // In order to upload cinterop klib files we need to extract the classifier from the file name. + // e.g: "sentry-kotlin-multiplatform-iosarm64-0.0.1-cinterop-Sentry.klib", + // the classifier is "cinterop-Sentry". + for (let i = 0; i < klibFiles.length; i++) { + const input = klibFiles[i]; + const start = input.indexOf('cinterop'); + const end = input.indexOf('.klib', start); + const classifier = input.substring(start, end); + + types += ',klib'; + classifiers += `,${classifier}`; + } + sideArtifacts += `,${metadataFile}`; types += ',jar'; classifiers += ',metadata'; + } else if (isKlibOnly) { + if (!Array.isArray(klibFiles) || klibFiles.length !== 1) { + throw new ConfigurationError( + 'klib files in klib-only distributions must be an array with exactly one element' + ); + } + sideArtifacts += `,${klibFiles}`; + types += ',klib'; + classifiers += ','; } // .module files should be available in every KMP artifact @@ -596,12 +622,12 @@ export class MavenTarget extends BaseTarget { const moduleName = parse(distDir).base; if (this.mavenConfig.kmp !== false) { - const isRootDistDir = this.mavenConfig.kmp.rootDistDirRegex.test( - moduleName - ); - const isAppleDistDir = this.mavenConfig.kmp.appleDistDirRegex.test( - moduleName - ); + const { klibDistDirRegex, appleDistDirRegex, rootDistDirRegex } = this.mavenConfig.kmp; + + const isRootDistDir = rootDistDirRegex.test(moduleName); + const isAppleDistDir = appleDistDirRegex.test(moduleName); + const isKlibOnly = klibDistDirRegex.test(moduleName); + if (isRootDistDir) { files['allFile'] = join(distDir, `${moduleName}-all.jar`); files['kotlinToolingMetadataFile'] = join( @@ -615,6 +641,35 @@ export class MavenTarget extends BaseTarget { .map(file => join(distDir, file)); files['klibFiles'] = cinteropFiles; + } else if (isKlibOnly) { + const dirEntries = await fsPromises.readdir(distDir); + const expectedFiles = [ + `${moduleName}-javadoc.jar`, + `${moduleName}.klib`, + `${moduleName}-sources.jar`, + `${moduleName}.module`, + POM_DEFAULT_FILENAME, + ]; + + const missingFiles = expectedFiles.filter(f => !dirEntries.includes(f)); + if (missingFiles.length > 0) { + throw new ConfigurationError( + `Missing expected file: ${missingFiles.join(', ')} in ${distDir}` + ); + } + + const extraFiles = dirEntries.filter(f => !expectedFiles.includes(f)); + if (extraFiles.length > 0) { + throw new ConfigurationError( + `Unexpected extra files in ${distDir}: ${extraFiles.join(', ')}` + ); + } + + this.logger.info( + `Found klib artifacts for ${moduleName}: [${expectedFiles.join(', ')}]` + ); + + files['klibFile'] = join(distDir, `${moduleName}.klib`); } } return files; @@ -649,13 +704,17 @@ export class MavenTarget extends BaseTarget { } } if (this.mavenConfig.kmp !== false) { - const isAppleDistDir = this.mavenConfig.kmp.appleDistDirRegex.test( - moduleName - ); - if (isAppleDistDir) { + const { klibDistDirRegex, appleDistDirRegex } = this.mavenConfig.kmp; + + if (klibDistDirRegex.test(moduleName)) { + return `${moduleName}.klib`; + } + + if (appleDistDirRegex.test(moduleName)) { return `${moduleName}.klib`; } } + return `${moduleName}.jar`; } From 597c400458a3276b894ceb49a3995ce25ec8a9fa Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:26:00 +0200 Subject: [PATCH 02/13] Update tests --- src/targets/__tests__/maven.test.ts | 77 ++++++++++++++++++++++++++++- src/targets/maven.ts | 2 +- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/targets/__tests__/maven.test.ts b/src/targets/__tests__/maven.test.ts index 00849a23..19e18c0b 100644 --- a/src/targets/__tests__/maven.test.ts +++ b/src/targets/__tests__/maven.test.ts @@ -13,6 +13,7 @@ import { import { retrySpawnProcess, sleep } from '../../utils/async'; import { withTempDir } from '../../utils/files'; import { importGPGKey } from '../../utils/gpg'; +import * as fs from 'fs'; jest.mock('../../utils/files'); jest.mock('../../utils/gpg'); @@ -73,10 +74,10 @@ function getFullTargetConfig(): any { fileReplacerStr: 'replacer', }, kmp: { - rootDistDirRegex: '/distDir/', + rootDistDirRegex: '/^(?!.*klib).*distDir/', // matches distDir but not klib-distDir appleDistDirRegex: '/apple-distDir/', klibDistDirRegex: '/klib-distDir/', - }, + }, }; } @@ -565,6 +566,78 @@ describe('upload', () => { expect(retrySpawnProcess).toHaveBeenCalledTimes(0); }); + + test('upload KMP klib-only distribution', async () => { + const klibDistDirName = 'sentry-klib-distDir-linuxx64-1.0.0'; // matches klib regex + const klibDistDir = `${tmpDirName}/${klibDistDirName}`; + + // simple mock to always use the same temporary directory, + // instead of creating a new one + (withTempDir as jest.MockedFunction).mockImplementation( + async cb => { + return await cb(tmpDirName); + } + ); + + // Override fs.promises.readdir for this test to return klib files + const readdirSpy = jest.spyOn(fs.promises, 'readdir').mockImplementation((dirPath: any) => { + if (dirPath.toString().includes(klibDistDirName)) { + return Promise.resolve([ + `${klibDistDirName}-javadoc.jar`, + `${klibDistDirName}.klib`, + `${klibDistDirName}-sources.jar`, + `${klibDistDirName}.module`, + POM_DEFAULT_FILENAME, + ] as any); + } + return Promise.resolve([] as any); + }); + + const mvnTarget = createMavenTarget(getFullTargetConfig()); + mvnTarget.getArtifactsForRevision = jest + .fn() + .mockResolvedValueOnce([{ filename: `${klibDistDirName}.zip` }]); + mvnTarget.artifactProvider.downloadArtifact = jest + .fn() + .mockResolvedValueOnce('artifact/download/path'); + mvnTarget.isBomFile = jest.fn().mockResolvedValueOnce(false); + mvnTarget.getPomFileInDist = jest.fn().mockResolvedValueOnce('pom-default.xml'); + mvnTarget.fileExists = jest.fn().mockResolvedValue(true); + + await mvnTarget.upload('r3v1s10n'); + + expect(retrySpawnProcess).toHaveBeenCalledTimes(1); + const callArgs = (retrySpawnProcess as jest.MockedFunction< + typeof retrySpawnProcess + >).mock.calls[0]; + + expect(callArgs).toHaveLength(2); + expect(callArgs[0]).toEqual(DEFAULT_OPTION_VALUE); + + const cmdArgs = callArgs[1] as string[]; + expect(cmdArgs).toHaveLength(11); + expect(cmdArgs[0]).toBe('gpg:sign-and-deploy-file'); + expect(cmdArgs[1]).toMatch(new RegExp(`-Dfile=${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0`)); + + expect(cmdArgs[2]).toBe( + `-Dfiles=${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0-javadoc.jar,${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0-sources.jar,${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0.klib,${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0.module` + ); + + expect(cmdArgs[3]).toBe(`-Dclassifiers=javadoc,sources,,`); + expect(cmdArgs[4]).toBe(`-Dtypes=jar,jar,klib,module`); + + expect(cmdArgs[5]).toMatch( + new RegExp(`-DpomFile=${klibDistDir}/pom-default\\.xml`) + ); + expect(cmdArgs[6]).toBe(`-DrepositoryId=${DEFAULT_OPTION_VALUE}`); + expect(cmdArgs[7]).toBe(`-Durl=${DEFAULT_OPTION_VALUE}`); + expect(cmdArgs[8]).toBe(`-Dgpg.passphrase=${DEFAULT_OPTION_VALUE}`); + expect(cmdArgs[9]).toBe('--settings'); + expect(cmdArgs[10]).toBe(DEFAULT_OPTION_VALUE); + + // Restore original mock + readdirSpy.mockRestore(); + }); }); describe('closeAndReleaseRepository', () => { diff --git a/src/targets/maven.ts b/src/targets/maven.ts index 1108faea..045d9e5b 100644 --- a/src/targets/maven.ts +++ b/src/targets/maven.ts @@ -669,7 +669,7 @@ export class MavenTarget extends BaseTarget { `Found klib artifacts for ${moduleName}: [${expectedFiles.join(', ')}]` ); - files['klibFile'] = join(distDir, `${moduleName}.klib`); + files['klibFiles'] = [join(distDir, `${moduleName}.klib`)]; } } return files; From 4debc9da4dc37b7341f84ccbf4fc8eeaa2901872 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:27:14 +0200 Subject: [PATCH 03/13] Clean up --- src/targets/__tests__/maven.test.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/targets/__tests__/maven.test.ts b/src/targets/__tests__/maven.test.ts index 19e18c0b..760bac07 100644 --- a/src/targets/__tests__/maven.test.ts +++ b/src/targets/__tests__/maven.test.ts @@ -542,8 +542,6 @@ describe('upload', () => { }); test('should skip upload for artifacts without any POM/BOM', async () => { - // simple mock to always use the same temporary directory, - // instead of creating a new one (withTempDir as jest.MockedFunction).mockImplementation( async cb => { return await cb(tmpDirName); @@ -571,8 +569,6 @@ describe('upload', () => { const klibDistDirName = 'sentry-klib-distDir-linuxx64-1.0.0'; // matches klib regex const klibDistDir = `${tmpDirName}/${klibDistDirName}`; - // simple mock to always use the same temporary directory, - // instead of creating a new one (withTempDir as jest.MockedFunction).mockImplementation( async cb => { return await cb(tmpDirName); From f506f9dd4b46d48d500295b0a873ebcb5eafca51 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:27:49 +0200 Subject: [PATCH 04/13] Clean up --- src/targets/__tests__/maven.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/targets/__tests__/maven.test.ts b/src/targets/__tests__/maven.test.ts index 760bac07..dc10fbf2 100644 --- a/src/targets/__tests__/maven.test.ts +++ b/src/targets/__tests__/maven.test.ts @@ -614,14 +614,11 @@ describe('upload', () => { expect(cmdArgs).toHaveLength(11); expect(cmdArgs[0]).toBe('gpg:sign-and-deploy-file'); expect(cmdArgs[1]).toMatch(new RegExp(`-Dfile=${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0`)); - expect(cmdArgs[2]).toBe( `-Dfiles=${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0-javadoc.jar,${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0-sources.jar,${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0.klib,${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0.module` ); - expect(cmdArgs[3]).toBe(`-Dclassifiers=javadoc,sources,,`); expect(cmdArgs[4]).toBe(`-Dtypes=jar,jar,klib,module`); - expect(cmdArgs[5]).toMatch( new RegExp(`-DpomFile=${klibDistDir}/pom-default\\.xml`) ); From 9033a38e3f5aa1a9d46226695ebee7cf421970e4 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:28:46 +0200 Subject: [PATCH 05/13] Clean up --- src/targets/maven.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/targets/maven.ts b/src/targets/maven.ts index 045d9e5b..4b588924 100644 --- a/src/targets/maven.ts +++ b/src/targets/maven.ts @@ -384,7 +384,7 @@ export class MavenTarget extends BaseTarget { const isAppleDistDir = this.mavenConfig.kmp.appleDistDirRegex.test( moduleName ); - const isKlibOnly = this.mavenConfig.kmp.klibDistDirRegex.test( + const isKlibDistDir = this.mavenConfig.kmp.klibDistDirRegex.test( moduleName ); const files = await this.getFilesForKmpMavenPomDist(distDir); @@ -393,7 +393,7 @@ export class MavenTarget extends BaseTarget { sideArtifacts, classifiers, types, - } = this.transformKmpSideArtifacts(isRootDistDir, isAppleDistDir, isKlibOnly, files); + } = this.transformKmpSideArtifacts(isRootDistDir, isAppleDistDir, isKlibDistDir, files); await retrySpawnProcess(this.mavenConfig.mavenCliPath, [ 'gpg:sign-and-deploy-file', @@ -429,7 +429,7 @@ export class MavenTarget extends BaseTarget { * * @param isRootDistDir boolean indicating whether the distDir is the root distDir * @param isAppleDistDir boolean indicating whether the distDir is the Apple distDir - * @param isKlibOnly boolean indicating whether the distDir is the klib-only distDir + * @param isKlibDistDir boolean indicating whether the distDir is the klib-only distDir * @param files an object containing the input files, as described above * @returns a Record with three fields: * - sideArtifacts: a comma-separated string listing the paths to all generated "side artifacts" @@ -439,7 +439,7 @@ export class MavenTarget extends BaseTarget { public transformKmpSideArtifacts( isRootDistDir: boolean, isAppleDistDir: boolean, - isKlibOnly: boolean, + isKlibDistDir: boolean, files: Record ): Record { const { @@ -483,7 +483,7 @@ export class MavenTarget extends BaseTarget { sideArtifacts += `,${metadataFile}`; types += ',jar'; classifiers += ',metadata'; - } else if (isKlibOnly) { + } else if (isKlibDistDir) { if (!Array.isArray(klibFiles) || klibFiles.length !== 1) { throw new ConfigurationError( 'klib files in klib-only distributions must be an array with exactly one element' @@ -626,7 +626,7 @@ export class MavenTarget extends BaseTarget { const isRootDistDir = rootDistDirRegex.test(moduleName); const isAppleDistDir = appleDistDirRegex.test(moduleName); - const isKlibOnly = klibDistDirRegex.test(moduleName); + const isKlibDistDir = klibDistDirRegex.test(moduleName); if (isRootDistDir) { files['allFile'] = join(distDir, `${moduleName}-all.jar`); @@ -641,7 +641,7 @@ export class MavenTarget extends BaseTarget { .map(file => join(distDir, file)); files['klibFiles'] = cinteropFiles; - } else if (isKlibOnly) { + } else if (isKlibDistDir) { const dirEntries = await fsPromises.readdir(distDir); const expectedFiles = [ `${moduleName}-javadoc.jar`, From 34554459aa7525e83c877477a0f2a719ab5b0470 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:30:39 +0200 Subject: [PATCH 06/13] Clean up --- src/targets/maven.ts | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/targets/maven.ts b/src/targets/maven.ts index 4b588924..6dd06213 100644 --- a/src/targets/maven.ts +++ b/src/targets/maven.ts @@ -642,33 +642,6 @@ export class MavenTarget extends BaseTarget { files['klibFiles'] = cinteropFiles; } else if (isKlibDistDir) { - const dirEntries = await fsPromises.readdir(distDir); - const expectedFiles = [ - `${moduleName}-javadoc.jar`, - `${moduleName}.klib`, - `${moduleName}-sources.jar`, - `${moduleName}.module`, - POM_DEFAULT_FILENAME, - ]; - - const missingFiles = expectedFiles.filter(f => !dirEntries.includes(f)); - if (missingFiles.length > 0) { - throw new ConfigurationError( - `Missing expected file: ${missingFiles.join(', ')} in ${distDir}` - ); - } - - const extraFiles = dirEntries.filter(f => !expectedFiles.includes(f)); - if (extraFiles.length > 0) { - throw new ConfigurationError( - `Unexpected extra files in ${distDir}: ${extraFiles.join(', ')}` - ); - } - - this.logger.info( - `Found klib artifacts for ${moduleName}: [${expectedFiles.join(', ')}]` - ); - files['klibFiles'] = [join(distDir, `${moduleName}.klib`)]; } } From 5bdee03300dbac6c976a82a5b04d47cc27013909 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:31:47 +0200 Subject: [PATCH 07/13] Clean up --- src/targets/maven.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/targets/maven.ts b/src/targets/maven.ts index 6dd06213..fcc2355d 100644 --- a/src/targets/maven.ts +++ b/src/targets/maven.ts @@ -679,11 +679,7 @@ export class MavenTarget extends BaseTarget { if (this.mavenConfig.kmp !== false) { const { klibDistDirRegex, appleDistDirRegex } = this.mavenConfig.kmp; - if (klibDistDirRegex.test(moduleName)) { - return `${moduleName}.klib`; - } - - if (appleDistDirRegex.test(moduleName)) { + if (klibDistDirRegex.test(moduleName) || appleDistDirRegex.test(moduleName)) { return `${moduleName}.klib`; } } From 2f5435f81660988b3809c7674ef22ed8f6df783e Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:32:54 +0200 Subject: [PATCH 08/13] Clean up --- src/targets/__tests__/maven.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/targets/__tests__/maven.test.ts b/src/targets/__tests__/maven.test.ts index dc10fbf2..482d9624 100644 --- a/src/targets/__tests__/maven.test.ts +++ b/src/targets/__tests__/maven.test.ts @@ -613,9 +613,9 @@ describe('upload', () => { const cmdArgs = callArgs[1] as string[]; expect(cmdArgs).toHaveLength(11); expect(cmdArgs[0]).toBe('gpg:sign-and-deploy-file'); - expect(cmdArgs[1]).toMatch(new RegExp(`-Dfile=${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0`)); + expect(cmdArgs[1]).toMatch(new RegExp(`-Dfile=${klibDistDir}/${klibDistDirName}`)); expect(cmdArgs[2]).toBe( - `-Dfiles=${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0-javadoc.jar,${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0-sources.jar,${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0.klib,${klibDistDir}/sentry-klib-distDir-linuxx64-1.0.0.module` + `-Dfiles=${klibDistDir}/${klibDistDirName}-javadoc.jar,${klibDistDir}/${klibDistDirName}-sources.jar,${klibDistDir}/${klibDistDirName}.klib,${klibDistDir}/${klibDistDirName}.module` ); expect(cmdArgs[3]).toBe(`-Dclassifiers=javadoc,sources,,`); expect(cmdArgs[4]).toBe(`-Dtypes=jar,jar,klib,module`); From 8a4b24af9b2993e38e97279b1a883999ddcb012e Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:35:29 +0200 Subject: [PATCH 09/13] Clean up --- src/targets/__tests__/maven.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/targets/__tests__/maven.test.ts b/src/targets/__tests__/maven.test.ts index 482d9624..f132b99b 100644 --- a/src/targets/__tests__/maven.test.ts +++ b/src/targets/__tests__/maven.test.ts @@ -74,7 +74,7 @@ function getFullTargetConfig(): any { fileReplacerStr: 'replacer', }, kmp: { - rootDistDirRegex: '/^(?!.*klib).*distDir/', // matches distDir but not klib-distDir + rootDistDirRegex: '/root-distDir/', appleDistDirRegex: '/apple-distDir/', klibDistDirRegex: '/klib-distDir/', }, From 2bad325035fef8e6ae5ebd0ea38f37ebfafbbfd3 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:36:13 +0200 Subject: [PATCH 10/13] Clean up --- src/targets/__tests__/maven.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/targets/__tests__/maven.test.ts b/src/targets/__tests__/maven.test.ts index f132b99b..9a63071e 100644 --- a/src/targets/__tests__/maven.test.ts +++ b/src/targets/__tests__/maven.test.ts @@ -297,7 +297,7 @@ describe('publish', () => { describe('transform KMP artifacts', () => { const tmpDirName = 'tmpDir'; - test('transform klib-only target side artifacts', async () => { + test('transform klib distDir target side artifacts', async () => { (withTempDir as jest.MockedFunction).mockImplementation( async cb => { return await cb(tmpDirName); From eefaddb7af0be845c90c4b89ed3921562b43dd8c Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:38:16 +0200 Subject: [PATCH 11/13] Update README --- README.md | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 4a1bad28..372adb9f 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,6 @@ Options: -h, --help Show help [boolean] ``` - ### Version naming conventions Craft currently supports [semantic versioning (semver)](https://semver.org)-like versions for the `NEW-VERSION` argument passed to its `prepare` and `publish` commands. This means, releases made with craft need to follow a general pattern as follows: @@ -146,7 +145,6 @@ Examples: #### Special Case: Python Post Releases - Python has the concept of post releases, which craft handles implicitly. A post release is indicated by a `-\d+` suffix to the semver version, for example: `1.0.0-1`. Given that we only consider certain identifiers as [pre-releases](#preview-releases-prerelease), post releases are considered stable releases. @@ -578,8 +576,8 @@ contains any one of [pre-release identifiers](#preview-releases-prerelease). **Environment** -| Name | Description | -| -------------- | ------------------------------------------------------------------ | +| Name | Description | +| -------------- | -------------------------------------------------------------------- | | `GITHUB_TOKEN` | Personal GitHub API token (see ) | **Configuration** @@ -621,10 +619,10 @@ The `npm` utility must be installed on the system. **Configuration** -| Option | Description | -| ------------------ | ------------------------------------------------------------------------------------------------------------------------------- | -| `access` | **optional**. Visibility for scoped packages: `restricted` (default) or `public` | -| `checkPackageName` | **optional**. If defined, check this package on the registry to get the current latest version to compare for the `latest` tag. The package(s) to be published will only be tagged with `latest` if the new version is greater than the checked package's version| +| Option | Description | +| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `access` | **optional**. Visibility for scoped packages: `restricted` (default) or `public` | +| `checkPackageName` | **optional**. If defined, check this package on the registry to get the current latest version to compare for the `latest` tag. The package(s) to be published will only be tagged with `latest` if the new version is greater than the checked package's version | **Example** @@ -669,8 +667,8 @@ like [getsentry/pypi] **Environment** -| Name | Description | -| -------------- | ------------------------------------------------------------------ | +| Name | Description | +| -------------- | -------------------------------------------------------------------- | | `GITHUB_TOKEN` | Personal GitHub API token (see ) | **Configuration** @@ -1164,6 +1162,7 @@ targets: kmp: rootDistDirRegex: /sentry-kotlin-multiplatform-[0-9]+.*$/ appleDistDirRegex: /sentry-kotlin-multiplatform-(macos|ios|tvos|watchos).*/ + klibDistDirRegex: /sentry-kotlin-multiplatform-(js|wasm-js).*/ ``` ### Symbol Collector (`symbol-collector`) @@ -1208,10 +1207,10 @@ For this target to work correctly, either `dart` must be installed on the system **Configuration** -| Option | Description | -| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `dartCliPath` | **optional** Path to the Dart CLI. It must be executable by the calling process. Defaults to `dart`. | -| `packages` | **optional** List of directories to be released, relative to the root. Useful when a single repository contains multiple packages. When skipped, root directory is assumed as the only package. | +| Option | Description | +| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `dartCliPath` | **optional** Path to the Dart CLI. It must be executable by the calling process. Defaults to `dart`. | +| `packages` | **optional** List of directories to be released, relative to the root. Useful when a single repository contains multiple packages. When skipped, root directory is assumed as the only package. | | `skipValidation` | **optional** Publishes the package without going through validation steps, such as analyzer & dependency checks.
This is useful in particular situations when package maintainers know why the validation fails and wish to side step the issue. For example, there may be analyzer issues due to not following the current (latest) dart SDK recommendation because the package needs to maintain the package compatibility with an old SDK version.
This option should be used with caution and only after testing and verifying the reported issue shouldn't affect the package. It is advisable to do an alpha pre-release to further reduce the chance of a potential negative impact. | **Example** @@ -1293,17 +1292,17 @@ The extracted directory is then published as a module. The `pwsh` executable [must be installed](https://github.com/powershell/powershell#get-powershell) on the system. -| Name | Description | Default | -| -------------------- | ---------------------------------------------------- | --------- | -| `POWERSHELL_API_KEY` | **required** PowerShell Gallery API key | | -| `POWERSHELL_BIN` | **optional** Path to PowerShell binary | `pwsh` | +| Name | Description | Default | +| -------------------- | --------------------------------------- | ------- | +| `POWERSHELL_API_KEY` | **required** PowerShell Gallery API key | | +| `POWERSHELL_BIN` | **optional** Path to PowerShell binary | `pwsh` | #### Configuration -| Option | Description | Default | -| -------------------- | ---------------------------------------------------- | --------- | -| `module` | **required** Module name. | | -| `repository` | **optional** Repository to publish the package to. | PSGallery | +| Option | Description | Default | +| ------------ | -------------------------------------------------- | --------- | +| `module` | **required** Module name. | | +| `repository` | **optional** Repository to publish the package to. | PSGallery | #### Example From e16dc2da95f62a9888653ab169710cfef6d31a45 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:39:22 +0200 Subject: [PATCH 12/13] Revert README --- README.md | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 372adb9f..4a1bad28 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,7 @@ Options: -h, --help Show help [boolean] ``` + ### Version naming conventions Craft currently supports [semantic versioning (semver)](https://semver.org)-like versions for the `NEW-VERSION` argument passed to its `prepare` and `publish` commands. This means, releases made with craft need to follow a general pattern as follows: @@ -145,6 +146,7 @@ Examples: #### Special Case: Python Post Releases + Python has the concept of post releases, which craft handles implicitly. A post release is indicated by a `-\d+` suffix to the semver version, for example: `1.0.0-1`. Given that we only consider certain identifiers as [pre-releases](#preview-releases-prerelease), post releases are considered stable releases. @@ -576,8 +578,8 @@ contains any one of [pre-release identifiers](#preview-releases-prerelease). **Environment** -| Name | Description | -| -------------- | -------------------------------------------------------------------- | +| Name | Description | +| -------------- | ------------------------------------------------------------------ | | `GITHUB_TOKEN` | Personal GitHub API token (see ) | **Configuration** @@ -619,10 +621,10 @@ The `npm` utility must be installed on the system. **Configuration** -| Option | Description | -| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `access` | **optional**. Visibility for scoped packages: `restricted` (default) or `public` | -| `checkPackageName` | **optional**. If defined, check this package on the registry to get the current latest version to compare for the `latest` tag. The package(s) to be published will only be tagged with `latest` if the new version is greater than the checked package's version | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------- | +| `access` | **optional**. Visibility for scoped packages: `restricted` (default) or `public` | +| `checkPackageName` | **optional**. If defined, check this package on the registry to get the current latest version to compare for the `latest` tag. The package(s) to be published will only be tagged with `latest` if the new version is greater than the checked package's version| **Example** @@ -667,8 +669,8 @@ like [getsentry/pypi] **Environment** -| Name | Description | -| -------------- | -------------------------------------------------------------------- | +| Name | Description | +| -------------- | ------------------------------------------------------------------ | | `GITHUB_TOKEN` | Personal GitHub API token (see ) | **Configuration** @@ -1162,7 +1164,6 @@ targets: kmp: rootDistDirRegex: /sentry-kotlin-multiplatform-[0-9]+.*$/ appleDistDirRegex: /sentry-kotlin-multiplatform-(macos|ios|tvos|watchos).*/ - klibDistDirRegex: /sentry-kotlin-multiplatform-(js|wasm-js).*/ ``` ### Symbol Collector (`symbol-collector`) @@ -1207,10 +1208,10 @@ For this target to work correctly, either `dart` must be installed on the system **Configuration** -| Option | Description | -| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `dartCliPath` | **optional** Path to the Dart CLI. It must be executable by the calling process. Defaults to `dart`. | -| `packages` | **optional** List of directories to be released, relative to the root. Useful when a single repository contains multiple packages. When skipped, root directory is assumed as the only package. | +| Option | Description | +| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `dartCliPath` | **optional** Path to the Dart CLI. It must be executable by the calling process. Defaults to `dart`. | +| `packages` | **optional** List of directories to be released, relative to the root. Useful when a single repository contains multiple packages. When skipped, root directory is assumed as the only package. | | `skipValidation` | **optional** Publishes the package without going through validation steps, such as analyzer & dependency checks.
This is useful in particular situations when package maintainers know why the validation fails and wish to side step the issue. For example, there may be analyzer issues due to not following the current (latest) dart SDK recommendation because the package needs to maintain the package compatibility with an old SDK version.
This option should be used with caution and only after testing and verifying the reported issue shouldn't affect the package. It is advisable to do an alpha pre-release to further reduce the chance of a potential negative impact. | **Example** @@ -1292,17 +1293,17 @@ The extracted directory is then published as a module. The `pwsh` executable [must be installed](https://github.com/powershell/powershell#get-powershell) on the system. -| Name | Description | Default | -| -------------------- | --------------------------------------- | ------- | -| `POWERSHELL_API_KEY` | **required** PowerShell Gallery API key | | -| `POWERSHELL_BIN` | **optional** Path to PowerShell binary | `pwsh` | +| Name | Description | Default | +| -------------------- | ---------------------------------------------------- | --------- | +| `POWERSHELL_API_KEY` | **required** PowerShell Gallery API key | | +| `POWERSHELL_BIN` | **optional** Path to PowerShell binary | `pwsh` | #### Configuration -| Option | Description | Default | -| ------------ | -------------------------------------------------- | --------- | -| `module` | **required** Module name. | | -| `repository` | **optional** Repository to publish the package to. | PSGallery | +| Option | Description | Default | +| -------------------- | ---------------------------------------------------- | --------- | +| `module` | **required** Module name. | | +| `repository` | **optional** Repository to publish the package to. | PSGallery | #### Example From a1e608c39d9f5199f9a02b5a00a5b72dfee8560f Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 21 Jul 2025 16:40:57 +0200 Subject: [PATCH 13/13] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4a1bad28..ef055b58 100644 --- a/README.md +++ b/README.md @@ -1164,6 +1164,7 @@ targets: kmp: rootDistDirRegex: /sentry-kotlin-multiplatform-[0-9]+.*$/ appleDistDirRegex: /sentry-kotlin-multiplatform-(macos|ios|tvos|watchos).*/ + klibDistDirRegex: /sentry-kotlin-multiplatform-(js|wasm-js).*/ ``` ### Symbol Collector (`symbol-collector`)