initial commit
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as githubUtils from '@actions/github/lib/utils'
|
||||
import * as retry from '@octokit/plugin-retry'
|
||||
import {Changes, ChangesSchema} from './schemas'
|
||||
|
||||
const retryingOctokit = githubUtils.GitHub.plugin(retry.retry)
|
||||
const octo = new retryingOctokit(
|
||||
githubUtils.getOctokitOptions(core.getInput('repo-token', {required: true}))
|
||||
)
|
||||
|
||||
export async function compare({
|
||||
owner,
|
||||
repo,
|
||||
baseRef,
|
||||
headRef
|
||||
}: {
|
||||
owner: string
|
||||
repo: string
|
||||
baseRef: string
|
||||
headRef: string
|
||||
}): Promise<Changes> {
|
||||
const changes = await octo.paginate(
|
||||
'GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}',
|
||||
{
|
||||
owner,
|
||||
repo,
|
||||
basehead: `${baseRef}...${headRef}`
|
||||
}
|
||||
)
|
||||
return ChangesSchema.parse(changes)
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as dependencyGraph from './dependency-graph'
|
||||
import * as github from '@actions/github'
|
||||
import styles from 'ansi-styles'
|
||||
import {RequestError} from '@octokit/request-error'
|
||||
import {PullRequestSchema} from './schemas'
|
||||
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
if (github.context.eventName !== 'pull_request') {
|
||||
throw new Error(
|
||||
`This run was triggered by the "${github.context.eventName}" event, which is unsupported. Please ensure you are using the "pull_request" event for this workflow.`
|
||||
)
|
||||
}
|
||||
|
||||
const pull_request = PullRequestSchema.parse(
|
||||
github.context.payload.pull_request
|
||||
)
|
||||
|
||||
const changes = await dependencyGraph.compare({
|
||||
owner: github.context.repo.owner,
|
||||
repo: github.context.repo.repo,
|
||||
baseRef: pull_request.base.sha,
|
||||
headRef: pull_request.head.sha
|
||||
})
|
||||
|
||||
let failed = false
|
||||
|
||||
for (const change of changes) {
|
||||
if (
|
||||
change.change_type === 'added' &&
|
||||
change.vulnerabilities !== undefined &&
|
||||
change.vulnerabilities.length > 0
|
||||
) {
|
||||
for (const vuln of change.vulnerabilities) {
|
||||
core.info(
|
||||
`${styles.bold.open}${change.manifest} » ${change.name}@${
|
||||
change.version
|
||||
}${styles.bold.close} – ${vuln.advisory_summary} ${renderSeverity(
|
||||
vuln.severity
|
||||
)}`
|
||||
)
|
||||
core.info(` ↪ ${vuln.advisory_url}`)
|
||||
}
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
throw new Error('Dependency review detected vulnerable packages.')
|
||||
} else {
|
||||
core.info('Dependency review did not detect any vulnerable packages.')
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof RequestError && error.status === 404) {
|
||||
core.setFailed(
|
||||
`Dependency review is not supported on this repository. Please ensure that Dependency graph is enabled, see https://github.com/${github.context.repo.owner}/${github.context.repo.repo}/settings/security_analysis`
|
||||
)
|
||||
} else if (error instanceof Error) {
|
||||
core.setFailed(error.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function renderSeverity(
|
||||
severity: 'critical' | 'high' | 'moderate' | 'low'
|
||||
): string {
|
||||
const color = (
|
||||
{
|
||||
critical: 'red',
|
||||
high: 'red',
|
||||
moderate: 'yellow',
|
||||
low: 'grey'
|
||||
} as const
|
||||
)[severity]
|
||||
return `${styles.color[color].open}(${severity} severity)${styles.color[color].close}`
|
||||
}
|
||||
|
||||
run()
|
||||
@@ -0,0 +1,32 @@
|
||||
import * as z from 'zod'
|
||||
|
||||
const ChangeSchema = z.object({
|
||||
change_type: z.enum(['added', 'removed']),
|
||||
manifest: z.string(),
|
||||
ecosystem: z.string(),
|
||||
name: z.string(),
|
||||
version: z.string(),
|
||||
package_url: z.string(),
|
||||
license: z.string().nullable(),
|
||||
source_repository_url: z.string().nullable(),
|
||||
vulnerabilities: z
|
||||
.array(
|
||||
z.object({
|
||||
severity: z.enum(['critical', 'high', 'moderate', 'low']),
|
||||
advisory_ghsa_id: z.string(),
|
||||
advisory_summary: z.string(),
|
||||
advisory_url: z.string()
|
||||
})
|
||||
)
|
||||
.optional()
|
||||
})
|
||||
|
||||
export const PullRequestSchema = z.object({
|
||||
number: z.number(),
|
||||
base: z.object({sha: z.string()}),
|
||||
head: z.object({sha: z.string()})
|
||||
})
|
||||
|
||||
export const ChangesSchema = z.array(ChangeSchema)
|
||||
|
||||
export type Changes = z.infer<typeof ChangesSchema>
|
||||
Reference in New Issue
Block a user