Merge branch 'flag-security-alerts' into get_compat_score

This commit is contained in:
Michael Waddell
2022-02-21 19:27:14 -06:00
8 changed files with 44 additions and 24 deletions

View File

@@ -25,8 +25,17 @@ jobs:
uses: dependabot/fetch-metadata@v1.1.1
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
alert-lookup: true
```
Supported inputs are:
- `github-token` (REQUIRED string)
- The `GITHUB_TOKEN` secret
- `alert-lookup` (boolean)
- If `true`, then call populate the `alert-state`, `ghsa-id` and `cvss` outputs.
- Defaults to `false`
Subsequent actions will have access to the following outputs:
- `steps.dependabot-metadata.outputs.dependency-names`
@@ -50,11 +59,11 @@ Subsequent actions will have access to the following outputs:
- `steps.dependabot-metadata.outputs.compatibility-score`
- The compatibility score of this update (if known, 0 otherwise)
- `steps.dependabot-metadata.outputs.alert-state`
- If this PR is associated with a security alert, this contains the current state of that alert (OPEN, FIXED or DISMISSED).
- If this PR is associated with a security alert and `alert-lookup` is `true`, this contains the current state of that alert (OPEN, FIXED or DISMISSED).
- `steps.dependabot-metadata.outputs.ghsa-id`
- If this PR is associated with a security alert, this contains the GHSA-ID of that alert.
- If this PR is associated with a security alert and `alert-lookup` is `true`, this contains the GHSA-ID of that alert.
- `steps.dependabot-metadata.outputs.cvss`
- If this PR is associated with a security alert, this contains the CVSS value of that alert (otherwise it contains 0).
- If this PR is associated with a security alert and `alert-lookup` is `true`, this contains the CVSS value of that alert (otherwise it contains 0).
**Note:** These outputs will only be populated if the target Pull Request was opened by Dependabot and contains
**only** Dependabot-created commits.

View File

@@ -4,6 +4,9 @@ branding:
icon: 'search'
color: 'blue'
inputs:
alert-lookup:
type: boolean
description: 'If true, then call populate the `alert-state`, `ghsa-id` and `cvss` outputs'
github-token:
description: 'The GITHUB_TOKEN secret'
required: true
@@ -29,11 +32,11 @@ outputs:
compatibility-score:
description: 'The compatibility score of this update (if known, 0 otherwise)'
alert-state:
description: 'If this PR is associated with a security alert, this contains the current state of that alert (OPEN, FIXED or DISMISSED).'
description: 'If this PR is associated with a security alert and `alert-lookup` is `true`, this contains the current state of that alert (OPEN, FIXED or DISMISSED).'
ghsa-id:
description: 'If this PR is associated with a security alert, this contains the GHSA-ID of that alert.'
description: 'If this PR is associated with a security alert and `alert-lookup` is `true`, this contains the GHSA-ID of that alert.'
cvss:
description: 'If this PR is associated with a security alert, this contains the CVSS value of that alert (otherwise it contains 0).'
description: 'If this PR is associated with a security alert and `alert-lookup` is `true`, this contains the CVSS value of that alert (otherwise it contains 0).'
runs:
using: 'node12'
main: 'dist/index.js'

9
dist/index.js generated vendored
View File

@@ -9050,6 +9050,8 @@ function parse(commitMessage, branchName, mainBranch, lookup, getScore) {
return __awaiter(this, void 0, void 0, function* () {
const bumpFragment = commitMessage.match(/^Bumps .* from (?<from>\d[^ ]*) to (?<to>\d[^ ]*)\.$/m);
const yamlFragment = commitMessage.match(/^-{3}\n(?<dependencies>[\S|\s]*?)\n^\.{3}\n/m);
const lookupFn = lookup !== null && lookup !== void 0 ? lookup : (() => Promise.resolve({ alertState: '', ghsaId: '', cvss: 0 }));
const scoreFn = getScore !== null && getScore !== void 0 ? getScore : (() => Promise.resolve(0));
if ((yamlFragment === null || yamlFragment === void 0 ? void 0 : yamlFragment.groups) && branchName.startsWith('dependabot')) {
const data = YAML.parse(yamlFragment.groups.dependencies);
// Since we are on the `dependabot` branch (9 letters), the 10th letter in the branch name is the delimiter
@@ -9062,7 +9064,7 @@ function parse(commitMessage, branchName, mainBranch, lookup, getScore) {
const dirname = `/${chunks.slice(2, -1 * (1 + (dependency['dependency-name'].match(/\//g) || []).length)).join(delim) || ''}`;
const lastVersion = index === 0 ? prev : '';
const nextVersion = index === 0 ? next : '';
return Object.assign({ dependencyName: dependency['dependency-name'], dependencyType: dependency['dependency-type'], updateType: dependency['update-type'], directory: dirname, packageEcosystem: chunks[1], targetBranch: mainBranch, prevVersion: lastVersion, newVersion: nextVersion, compatScore: yield getScore(dependency['dependency-name'], lastVersion, nextVersion, chunks[1]) }, yield lookup(dependency['dependency-name'], lastVersion, dirname));
return Object.assign({ dependencyName: dependency['dependency-name'], dependencyType: dependency['dependency-type'], updateType: dependency['update-type'], directory: dirname, packageEcosystem: chunks[1], targetBranch: mainBranch, prevVersion: lastVersion, newVersion: nextVersion, compatScore: yield scoreFn(dependency['dependency-name'], lastVersion, nextVersion, chunks[1]) }, yield lookupFn(dependency['dependency-name'], lastVersion, dirname));
})));
}
}
@@ -9296,7 +9298,10 @@ function run() {
// Validate the job
const commitMessage = yield verifiedCommits.getMessage(githubClient, github.context);
const branchNames = util.getBranchNames(github.context);
const alertLookup = (name, version, directory) => verifiedCommits.getAlert(name, version, directory, githubClient, github.context);
let alertLookup;
if (core.getInput('alert-lookup')) {
alertLookup = (name, version, directory) => verifiedCommits.getAlert(name, version, directory, githubClient, github.context);
}
if (commitMessage) {
// Parse metadata
core.info('Parsing Dependabot metadata');

View File

@@ -142,9 +142,7 @@ test('it only returns information within the first fragment if there are multipl
'\n' +
'Signed-off-by: dependabot[bot] <support@github.com>'
const getAlert = async () => Promise.resolve({ alertState: '', ghsaId: '', cvss: 0 })
const getScore = async () => Promise.resolve(0)
const updatedDependencies = await updateMetadata.parse(commitMessage, 'dependabot|nuget|coffee-rails', 'main', getAlert, getScore)
const updatedDependencies = await updateMetadata.parse(commitMessage, 'dependabot|nuget|coffee-rails', 'main', undefined, undefined)
expect(updatedDependencies).toHaveLength(1)

View File

@@ -26,9 +26,11 @@ export interface scoreLookup {
(dependencyName: string, previousVersion: string, newVersion: string, ecosystem: string): Promise<number>;
}
export async function parse (commitMessage: string, branchName: string, mainBranch: string, lookup: alertLookup, getScore: scoreLookup): Promise<Array<updatedDependency>> {
export async function parse (commitMessage: string, branchName: string, mainBranch: string, lookup?: alertLookup, getScore?: scoreLookup): Promise<Array<updatedDependency>> {
const bumpFragment = commitMessage.match(/^Bumps .* from (?<from>\d[^ ]*) to (?<to>\d[^ ]*)\.$/m)
const yamlFragment = commitMessage.match(/^-{3}\n(?<dependencies>[\S|\s]*?)\n^\.{3}\n/m)
const lookupFn = lookup ?? (() => Promise.resolve({ alertState: '', ghsaId: '', cvss: 0 }))
const scoreFn = getScore ?? (() => Promise.resolve(0))
if (yamlFragment?.groups && branchName.startsWith('dependabot')) {
const data = YAML.parse(yamlFragment.groups.dependencies)
@@ -53,8 +55,8 @@ export async function parse (commitMessage: string, branchName: string, mainBran
targetBranch: mainBranch,
prevVersion: lastVersion,
newVersion: nextVersion,
compatScore: await getScore(dependency['dependency-name'], lastVersion, nextVersion, chunks[1]),
...await lookup(dependency['dependency-name'], lastVersion, dirname)
compatScore: await scoreFn(dependency['dependency-name'], lastVersion, nextVersion, chunks[1]),
...await lookupFn(dependency['dependency-name'], lastVersion, dirname)
}
}))
}

View File

@@ -51,9 +51,9 @@ async function check (args: any): Promise<void> {
if (commitMessage) {
console.log('This appears to be a valid Dependabot Pull Request.')
const branchNames = getBranchNames(newContext)
const alertLookup = (name, version, directory) => getAlert(name, version, directory, githubClient, actionContext)
const lookupFn = (name, version, directory) => getAlert(name, version, directory, githubClient, actionContext)
const updatedDependencies = await parse(commitMessage, branchNames.headName, branchNames.baseName, alertLookup, getCompatibility)
const updatedDependencies = await parse(commitMessage, branchNames.headName, branchNames.baseName, lookupFn, getCompatibility)
if (updatedDependencies.length > 0) {
console.log('Updated dependencies:')

View File

@@ -78,7 +78,7 @@ test('it sets the updated dependency as an output for subsequent actions', async
'Signed-off-by: dependabot[bot] <support@github.com>'
const mockAlert = { alertState: 'FIXED', ghsaId: 'GSHA', cvss: 3.4 }
jest.spyOn(core, 'getInput').mockReturnValue('mock-token')
jest.spyOn(core, 'getInput').mockImplementation(jest.fn((name) => { return name === 'github-token' ? 'mock-token' : '' }))
jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot|nuget|feature1', baseName: 'main' })
jest.spyOn(dependabotCommits, 'getMessage').mockImplementation(jest.fn(
() => Promise.resolve(mockCommitMessage)
@@ -110,9 +110,9 @@ test('it sets the updated dependency as an output for subsequent actions', async
prevVersion: '4.0.1',
newVersion: '4.2.2',
compatScore: 34,
alertState: 'FIXED',
ghsaId: 'GSHA',
cvss: 3.4
alertState: '',
ghsaId: '',
cvss: 0
}
]
)
@@ -126,9 +126,9 @@ test('it sets the updated dependency as an output for subsequent actions', async
expect(core.setOutput).toBeCalledWith('previous-version', '4.0.1')
expect(core.setOutput).toBeCalledWith('new-version', '4.2.2')
expect(core.setOutput).toBeCalledWith('compatibility-score', 34)
expect(core.setOutput).toBeCalledWith('alert-state', 'FIXED')
expect(core.setOutput).toBeCalledWith('ghsa-id', 'GSHA')
expect(core.setOutput).toBeCalledWith('cvss', 3.4)
expect(core.setOutput).toBeCalledWith('alert-state', '')
expect(core.setOutput).toBeCalledWith('ghsa-id', '')
expect(core.setOutput).toBeCalledWith('cvss', 0)
})
test('if there are multiple dependencies, it summarizes them', async () => {

View File

@@ -24,7 +24,10 @@ export async function run (): Promise<void> {
// Validate the job
const commitMessage = await verifiedCommits.getMessage(githubClient, github.context)
const branchNames = util.getBranchNames(github.context)
const alertLookup = (name, version, directory) => verifiedCommits.getAlert(name, version, directory, githubClient, github.context)
let alertLookup: updateMetadata.alertLookup | undefined
if (core.getInput('alert-lookup')) {
alertLookup = (name, version, directory) => verifiedCommits.getAlert(name, version, directory, githubClient, github.context)
}
if (commitMessage) {
// Parse metadata