Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/commands/scan/handle-create-new-scan.mts
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,27 @@ export async function handleCreateNewScan({
const scanId = fullScanCResult.ok ? fullScanCResult.data?.id : undefined

if (reach && scanId && tier1ReachabilityScanId) {
await finalizeTier1Scan(tier1ReachabilityScanId, scanId)
// The finalize call is what transitions the tier1 reachability scan row
// out of INIT on depscan's side. Swallowing the failure here left tens
// of thousands of rows stuck in INIT. Capture the result, retry once on
// any failure, and log clearly if it still fails. We deliberately do
// NOT change the user-facing exit code: the full scan upload above
// already succeeded, and finalize is metadata-only.
let finalizeResult = await finalizeTier1Scan(
tier1ReachabilityScanId,
scanId,
)
if (!finalizeResult.ok) {
debugFn('warn', 'tier1 finalize failed, retrying once')
debugDir('inspect', { finalizeResult })
finalizeResult = await finalizeTier1Scan(tier1ReachabilityScanId, scanId)
}
if (!finalizeResult.ok) {
logger.error(
`Failed to finalize tier1 reachability scan (scan_id=${scanId}, tier1_reachability_scan_id=${tier1ReachabilityScanId}): ${finalizeResult.message}${finalizeResult.cause ? ` — ${finalizeResult.cause}` : ''}`,
)
debugDir('inspect', { finalizeResult })
}
}

if (report && fullScanCResult.ok) {
Expand Down
5 changes: 4 additions & 1 deletion src/commands/scan/handle-create-new-scan.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { HandleCreateNewScanConfig } from './handle-create-new-scan.mts'
const {
mockFetchCreateOrgFullScan,
mockFetchSupportedScanFileNames,
mockFinalizeTier1Scan,
mockFindSocketYmlSync,
mockGenerateAutoManifest,
mockGetPackageFilesForScan,
Expand All @@ -15,6 +16,7 @@ const {
} = vi.hoisted(() => ({
mockFetchCreateOrgFullScan: vi.fn(),
mockFetchSupportedScanFileNames: vi.fn(),
mockFinalizeTier1Scan: vi.fn(),
mockFindSocketYmlSync: vi.fn(),
mockGenerateAutoManifest: vi.fn(),
mockGetPackageFilesForScan: vi.fn(),
Expand All @@ -31,7 +33,7 @@ vi.mock('./fetch-supported-scan-file-names.mts', () => ({
}))

vi.mock('./finalize-tier1-scan.mts', () => ({
finalizeTier1Scan: vi.fn(),
finalizeTier1Scan: mockFinalizeTier1Scan,
}))

vi.mock('./handle-scan-report.mts', () => ({
Expand Down Expand Up @@ -126,6 +128,7 @@ describe('handleCreateNewScan excludePaths', () => {
data: { size: 1 },
ok: true,
})
mockFinalizeTier1Scan.mockResolvedValue({ data: undefined, ok: true })
mockFindSocketYmlSync.mockReturnValue({
data: { parsed: { projectIgnorePaths: ['fixtures/**'] } },
ok: true,
Expand Down
Loading