Skip to content

Commit

Permalink
Merge pull request #556 from actions/juxtin/dr-snaps-pre-launch
Browse files Browse the repository at this point in the history
Dr Snaps launch PR
juxtin authored Sep 7, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 511675e + bb0ca79 commit e4d20ce
Showing 10 changed files with 169 additions and 37 deletions.
4 changes: 3 additions & 1 deletion __tests__/summary.test.ts
Original file line number Diff line number Diff line change
@@ -26,7 +26,9 @@ const defaultConfig: ConfigurationOptions = {
deny_licenses: [],
deny_packages: [],
deny_groups: [],
comment_summary_in_pr: true
comment_summary_in_pr: true,
retry_on_snapshot_warnings: false,
retry_on_snapshot_warnings_timeout: 120
}

const changesWithEmptyManifests: Changes = [
8 changes: 8 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -53,6 +53,14 @@ inputs:
deny-groups:
description: A comma-separated list of package URLs for group(s)/namespace(s) to deny (e.g. "pkg:npm/express, pkg:pip/pycrypto")
required: false
retry-on-snapshot-warnings:
description: Whether to retry on snapshot warnings
required: false
default: false
retry-on-snapshot-warnings-timeout:
description: Number of seconds to wait before stopping snapshot retries.
required: false
default: 120
runs:
using: 'node16'
main: 'dist/index.js'
67 changes: 51 additions & 16 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

38 changes: 37 additions & 1 deletion docs/examples.md
Original file line number Diff line number Diff line change
@@ -257,4 +257,40 @@ jobs:
with:
deny-packages: 'pkg:maven/org.apache.logging.log4j/log4j-api,pkg:maven/org.apache.logging.log4j/log4j-core'
deny-groups: 'pkg:maven/com.bazaarvoice.jolt'
```
```

## Waiting for dependency submission jobs to complete

When possible, this action will [include dependencies submitted through the dependency submission API][DSAPI]. In this case,
it's important for the action not to complete until all of the relevant dependencies have been submitted for both the base
and head commits.

When this action runs before one or more of the dependency submission actions, there will be an unequal number of dependency
snapshots between the base and head commits. For example, there may be one snapshot available for the tip of `main` and none
for the PR branch. In that case, the API response will contain a "snapshot warning" explaining the discrepancy.

In this example, when the action encounters one of these warnings it will retry every 10 seconds after that for 60 seconds
or until there is no warning in the response.

```yaml
name: 'Dependency Review'
on: [pull_request]
permissions:
contents: read
pull-requests: write
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: 'Dependency Review'
uses: actions/dependency-review-action@v3
with:
retry-on-snapshot-warnings: true
retry-on-snapshot-warnings-timeout: 60
```

[DSAPI]: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#best-practices-for-using-the-dependency-review-api-and-the-dependency-submission-api-together
4 changes: 3 additions & 1 deletion scripts/create_summary.ts
Original file line number Diff line number Diff line change
@@ -30,7 +30,9 @@ const defaultConfig: ConfigurationOptions = {
'pkg:pip/certifi',
'pkg:pip/[email protected]'
],
comment_summary_in_pr: 'never'
comment_summary_in_pr: true,
retry_on_snapshot_warnings: false,
retry_on_snapshot_warnings_timeout: 120
}

const tmpDir = path.resolve(__dirname, '../tmp')
16 changes: 15 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
@@ -41,6 +41,12 @@ function readInlineConfig(): ConfigurationOptionsPartial {
const base_ref = getOptionalInput('base-ref')
const head_ref = getOptionalInput('head-ref')
const comment_summary_in_pr = getOptionalInput('comment-summary-in-pr')
const retry_on_snapshot_warnings = getOptionalBoolean(
'retry-on-snapshot-warnings'
)
const retry_on_snapshot_warnings_timeout = getOptionalNumber(
'retry-on-snapshot-warnings-timeout'
)

validatePURL(allow_dependencies_licenses)
validateLicenses('allow-licenses', allow_licenses)
@@ -59,14 +65,22 @@ function readInlineConfig(): ConfigurationOptionsPartial {
vulnerability_check,
base_ref,
head_ref,
comment_summary_in_pr
comment_summary_in_pr,
retry_on_snapshot_warnings,
retry_on_snapshot_warnings_timeout
}

return Object.fromEntries(
Object.entries(keys).filter(([_, value]) => value !== undefined)
)
}

