Skip to content

Commit acd6d30

Browse files
committed
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 <path>.pom` to its `target/` ancestor and copy the pom to `<projectRoot>/socket.pom.xml` (or `<basename(--out)>`). 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.
1 parent 796ea6d commit acd6d30

2 files changed

Lines changed: 61 additions & 13 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "socket",
3-
"version": "1.1.93",
3+
"version": "1.1.94",
44
"description": "CLI for Socket.dev",
55
"homepage": "https://github.com/SocketDev/socket-cli",
66
"license": "MIT AND OFL-1.1",

src/commands/manifest/convert_sbt_to_maven.mts

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,28 @@
1+
import { promises as fs } from 'node:fs'
2+
import path from 'node:path'
3+
14
import { safeReadFile } from '@socketsecurity/registry/lib/fs'
25
import { logger } from '@socketsecurity/registry/lib/logger'
36
import { spawn } from '@socketsecurity/registry/lib/spawn'
47

58
import constants from '../../constants.mts'
69

10+
// Walk up from a pom path to find a `target` directory ancestor and return
11+
// its parent (the project root). Returns undefined if no `target` ancestor
12+
// is found, which means we cannot safely lift the file out of the ignored
13+
// build dir.
14+
function findProjectRootAboveTarget(pomPath: string): string | undefined {
15+
let dir = path.dirname(pomPath)
16+
const { root } = path.parse(dir)
17+
while (dir !== root) {
18+
if (path.basename(dir) === 'target') {
19+
return path.dirname(dir)
20+
}
21+
dir = path.dirname(dir)
22+
}
23+
return undefined
24+
}
25+
726
export async function convertSbtToMaven({
827
bin,
928
cwd,
@@ -92,18 +111,47 @@ export async function convertSbtToMaven({
92111
logger.info('Exiting now...')
93112
return
94113
} else {
95-
// if (verbose) {
96-
// logger.log(
97-
// `Moving manifest file from \`${loc.replace(/^\/home\/[^/]*?\//, '~/')}\` to \`${out}\``
98-
// )
99-
// } else {
100-
// logger.log('Moving output pom file')
101-
// }
102-
// TODO: Do we prefer fs-extra? Renaming can be gnarly on windows and fs-extra's version is better.
103-
// await renamep(loc, out)
104-
logger.success(`Generated ${poms.length} pom files`)
105-
poms.forEach(fn => logger.log('-', fn))
106-
logger.success(`OK`)
114+
// sbt writes poms inside each project's `target/` directory, which is
115+
// typically gitignored. Copy them out to a sibling of `target/` so
116+
// downstream SBOM/scan steps see them.
117+
const copied: string[] = []
118+
const outBasename = path.basename(out) || 'socket.pom.xml'
119+
for (const pomPath of poms) {
120+
let destPath: string
121+
if (poms.length === 1 && out !== outBasename) {
122+
// Honor the full `--out` path verbatim when exactly one pom was
123+
// produced and the user (or default) supplied a path, not just a
124+
// bare filename.
125+
destPath = path.resolve(cwd, out)
126+
} else {
127+
const projectRoot = findProjectRootAboveTarget(pomPath)
128+
if (!projectRoot) {
129+
logger.warn(
130+
`Could not locate \`target/\` ancestor for \`${pomPath}\`, leaving in place`,
131+
)
132+
continue
133+
}
134+
destPath = path.join(projectRoot, outBasename)
135+
}
136+
try {
137+
// eslint-disable-next-line no-await-in-loop
138+
await fs.mkdir(path.dirname(destPath), { recursive: true })
139+
// eslint-disable-next-line no-await-in-loop
140+
await fs.copyFile(pomPath, destPath)
141+
copied.push(destPath)
142+
} catch (e) {
143+
logger.warn(
144+
`Failed to copy \`${pomPath}\` to \`${destPath}\`: ${(e as Error).message}`,
145+
)
146+
}
147+
}
148+
logger.success(
149+
`Generated ${copied.length} pom file${copied.length === 1 ? '' : 's'}`,
150+
)
151+
logger.log('Reported exports:')
152+
for (const fn of copied) {
153+
logger.log('-', fn)
154+
}
107155
}
108156
} catch (e) {
109157
process.exitCode = 1

0 commit comments

Comments
 (0)