Repository navigation
fix(scan): make every discovered ecosystem facts-only under --dynamic-sbom-inference #1696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,9 +18,10 @@ import { | |
| DSI_SETUP_COMMAND, | ||
| REACH_CONTINUE_ON_INSTALL_ERRORS_FLAG, | ||
| } from './scripts/resolution-report-render.mts' | ||
| import { skipWithoutDotnetSdk } from './scripts/run.mts' | ||
| import { noDotnetSdkReason } from './scripts/run.mts' | ||
| import { SOCKET_JSON } from '../../constants.mts' | ||
| import { loadSocketConfig } from '../../utils/config.mts' | ||
| import { InputError } from '../../utils/errors.mts' | ||
| import { withTmpDir } from '../../utils/fs.mts' | ||
| import { | ||
| readOrDefaultSocketJson, | ||
|
|
@@ -44,7 +45,6 @@ export type RecursiveManifestOutcomeStatus = | |
| | 'generated' | ||
| | 'skippedCovered' | ||
| | 'skippedDisabled' | ||
| | 'skippedNoSdk' | ||
|
|
||
| export type RecursiveManifestOutcome = BuildRoot & { | ||
| ecosystem: BuildTool | ||
|
|
@@ -212,13 +212,20 @@ async function runEcosystemCandidates({ | |
| outcomes.push({ ...root, ecosystem, status: 'skippedDisabled' }) | ||
| continue | ||
| } | ||
| if ( | ||
| ecosystem === 'dotnet' && | ||
| const socketJson = displayPath(path.join(dir, SOCKET_JSON)) | ||
| if (ecosystem === 'dotnet') { | ||
| // eslint-disable-next-line no-await-in-loop | ||
| (await skipWithoutDotnetSdk(dirConfig.bin, dir)) | ||
| ) { | ||
| outcomes.push({ ...root, ecosystem, status: 'skippedNoSdk' }) | ||
| continue | ||
| const reason = await noDotnetSdkReason(dirConfig.bin, dir) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because this check runs per root inside the build loop, a later .NET root whose |
||
| if (reason !== undefined) { | ||
| throw new InputError( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| [ | ||
| `No .NET SDK runs for ${displayPath(buildRootPath(root))} (${reason}), so its Socket facts cannot be generated.`, | ||
| '', | ||
| `- Install the .NET SDK, or point defaults.manifest.dotnet.bin in ${socketJson} at one (\`${DSI_SETUP_COMMAND}\` walks you through it).`, | ||
| `- Or leave it out with --exclude-paths, or with defaults.manifest.dotnet.disabled in ${socketJson}.`, | ||
| ].join('\n'), | ||
| ) | ||
| } | ||
| } | ||
| // eslint-disable-next-line no-await-in-loop | ||
| const result = await buildUncoveredRoot({ | ||
|
|
@@ -240,7 +247,7 @@ async function runEcosystemCandidates({ | |
| : undefined, | ||
| flags: optionFlags, | ||
| setupCommand: DSI_SETUP_COMMAND, | ||
| socketJson: displayPath(path.join(dir, SOCKET_JSON)), | ||
| socketJson, | ||
| }, | ||
| root, | ||
| sidecarAcc, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,16 +18,13 @@ vi.mock('./run-manifest-facts.mts', () => ({ | |
| vi.mock('./scripts/run.mts', async importOriginal => ({ | ||
| ...(await importOriginal<typeof import('./scripts/run.mts')>()), | ||
| listDotnetEntryProjects: vi.fn(async () => undefined), | ||
| skipWithoutDotnetSdk: vi.fn(async () => false), | ||
| noDotnetSdkReason: vi.fn(async () => undefined), | ||
| })) | ||
|
|
||
| import { buildRootPath } from './discover-manifest-roots.mts' | ||
| import { generateRecursiveManifests } from './generate-recursive-manifests.mts' | ||
| import { runManifestFacts } from './run-manifest-facts.mts' | ||
| import { | ||
| listDotnetEntryProjects, | ||
| skipWithoutDotnetSdk, | ||
| } from './scripts/run.mts' | ||
| import { listDotnetEntryProjects, noDotnetSdkReason } from './scripts/run.mts' | ||
| import { testPath } from '../../../test/utils.mts' | ||
| import { | ||
| readOrDefaultSocketJson, | ||
|
|
@@ -527,28 +524,21 @@ describe('generateRecursiveManifests', () => { | |
| }) | ||
| }) | ||
|
|
||
| it('skips .NET builds, without failing, where no .NET SDK runs', async () => { | ||
| const dir = await fs.mkdtemp(path.join(tmpdir(), 'dsi-no-sdk-')) | ||
| it('fails before building anything when no .NET SDK runs for a .NET build root', async () => { | ||
| const dir = await fs.mkdtemp(path.join(tmpdir(), 'dsi-require-sdk-')) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [agent] Not changing this here: as you say it's only worth it for the whole file, and the rest of the file is outside this PR. |
||
| try { | ||
| await fs.writeFile(path.join(dir, 'pom.xml'), '<project/>') | ||
| await fs.mkdir(path.join(dir, 'samples')) | ||
| await fs.writeFile(path.join(dir, 'samples', 'Stray.csproj'), '') | ||
| vi.mocked(skipWithoutDotnetSdk).mockResolvedValueOnce(true) | ||
| vi.mocked(runManifestFacts).mockImplementation(async ({ cwd }) => ({ | ||
| factsPath: path.join(cwd, 'pom.xml.socket.facts.json'), | ||
| projects: [], | ||
| })) | ||
| const outcomes = await generateRecursiveManifests({ | ||
| cwd: dir, | ||
| verbose: false, | ||
| }) | ||
| await fs.writeFile(path.join(dir, 'App.csproj'), '') | ||
| vi.mocked(noDotnetSdkReason).mockResolvedValueOnce('dotnet not found') | ||
| vi.mocked(runManifestFacts).mockClear() | ||
|
|
||
| expect( | ||
| outcomes.map(o => `${o.ecosystem}:${o.entryFile}:${o.status}`).sort(), | ||
| ).toEqual(['dotnet:Stray.csproj:skippedNoSdk', 'maven:pom.xml:generated']) | ||
| expect( | ||
| vi.mocked(runManifestFacts).mock.calls.map(([o]) => o.ecosystem), | ||
| ).toEqual(['maven']) | ||
| await expect( | ||
| generateRecursiveManifests({ | ||
| cwd: dir, | ||
| verbose: false, | ||
| }), | ||
| ).rejects.toThrow(/No .NET SDK runs for .* \(dotnet not found\)/) | ||
| expect(runManifestFacts).not.toHaveBeenCalled() | ||
| } finally { | ||
| await fs.rm(dir, { recursive: true, force: true }) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,7 @@ import { | |
| } from './discover-manifest-roots.mts' | ||
| import { enumerateWorkspaces } from './enumerate-workspaces.mts' | ||
| import { resolveEcosystemConfig } from './generate-recursive-manifests.mts' | ||
| import { skipWithoutDotnetSdk } from './scripts/run.mts' | ||
| import { noDotnetSdkReason } from './scripts/run.mts' | ||
| import { | ||
| setupDotnet, | ||
| setupGradle, | ||
|
|
@@ -241,8 +241,16 @@ export async function markWorkspaceCoverage({ | |
| if (skipReason) { | ||
| return { ok: true, data: undefined } | ||
| } | ||
| if (ecosystem === 'dotnet' && (await skipWithoutDotnetSdk(bin, dir))) { | ||
| return { ok: true, data: undefined } | ||
| if (ecosystem === 'dotnet') { | ||
| const reason = await noDotnetSdkReason(bin, dir) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The wizard checks for an SDK only on the path where nested roots are configured one by one. If the user answers no to "Configure other build roots found beneath this one, individually?" (line 853), it reports "Recursive setup complete." without checking any nested .NET root, and the next |
||
| if (reason !== undefined) { | ||
| return { | ||
| ok: false, | ||
| message: `No .NET SDK runs in ${path.relative(cwd, dir) || '.'} (${reason})`, | ||
| cause: | ||
| 'Install the .NET SDK, or point defaults.manifest.dotnet.bin at one; or leave the directory out with --exclude-paths.', | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This remedy differs from the one in |
||
| } | ||
| } | ||
| } | ||
|
|
||
| for (const root of roots) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This repeats the sidecar and facts-only flag assembly from
performReachabilityAnalysis, and the two copies already differ. Reach writes a sidecar wheneverfactsOnlyTypesis non-empty, but this writes one only when it has entries. Coana's fix commands don't require the sidecar today, so nothing breaks yet. Still, one helper returning the flags and the sidecar together would stop the two from drifting further.