function getOptionalNumber(name: string): number | undefined {
const value = core.getInput(name)
const parsed = z.string().regex(/^\d+$/).transform(Number).safeParse(value)
return parsed.success ? parsed.data : undefined
}

function getOptionalBoolean(name: string): boolean | undefined {
const value = core.getInput(name)
return value.length > 0 ? core.getBooleanInput(name) : undefined
54 changes: 48 additions & 6 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -18,18 +18,60 @@ import {groupDependenciesByManifest} from './utils'
import {commentPr} from './comment-pr'
import {getDeniedChanges} from './deny'

async function delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}

async function getComparison(
baseRef: string,
headRef: string,
retryOpts?: {
retryUntil: number
retryDelay: number
}
): ReturnType<typeof dependencyGraph.compare> {
const comparison = await dependencyGraph.compare({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
baseRef,
headRef
})

if (comparison.snapshot_warnings.trim() !== '') {
core.info(comparison.snapshot_warnings)
if (retryOpts !== undefined) {
if (retryOpts.retryUntil < Date.now()) {
core.info(`Retry timeout exceeded. Proceeding...`)
return comparison
} else {
core.info(`Retrying in ${retryOpts.retryDelay} seconds...`)
await delay(retryOpts.retryDelay * 1000)
return getComparison(baseRef, headRef, retryOpts)
}
}
}

return comparison
}

async function run(): Promise<void> {
try {
const config = await readConfig()

const refs = getRefs(config, github.context)

const comparison = await dependencyGraph.compare({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
baseRef: refs.base,
headRef: refs.head
})
const comparison = await getComparison(
refs.base,
refs.head,
config.retry_on_snapshot_warnings
? {
retryUntil:
Date.now() + config.retry_on_snapshot_warnings_timeout * 1000,
retryDelay: 10
}
: undefined
)

const changes = comparison.changes
const snapshot_warnings = comparison.snapshot_warnings

2 changes: 2 additions & 0 deletions src/schemas.ts
Original file line number Diff line number Diff line change
@@ -49,6 +49,8 @@ export const ConfigurationOptionsSchema = z
config_file: z.string().optional(),
base_ref: z.string().optional(),
head_ref: z.string().optional(),
retry_on_snapshot_warnings: z.boolean().default(false),
retry_on_snapshot_warnings_timeout: z.number().default(120),
comment_summary_in_pr: z
.union([
z.preprocess(
11 changes: 1 addition & 10 deletions src/summary.ts
Original file line number Diff line number Diff line change
@@ -232,19 +232,10 @@ export function addScannedDependencies(changes: Changes): void {
}

export function addSnapshotWarnings(warnings: string): void {
// For now, we want to ignore warnings that just complain
// about missing snapshots on the head SHA. This is a product
// decision to avoid presenting warnings to users who simply
// don't use snapshots.
const ignore_regex = new RegExp(/No.*snapshot.*found.*head.*/, 'i')
if (ignore_regex.test(warnings)) {
return
}

core.summary.addHeading('Snapshot Warnings', 2)
core.summary.addQuote(`${icons.warning}: ${warnings}`)
core.summary.addRaw(
'Re-running this action after a short time may resolve the issue. See the documentation for more information and troubleshooting advice.'
'Re-running this action after a short time may resolve the issue. See <a href="https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#best-practices-for-using-the-dependency-review-api-and-the-dependency-submission-api-together">the documentation</a> for more information and troubleshooting advice.'
)
}

0 comments on commit e4d20ce

Please sign in to comment.