feat: add option to skip internal verifications (#336)

Add a `skip-verification` (boolean) option:
 
 - If `true`, the action will not validate the user or the commit verification status
 - Defaults to `false`

Allows for scenarios where users want to add or amend commits on the Dependabot PR, and those commits will not come from the :dependabot: user.

There's a fair bit of discussion on this use case and also why this isn't the default behavior, see:
* https://github.com/dependabot/fetch-metadata/pull/336
* https://github.com/dependabot/fetch-metadata/issues/332
This commit is contained in:
Yeikel
2023-04-17 15:44:22 -04:00
committed by GitHub
parent 684ca1c3fd
commit 6c2bf2fe33
6 changed files with 50 additions and 18 deletions

View File

@@ -48,6 +48,9 @@ Supported inputs are:
- `skip-commit-verification` (boolean) - `skip-commit-verification` (boolean)
- If `true`, then the action will not expect the commits to have a verification signature. **It is required to set this to 'true' in GitHub Enterprise Server** - If `true`, then the action will not expect the commits to have a verification signature. **It is required to set this to 'true' in GitHub Enterprise Server**
- Defaults to `false` - Defaults to `false`
- `skip-verification` (boolean)
- If `true`, the action will not validate the user or the commit verification status
- Defaults to `false`
Subsequent actions will have access to the following outputs: Subsequent actions will have access to the following outputs:

View File

@@ -15,7 +15,11 @@ inputs:
default: ${{ github.token }} default: ${{ github.token }}
skip-commit-verification: skip-commit-verification:
type: boolean type: boolean
description: 'If true, the action will not expect Dependabot commits to be verified. This should be set as `true` in GHES environments.' description: 'If true, the action will not expect Dependabot commits to be verified. This should be set as `true` in GHES environments'
default: false
skip-verification:
type: boolean
description: 'If true, the action will not validate the user or the commit verification status'
default: false default: false
outputs: outputs:
dependency-names: dependency-names:

20
dist/index.js generated vendored
View File

@@ -10200,34 +10200,38 @@ exports.getCompatibility = exports.trimSlashes = exports.getAlert = exports.getM
const core = __importStar(__nccwpck_require__(2186)); const core = __importStar(__nccwpck_require__(2186));
const https_1 = __importDefault(__nccwpck_require__(5687)); const https_1 = __importDefault(__nccwpck_require__(5687));
const DEPENDABOT_LOGIN = 'dependabot[bot]'; const DEPENDABOT_LOGIN = 'dependabot[bot]';
function getMessage(client, context, skipCommitVerification = false) { function getMessage(client, context, skipCommitVerification = false, skipVerification = false) {
var _a; var _a;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
core.debug('Verifying the job is for an authentic Dependabot Pull Request'); if (skipVerification) {
core.debug('Skipping pull request verification');
}
else {
core.debug('Verifying the job is for an authentic Dependabot Pull Request');
}
const { pull_request: pr } = context.payload; const { pull_request: pr } = context.payload;
if (!pr) { if (!pr) {
core.warning("Event payload missing `pull_request` key. Make sure you're " + core.warning("Event payload missing `pull_request` key. Make sure you're " +
'triggering this action on the `pull_request` or `pull_request_target` events.'); 'triggering this action on the `pull_request` or `pull_request_target` events.');
return false; return false;
} }
// Don't bother hitting the API if the PR author isn't Dependabot // Don't bother hitting the API if the PR author isn't Dependabot unless verification is disabled
if (pr.user.login !== DEPENDABOT_LOGIN) { if (!skipVerification && pr.user.login !== DEPENDABOT_LOGIN) {
core.debug(`PR author '${pr.user.login}' is not Dependabot.`); core.debug(`PR author '${pr.user.login}' is not Dependabot.`);
return false; return false;
} }
core.debug('Verifying the Pull Request contents are from Dependabot');
const { data: commits } = yield client.rest.pulls.listCommits({ const { data: commits } = yield client.rest.pulls.listCommits({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
pull_number: pr.number pull_number: pr.number
}); });
const { commit, author } = commits[0]; const { commit, author } = commits[0];
if ((author === null || author === void 0 ? void 0 : author.login) !== DEPENDABOT_LOGIN) { if (!skipVerification && (author === null || author === void 0 ? void 0 : author.login) !== DEPENDABOT_LOGIN) {
// TODO: Promote to setFailed // TODO: Promote to setFailed
core.warning('It looks like this PR was not created by Dependabot, refusing to proceed.'); core.warning('It looks like this PR was not created by Dependabot, refusing to proceed.');
return false; return false;
} }
if (!skipCommitVerification && !((_a = commit.verification) === null || _a === void 0 ? void 0 : _a.verified)) { if (!skipVerification && !skipCommitVerification && !((_a = commit.verification) === null || _a === void 0 ? void 0 : _a.verified)) {
// TODO: Promote to setFailed // TODO: Promote to setFailed
core.warning("Dependabot's commit signature is not verified, refusing to proceed."); core.warning("Dependabot's commit signature is not verified, refusing to proceed.");
return false; return false;
@@ -10351,7 +10355,7 @@ function run() {
try { try {
const githubClient = github.getOctokit(token); const githubClient = github.getOctokit(token);
// Validate the job // Validate the job
const commitMessage = yield verifiedCommits.getMessage(githubClient, github.context, core.getBooleanInput('skip-commit-verification')); const commitMessage = yield verifiedCommits.getMessage(githubClient, github.context, core.getBooleanInput('skip-commit-verification'), core.getBooleanInput('skip-verification'));
const branchNames = util.getBranchNames(github.context); const branchNames = util.getBranchNames(github.context);
let alertLookup; let alertLookup;
if (core.getInput('alert-lookup')) { if (core.getInput('alert-lookup')) {

View File

@@ -87,6 +87,25 @@ test('it returns the message if the commit is has no verification payload but ve
expect(await getMessage(mockGitHubClient, mockGitHubPullContext(), true)).toEqual('Bump lodash from 1.0.0 to 2.0.0') expect(await getMessage(mockGitHubClient, mockGitHubPullContext(), true)).toEqual('Bump lodash from 1.0.0 to 2.0.0')
}) })
test('it returns the message when skip-verification is enabled', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('true')
nock('https://api.github.com').get('/repos/dependabot/dependabot/pulls/101/commits')
.reply(200, [
{
author: {
login: 'myUser'
},
commit: {
message: 'Bump lodash from 1.0.0 to 2.0.0',
verification: false
}
}
])
expect(await getMessage(mockGitHubClient, mockGitHubPullContext(), false, true)).toEqual('Bump lodash from 1.0.0 to 2.0.0')
})
test('it returns false if the commit is not verified', async () => { test('it returns false if the commit is not verified', async () => {
nock('https://api.github.com').get('/repos/dependabot/dependabot/pulls/101/commits') nock('https://api.github.com').get('/repos/dependabot/dependabot/pulls/101/commits')
.reply(200, [ .reply(200, [

View File

@@ -6,8 +6,12 @@ import https from 'https'
const DEPENDABOT_LOGIN = 'dependabot[bot]' const DEPENDABOT_LOGIN = 'dependabot[bot]'
export async function getMessage (client: InstanceType<typeof GitHub>, context: Context, skipCommitVerification = false): Promise<string | false> { export async function getMessage (client: InstanceType<typeof GitHub>, context: Context, skipCommitVerification = false, skipVerification = false): Promise<string | false> {
core.debug('Verifying the job is for an authentic Dependabot Pull Request') if (skipVerification) {
core.debug('Skipping pull request verification')
} else {
core.debug('Verifying the job is for an authentic Dependabot Pull Request')
}
const { pull_request: pr } = context.payload const { pull_request: pr } = context.payload
@@ -19,14 +23,12 @@ export async function getMessage (client: InstanceType<typeof GitHub>, context:
return false return false
} }
// Don't bother hitting the API if the PR author isn't Dependabot // Don't bother hitting the API if the PR author isn't Dependabot unless verification is disabled
if (pr.user.login !== DEPENDABOT_LOGIN) { if (!skipVerification && pr.user.login !== DEPENDABOT_LOGIN) {
core.debug(`PR author '${pr.user.login}' is not Dependabot.`) core.debug(`PR author '${pr.user.login}' is not Dependabot.`)
return false return false
} }
core.debug('Verifying the Pull Request contents are from Dependabot')
const { data: commits } = await client.rest.pulls.listCommits({ const { data: commits } = await client.rest.pulls.listCommits({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
@@ -35,7 +37,7 @@ export async function getMessage (client: InstanceType<typeof GitHub>, context:
const { commit, author } = commits[0] const { commit, author } = commits[0]
if (author?.login !== DEPENDABOT_LOGIN) { if (!skipVerification && author?.login !== DEPENDABOT_LOGIN) {
// TODO: Promote to setFailed // TODO: Promote to setFailed
core.warning( core.warning(
'It looks like this PR was not created by Dependabot, refusing to proceed.' 'It looks like this PR was not created by Dependabot, refusing to proceed.'
@@ -43,7 +45,7 @@ export async function getMessage (client: InstanceType<typeof GitHub>, context:
return false return false
} }
if (!skipCommitVerification && !commit.verification?.verified) { if (!skipVerification && !skipCommitVerification && !commit.verification?.verified) {
// TODO: Promote to setFailed // TODO: Promote to setFailed
core.warning( core.warning(
"Dependabot's commit signature is not verified, refusing to proceed." "Dependabot's commit signature is not verified, refusing to proceed."

View File

@@ -22,7 +22,7 @@ export async function run (): Promise<void> {
const githubClient = github.getOctokit(token) const githubClient = github.getOctokit(token)
// Validate the job // Validate the job
const commitMessage = await verifiedCommits.getMessage(githubClient, github.context, core.getBooleanInput('skip-commit-verification')) const commitMessage = await verifiedCommits.getMessage(githubClient, github.context, core.getBooleanInput('skip-commit-verification'), core.getBooleanInput('skip-verification'))
const branchNames = util.getBranchNames(github.context) const branchNames = util.getBranchNames(github.context)
let alertLookup: updateMetadata.alertLookup | undefined let alertLookup: updateMetadata.alertLookup | undefined
if (core.getInput('alert-lookup')) { if (core.getInput('alert-lookup')) {