diff --git a/CHANGELOG.md b/CHANGELOG.md index a0935f632..4061f5194 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 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 ### Changed 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/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 4846117b5..eeda44768 100644 --- a/src/commands/manifest/convert_sbt_to_maven.mts +++ b/src/commands/manifest/convert_sbt_to_maven.mts @@ -1,8 +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' +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 +// 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, @@ -92,18 +112,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) || '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}\`: ${getErrorCause(e)}`, + ) + } + } + 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 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(' ')