From acd6d30800b20bf80fc064498948b736dbd99fa5 Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Tue, 12 May 2026 14:08:39 +0200 Subject: [PATCH 1/6] fix(manifest): copy sbt-generated poms out of `target/` (REA-437) `socket manifest scala` runs `sbt makePom`, which writes poms into each subproject's `target/scala-X.Y/` dir. That path is gitignored in standard SBT projects, so downstream SBOM/scan steps that respect `.gitignore` never see the generated manifests. After sbt finishes, walk up from each reported `Wrote .pom` to its `target/` ancestor and copy the pom to `/socket.pom.xml` (or ``). Single-pom case with an explicit path `--out` still honors the exact path; stdout mode unchanged. Mirrors what `init.gradle` already does on the gradle path, just from Node since sbt has no direct analogue of `gradle --init-script`. Also tightens the success output to one list of destinations to match the gradle command's verbosity. --- package.json | 2 +- .../manifest/convert_sbt_to_maven.mts | 72 +++++++++++++++---- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 601fc7464..1e78f22ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socket", - "version": "1.1.93", + "version": "1.1.94", "description": "CLI for Socket.dev", "homepage": "https://github.com/SocketDev/socket-cli", "license": "MIT AND OFL-1.1", diff --git a/src/commands/manifest/convert_sbt_to_maven.mts b/src/commands/manifest/convert_sbt_to_maven.mts index 4846117b5..926db79a9 100644 --- a/src/commands/manifest/convert_sbt_to_maven.mts +++ b/src/commands/manifest/convert_sbt_to_maven.mts @@ -1,9 +1,28 @@ +import { promises as fs } from 'node:fs' +import path from 'node:path' + import { safeReadFile } from '@socketsecurity/registry/lib/fs' import { logger } from '@socketsecurity/registry/lib/logger' import { spawn } from '@socketsecurity/registry/lib/spawn' import constants from '../../constants.mts' +// Walk up from a pom path to find a `target` directory ancestor and return +// its parent (the project root). Returns undefined if no `target` ancestor +// is found, which means we cannot safely lift the file out of the ignored +// build dir. +function findProjectRootAboveTarget(pomPath: string): string | undefined { + let dir = path.dirname(pomPath) + const { root } = path.parse(dir) + while (dir !== root) { + if (path.basename(dir) === 'target') { + return path.dirname(dir) + } + dir = path.dirname(dir) + } + return undefined +} + export async function convertSbtToMaven({ bin, cwd, @@ -92,18 +111,47 @@ export async function convertSbtToMaven({ logger.info('Exiting now...') return } else { - // if (verbose) { - // logger.log( - // `Moving manifest file from \`${loc.replace(/^\/home\/[^/]*?\//, '~/')}\` to \`${out}\`` - // ) - // } else { - // logger.log('Moving output pom file') - // } - // TODO: Do we prefer fs-extra? Renaming can be gnarly on windows and fs-extra's version is better. - // await renamep(loc, out) - logger.success(`Generated ${poms.length} pom files`) - poms.forEach(fn => logger.log('-', fn)) - logger.success(`OK`) + // sbt writes poms inside each project's `target/` directory, which is + // typically gitignored. Copy them out to a sibling of `target/` so + // downstream SBOM/scan steps see them. + const copied: string[] = [] + const outBasename = path.basename(out) || 'socket.pom.xml' + for (const pomPath of poms) { + let destPath: string + if (poms.length === 1 && out !== outBasename) { + // Honor the full `--out` path verbatim when exactly one pom was + // produced and the user (or default) supplied a path, not just a + // bare filename. + destPath = path.resolve(cwd, out) + } else { + const projectRoot = findProjectRootAboveTarget(pomPath) + if (!projectRoot) { + logger.warn( + `Could not locate \`target/\` ancestor for \`${pomPath}\`, leaving in place`, + ) + continue + } + destPath = path.join(projectRoot, outBasename) + } + try { + // eslint-disable-next-line no-await-in-loop + await fs.mkdir(path.dirname(destPath), { recursive: true }) + // eslint-disable-next-line no-await-in-loop + await fs.copyFile(pomPath, destPath) + copied.push(destPath) + } catch (e) { + logger.warn( + `Failed to copy \`${pomPath}\` to \`${destPath}\`: ${(e as Error).message}`, + ) + } + } + logger.success( + `Generated ${copied.length} pom file${copied.length === 1 ? '' : 's'}`, + ) + logger.log('Reported exports:') + for (const fn of copied) { + logger.log('-', fn) + } } } catch (e) { process.exitCode = 1 From a4e83465d7fb61a53cb1cf3eba9a69e1de883420 Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Tue, 12 May 2026 14:17:36 +0200 Subject: [PATCH 2/6] fix(manifest): use getErrorCause helper in sbt copy catch Replaces the ad-hoc `(e as Error).message` cast in the pom-copy catch block with `getErrorCause(e)` from `utils/errors.mts`, matching the project's existing convention. Addresses cursor bugbot review on #1311. --- src/commands/manifest/convert_sbt_to_maven.mts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/commands/manifest/convert_sbt_to_maven.mts b/src/commands/manifest/convert_sbt_to_maven.mts index 926db79a9..170d40499 100644 --- a/src/commands/manifest/convert_sbt_to_maven.mts +++ b/src/commands/manifest/convert_sbt_to_maven.mts @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { spawn } from '@socketsecurity/registry/lib/spawn' import constants from '../../constants.mts' +import { getErrorCause } from '../../utils/errors.mts' // Walk up from a pom path to find a `target` directory ancestor and return // its parent (the project root). Returns undefined if no `target` ancestor @@ -141,7 +142,7 @@ export async function convertSbtToMaven({ copied.push(destPath) } catch (e) { logger.warn( - `Failed to copy \`${pomPath}\` to \`${destPath}\`: ${(e as Error).message}`, + `Failed to copy \`${pomPath}\` to \`${destPath}\`: ${getErrorCause(e)}`, ) } } From 8b757679e6a93464807f9524de3756c78f6fb21c Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Tue, 12 May 2026 22:01:42 +0200 Subject: [PATCH 3/6] docs(changelog): add 1.1.94 entry for sbt pom copy fix --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0935f632..9c52ca3a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [1.1.94](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.94) - 2026-05-12 + +### Fixed +- `socket manifest scala` now copies sbt-generated `.pom` files out of each subproject's `target/` directory to the project root, so downstream SBOM and scan steps that respect `.gitignore` can see the generated manifests. + ## [1.1.93](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.93) - 2026-05-08 ### Changed From c72f397960709de350442ae96a9f1b33b061af99 Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Wed, 13 May 2026 10:45:47 +0200 Subject: [PATCH 4/6] Fix typo in CHANGELOG for version 1.1.94 Signed-off-by: Jeppe Fredsgaard Blaabjerg --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c52ca3a9..be4cf46cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [1.1.94](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.94) - 2026-05-12 ### Fixed -- `socket manifest scala` now copies sbt-generated `.pom` files out of each subproject's `target/` directory to the project root, so downstream SBOM and scan steps that respect `.gitignore` can see the generated manifests. +- `socket manifest scala` now copies sbt-generated `.pom` files out of each subproject's `target/` directory to the project root, so downstream SBOM and scan steps that respect `.gitignore` can see the generated manifest files. ## [1.1.93](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.93) - 2026-05-08 From 0dc3d3c7cd5d3522b445c925767e80a06c01d99b Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Wed, 13 May 2026 10:54:32 +0200 Subject: [PATCH 5/6] ci: retrigger e2e checks From 560b147fe8cb1cfc3051fdb40f69773364dacd05 Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Wed, 13 May 2026 14:39:15 +0200 Subject: [PATCH 6/6] fix(manifest): default sbt pom output to pom.xml for scan discovery Match the gradle init script's convention by writing the sbt-generated manifest as pom.xml at the project root above target/, so Socket scan's **/pom.xml glob picks it up automatically. Help text documents --out as the escape hatch when a hand-authored pom.xml exists at the root. --- CHANGELOG.md | 2 +- src/commands/manifest/cmd-manifest-scala.mts | 8 +++++--- src/commands/manifest/cmd-manifest-scala.test.mts | 6 ++++-- src/commands/manifest/convert_sbt_to_maven.mts | 2 +- src/commands/manifest/generate_auto_manifest.mts | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be4cf46cd..4061f5194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [1.1.94](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.94) - 2026-05-12 ### Fixed -- `socket manifest scala` now copies sbt-generated `.pom` files out of each subproject's `target/` directory to the project root, so downstream SBOM and scan steps that respect `.gitignore` can see the generated manifest files. +- `socket manifest scala` now copies sbt-generated `.pom` files out of each subproject's `target/` directory to the project root as `pom.xml`, so Socket scan (which discovers `**/pom.xml` and respects `.gitignore`) picks them up automatically. Use `--out` to override the destination filename. ## [1.1.93](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.93) - 2026-05-08 diff --git a/src/commands/manifest/cmd-manifest-scala.mts b/src/commands/manifest/cmd-manifest-scala.mts index 22c5daf14..5a971519b 100644 --- a/src/commands/manifest/cmd-manifest-scala.mts +++ b/src/commands/manifest/cmd-manifest-scala.mts @@ -59,8 +59,10 @@ const config: CliCommandConfig = { There are some caveats with \`build.sbt\` to \`pom.xml\` conversion: - - the xml is exported as socket.pom.xml as to not confuse existing build tools - but it will first hit your /target/sbt folder (as a different name) + - the xml is exported as pom.xml at the project root so Socket scan picks + it up; sbt itself first writes it inside your /target/sbt folder + (as a different name). Use --out to override if you already have a + hand-authored pom.xml at the project root. - the pom.xml format (standard by Scala) does not support certain sbt features - \`excludeAll()\`, \`dependencyOverrides\`, \`force()\`, \`relativePath\` @@ -148,7 +150,7 @@ async function run( out = sockJson.defaults?.manifest?.sbt?.outfile logger.info(`Using default --out from ${SOCKET_JSON}:`, out) } else { - out = './socket.pom.xml' + out = './pom.xml' } } if (!sbtOpts) { diff --git a/src/commands/manifest/cmd-manifest-scala.test.mts b/src/commands/manifest/cmd-manifest-scala.test.mts index 359a0f4b6..40e59e382 100644 --- a/src/commands/manifest/cmd-manifest-scala.test.mts +++ b/src/commands/manifest/cmd-manifest-scala.test.mts @@ -35,8 +35,10 @@ describe('socket manifest scala', async () => { There are some caveats with \`build.sbt\` to \`pom.xml\` conversion: - - the xml is exported as socket.pom.xml as to not confuse existing build tools - but it will first hit your /target/sbt folder (as a different name) + - the xml is exported as pom.xml at the project root so Socket scan picks + it up; sbt itself first writes it inside your /target/sbt folder + (as a different name). Use --out to override if you already have a + hand-authored pom.xml at the project root. - the pom.xml format (standard by Scala) does not support certain sbt features - \`excludeAll()\`, \`dependencyOverrides\`, \`force()\`, \`relativePath\` diff --git a/src/commands/manifest/convert_sbt_to_maven.mts b/src/commands/manifest/convert_sbt_to_maven.mts index 170d40499..eeda44768 100644 --- a/src/commands/manifest/convert_sbt_to_maven.mts +++ b/src/commands/manifest/convert_sbt_to_maven.mts @@ -116,7 +116,7 @@ export async function convertSbtToMaven({ // typically gitignored. Copy them out to a sibling of `target/` so // downstream SBOM/scan steps see them. const copied: string[] = [] - const outBasename = path.basename(out) || 'socket.pom.xml' + const outBasename = path.basename(out) || 'pom.xml' for (const pomPath of poms) { let destPath: string if (poms.length === 1 && out !== outBasename) { diff --git a/src/commands/manifest/generate_auto_manifest.mts b/src/commands/manifest/generate_auto_manifest.mts index ecb2fe19f..e472cd0b3 100644 --- a/src/commands/manifest/generate_auto_manifest.mts +++ b/src/commands/manifest/generate_auto_manifest.mts @@ -34,7 +34,7 @@ export async function generateAutoManifest({ // Note: `sbt` is more likely to be resolved against PATH env bin: sockJson.defaults?.manifest?.sbt?.bin ?? 'sbt', cwd, - out: sockJson.defaults?.manifest?.sbt?.outfile ?? './socket.sbt.pom.xml', + out: sockJson.defaults?.manifest?.sbt?.outfile ?? './pom.xml', sbtOpts: sockJson.defaults?.manifest?.sbt?.sbtOpts ?.split(' ')