Skip to content
Merged
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
10 changes: 5 additions & 5 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@ inputs:
footer:
description: 'A block of Markdown that will be appended to any PR comments posted'
required: false
eval-indirect-dependencies:
deprecationMessage: 'Deprecated in favor of SCA configurations'
description: 'Show vulnerabilities found in transitive dependencies'
required: false
default: false
artifact-prefix:
description: 'Prefix for the artifact name'
required: false
default: ''
code-scanning-path:
description: 'Path to write code scanning SARIF file'
required: false
default: 'code-scanning.sarif'
outputs:
old-completed:
description: 'If running a target called old, whether the analysis for this was completed'
Expand Down Expand Up @@ -97,3 +96,4 @@ runs:
token: '${{ inputs.token || github.token }}'
footer: '${{ inputs.footer }}'
artifact-prefix: '${{ inputs.artifact-prefix }}'
code-scanning-path: '${{ inputs.code-scanning-path }}'
103 changes: 66 additions & 37 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { error, getInput, info, setOutput, warning } from '@actions/core'
import { appendFileSync, existsSync } from 'fs'
import { appendFileSync, existsSync, readFileSync } from 'fs'
import {
downloadArtifact,
postCommentIfInPr,
resolveExistingCommentIfFound,
uploadArtifact,
} from './actions'
import { compareResults } from './tool'
import {
callCommand,
callLaceworkCli,
debug,
generateUILink,
getActionRef,
getMsSinceStart,
getOptionalEnvVariable,
Expand All @@ -21,10 +20,9 @@ import {

import path from 'path'

const scaSarifReport = 'scaReport/output.sarif'
const scaReport = 'sca.sarif'
const scaLWJSONReport = 'scaReport/output-lw.json'
const scaDir = 'scaReport'
const artifactPrefix = getInput('artifact-prefix')
const sarifReportPath = getInput('code-scanning-path')
const comparisonMarkdownPath = 'comparison.md'

async function runAnalysis() {
const target = getInput('target')
Expand All @@ -40,68 +38,91 @@ async function runAnalysis() {
}

info('Analyzing ' + target)
telemetryCollector.addField('tools', 'sca')
const toUpload: string[] = []

// command to print both sarif and lwjson formats
var args = ['sca', 'scan', '.', '-o', scaDir, '--formats', 'sarif,lw-json', '--deployment', 'ci']
var args = [
'sca',
'scan',
'.',
'--formats',
'sarif',
'--output',
sarifReportPath,
'--deployment',
'ci',
]
if (target === 'push') {
args.push('--save-results')
}
if (debug()) {
args.push('--debug')
}
await callLaceworkCli(...args)
// make a copy of the sarif file
args = [scaSarifReport, scaReport]
await callCommand('cp', ...args)

toUpload.push(scaReport)
toUpload.push(sarifReportPath)

const uploadStart = Date.now()
const artifactPrefix = getInput('artifact-prefix')
if (artifactPrefix !== '') {
await uploadArtifact(artifactPrefix + '-results-' + target, ...toUpload)
} else {
await uploadArtifact('results-' + target, ...toUpload)
}

await uploadArtifact(getArtifactName(target), ...toUpload)

telemetryCollector.addField('duration.upload-artifacts', (Date.now() - uploadStart).toString())
setOutput(`${target}-completed`, true)
}

export async function compareResults(oldReport: string, newReport: string): Promise<string> {
const args = [
'sca',
'compare',
'--old',
oldReport,
'--new',
newReport,
'--output',
sarifReportPath,
'--markdown',
comparisonMarkdownPath,
'--markdown-variant',
'GitHub',
'--deployment',
'ci',
]
const uiLink = generateUILink()
if (uiLink) args.push(...['--ui-link', uiLink])
if (debug()) args.push('--debug')

await callLaceworkCli(...args)
await uploadArtifact(getArtifactName('compare'), sarifReportPath, comparisonMarkdownPath)

return existsSync(comparisonMarkdownPath) ? readFileSync(comparisonMarkdownPath, 'utf8') : ''
}

async function displayResults() {
info('Displaying results')
const downloadStart = Date.now()
const artifactOld = await downloadArtifact('results-old')
const artifactNew = await downloadArtifact('results-new')
const artifactOld = await downloadArtifact(getArtifactName('old'))
const artifactNew = await downloadArtifact(getArtifactName('new'))
telemetryCollector.addField(
'duration.download-artifacts',
(Date.now() - downloadStart).toString()
)
const sarifFileOld = path.join(artifactOld, scaReport)
const sarifFileNew = path.join(artifactNew, scaReport)
const sarifFileOld = path.join(artifactOld, sarifReportPath)
const sarifFileNew = path.join(artifactNew, sarifReportPath)

const issuesByTool: { [tool: string]: string } = {}
var compareMessage: string
if (existsSync(sarifFileOld) && existsSync(sarifFileNew)) {
issuesByTool['sca'] = await compareResults('sca', sarifFileOld, sarifFileNew)
compareMessage = await compareResults(sarifFileOld, sarifFileNew)
} else {
throw new Error('SARIF file not found for SCA')
throw new Error('SARIF file not found')
}

const commentStart = Date.now()
if (Object.values(issuesByTool).some((x) => x.length > 0) && getInput('token').length > 0) {
if (compareMessage.length > 0 && getInput('token').length > 0) {
info('Posting comment to GitHub PR as there were new issues introduced:')
let message = ''
for (const [, issues] of Object.entries(issuesByTool)) {
if (issues.length > 0) {
message += issues
}
}
if (getInput('footer') !== '') {
message += '\n\n' + getInput('footer')
compareMessage += '\n\n' + getInput('footer')
}
info(message)
const commentUrl = await postCommentIfInPr(message)
info(compareMessage)
const commentUrl = await postCommentIfInPr(compareMessage)
if (commentUrl !== undefined) {
setOutput('posted-comment', commentUrl)
}
Expand All @@ -112,6 +133,14 @@ async function displayResults() {
setOutput(`display-completed`, true)
}

function getArtifactName(target: string): string {
var artifactName = 'results-'
if (artifactPrefix !== '') {
artifactName = artifactPrefix + '-' + artifactName
}
return artifactName + target
}

async function main() {
telemetryCollector.addField('duration.install', getMsSinceStart())
telemetryCollector.addField('version', getActionRef())
Expand Down
5 changes: 2 additions & 3 deletions src/post.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { info, warning } from '@actions/core'
import { context } from '@actions/github'
import { getActionsApi } from './actions'
import {
getActionRef,
getMsSinceStart,
Expand All @@ -7,8 +9,6 @@ import {
getRunUrl,
telemetryCollector,
} from './util'
import { getActionsApi } from './actions'
import { context } from '@actions/github'

async function main() {
if (getOptionalEnvVariable('LACEWORK_WROTE_TELEMETRY', 'false') !== 'true') {
Expand All @@ -32,7 +32,6 @@ async function main() {
telemetryCollector.addField('repository', getRequiredEnvVariable('GITHUB_REPOSITORY'))
telemetryCollector.addField('duration.total', getMsSinceStart())
telemetryCollector.addField('error', 'Unknown catastrophic error')
telemetryCollector.addField('tools', 'sca')
await telemetryCollector.report()
} else {
info('Telemetry has been reported previously')
Expand Down
33 changes: 0 additions & 33 deletions src/tool.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { error, getInput, info, isDebug } from '@actions/core'
import { context } from '@actions/github'
import { spawn } from 'child_process'
import { TelemetryCollector } from './telemetry'
import { readFileSync } from 'fs'
import { TelemetryCollector } from './telemetry'

export const telemetryCollector = new TelemetryCollector()

Expand Down