Skip to content

Commit

Permalink
Merge pull request #1274 from DataDog/dastrong/STAL-1577
Browse files Browse the repository at this point in the history
[STAL-1577] Improve SBOM/SARIF messaging
  • Loading branch information
dastrong authored Apr 4, 2024
2 parents 0bd7335 + 1218b55 commit 75a65dc
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 10 deletions.
17 changes: 14 additions & 3 deletions src/commands/sarif/__tests__/upload.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,10 @@ describe('execute', () => {
const cli = makeCli()
const context = createMockContext() as any
process.env = {DATADOG_API_KEY: 'PLACEHOLDER'}
const code = await cli.run(['sarif', 'upload', '--service', 'test-service', '--dry-run', ...paths], context)
const code = await cli.run(
['sarif', 'upload', '--service', 'test-service', '--env', 'ci', '--dry-run', ...paths],
context
)

return {context, code}
}
Expand All @@ -195,6 +198,7 @@ describe('execute', () => {
basePaths: ['src/commands/sarif/__tests__/fixtures/subfolder'],
concurrency: 20,
service: 'test-service',
env: 'ci',
})
})
test('multiple paths', async () => {
Expand All @@ -211,6 +215,7 @@ describe('execute', () => {
],
concurrency: 20,
service: 'test-service',
env: 'ci',
})
})

Expand All @@ -222,6 +227,7 @@ describe('execute', () => {
basePaths: [`${process.cwd()}/src/commands/sarif/__tests__/fixtures/subfolder`],
concurrency: 20,
service: 'test-service',
env: 'ci',
})
})

Expand All @@ -233,7 +239,9 @@ describe('execute', () => {
expect(output[0]).toContain('DRY-RUN MODE ENABLED. WILL NOT UPLOAD SARIF REPORT')
expect(output[1]).toContain('Starting upload with concurrency 20.')
expect(output[2]).toContain(`Will upload SARIF report file ${path}`)
expect(output[3]).toContain('service: test-service')
expect(output[3]).toContain('Only one upload per commit, env, service and tool')
expect(output[4]).toContain(`Preparing upload for`)
expect(output[4]).toContain(`env:ci service:test-service`)
})

test('not found file', async () => {
Expand All @@ -250,11 +258,14 @@ interface ExpectedOutput {
basePaths: string[]
concurrency: number
service: string
env: string
}

const checkConsoleOutput = (output: string[], expected: ExpectedOutput) => {
expect(output[0]).toContain('DRY-RUN MODE ENABLED. WILL NOT UPLOAD SARIF REPORT')
expect(output[1]).toContain(`Starting upload with concurrency ${expected.concurrency}.`)
expect(output[2]).toContain(`Will look for SARIF report files in ${expected.basePaths.join(', ')}`)
expect(output[3]).toContain(`service: ${expected.service}`)
expect(output[3]).toContain('Only one upload per commit, env, service and tool')
expect(output[4]).toContain(`Preparing upload for`)
expect(output[4]).toContain(`env:${expected.env} service:${expected.service}`)
}
5 changes: 4 additions & 1 deletion src/commands/sarif/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ export const renderUpload = (payload: Payload): string => `Uploading SARIF repor
export const renderCommandInfo = (
basePaths: string[],
service: string,
env: string,
sha: string,
concurrency: number,
dryRun: boolean,
noVerify: boolean
Expand All @@ -92,7 +94,8 @@ export const renderCommandInfo = (
} else {
fullStr += chalk.green(`Will look for SARIF report files in ${basePaths.join(', ')}\n`)
}
fullStr += chalk.green(`service: ${service}\n`)
fullStr += `Only one upload per commit, env, service and tool\n`
fullStr += `Preparing upload for sha:${sha} env:${env} service:${service}\n`

return fullStr
}
Expand Down
6 changes: 4 additions & 2 deletions src/commands/sarif/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {doWithMaxConcurrency} from '../../helpers/concurrency'
import {DatadogCiConfig} from '../../helpers/config'
import {SpanTags} from '../../helpers/interfaces'
import {retryRequest} from '../../helpers/retry'
import {getSpanTags, mandatoryGitFields} from '../../helpers/tags'
import {GIT_SHA, getSpanTags, mandatoryGitFields} from '../../helpers/tags'
import {buildPath} from '../../helpers/utils'
import * as validation from '../../helpers/validation'

Expand Down Expand Up @@ -138,8 +138,10 @@ export class UploadSarifReportCommand extends Command {
return 1
}

const sha = spanTags[GIT_SHA] || 'sha-not-found'
const env = this.config.env || 'env-not-set'
this.context.stdout.write(
renderCommandInfo(this.basePaths, this.service, this.maxConcurrency, this.dryRun, this.noVerify)
renderCommandInfo(this.basePaths, this.service, env, sha, this.maxConcurrency, this.dryRun, this.noVerify)
)
const upload = (p: Payload) => this.uploadSarifReport(api, p)

Expand Down
12 changes: 11 additions & 1 deletion src/commands/sbom/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,21 @@ export const renderMissingSpan = (errorMessage: string) => {
return fullStr
}

export const renderDuplicateUpload = (sha: string, env: string, service: string) => {
let fullStr = ''
fullStr += chalk.red(`${ICONS.WARNING} Duplicate SBOM upload detected\n`)
fullStr += chalk.red(`An analysis has already been processed for sha:${sha} env:${env} service:${service}\n`)
fullStr += chalk.red(`Push a new commit or specify a different env or service variable\n`)
fullStr += chalk.red(`Exiting with code 0\n`)

return fullStr
}

export const renderFailedUpload = (sbomReport: string, error: any) => {
const reportPath = `[${chalk.bold.dim(sbomReport)}]`

let fullStr = ''
fullStr += chalk.red(`${ICONS.FAILED} Failed upload SBOM file ${reportPath}: ${error.message}\n`)
fullStr += chalk.red(`${ICONS.FAILED} Failed upload SBOM file ${reportPath}: ${error.message}\n`)
if (error?.response?.status) {
fullStr += chalk.red(`API status code: ${error.response.status}\n`)
}
Expand Down
15 changes: 12 additions & 3 deletions src/commands/sbom/upload.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import fs from 'fs'
import process from 'process'

import type {AxiosPromise, AxiosResponse} from 'axios'

import Ajv from 'ajv'
import {AxiosPromise, AxiosResponse, isAxiosError} from 'axios'
import {Command, Option} from 'clipanion'

import {getSpanTags, mandatoryGitFields} from '../../helpers/tags'
import {GIT_SHA, getSpanTags, mandatoryGitFields} from '../../helpers/tags'

import {getApiHelper} from './api'
import {generatePayload} from './payload'
import {
renderDuplicateUpload,
renderFailedUpload,
renderInvalidFile,
renderInvalidPayload,
Expand Down Expand Up @@ -133,6 +133,15 @@ export class UploadSbomCommand extends Command {
this.context.stdout.write(`Upload done for ${basePath}.\n`)
}
} catch (error) {
if (isAxiosError(error)) {
if (error.response?.status === 409) {
const sha = tags[GIT_SHA] || 'sha-not-found'
this.context.stderr.write(renderDuplicateUpload(sha, environment, service))

return 0
}
}

this.context.stderr.write(renderFailedUpload(basePath, error))

return 1
Expand Down

0 comments on commit 75a65dc

Please sign in to comment.