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)
- 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`
- `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:

View File

@@ -15,7 +15,11 @@ inputs:
default: ${{ github.token }}
skip-commit-verification:
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
outputs:
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 https_1 = __importDefault(__nccwpck_require__(5687));
const DEPENDABOT_LOGIN = 'dependabot[bot]';
function getMessage(client, context, skipCommitVerification = false) {
function getMessage(client, context, skipCommitVerification = false, skipVerification = false) {
var _a;
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;
if (!pr) {
core.warning("Event payload missing `pull_request` key. Make sure you're " +
'triggering this action on the `pull_request` or `pull_request_target` events.');
return false;
}
// Don't bother hitting the API if the PR author isn't Dependabot
if (pr.user.login !== DEPENDABOT_LOGIN) {
// Don't bother hitting the API if the PR author isn't Dependabot unless verification is disabled
if (!skipVerification && pr.user.login !== DEPENDABOT_LOGIN) {
core.debug(`PR author '${pr.user.login}' is not Dependabot.`);
return false;
}
core.debug('Verifying the Pull Request contents are from Dependabot');
const { data: commits } = yield client.rest.pulls.listCommits({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number
});
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
core.warning('It looks like this PR was not created by Dependabot, refusing to proceed.');
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
core.warning("Dependabot's commit signature is not verified, refusing to proceed.");
return false;
@@ -10351,7 +10355,7 @@ function run() {
try {
const githubClient = github.getOctokit(token);
// 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);
let alertLookup;
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')
})
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 () => {
nock('https://api.github.com').get('/repos/dependabot/dependabot/pulls/101/commits')
.reply(200, [

View File

@@ -6,8 +6,12 @@ import https from 'https'
const DEPENDABOT_LOGIN = 'dependabot[bot]'
export async function getMessage (client: InstanceType<typeof GitHub>, context: Context, skipCommitVerification = false): Promise<string | false> {
core.debug('Verifying the job is for an authentic Dependabot Pull Request')
export async function getMessage (client: InstanceType<typeof GitHub>, context: Context, skipCommitVerification = false, skipVerification = false): Promise<string | false> {
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
@@ -19,14 +23,12 @@ export async function getMessage (client: InstanceType<typeof GitHub>, context:
return false
}
// Don't bother hitting the API if the PR author isn't Dependabot
if (pr.user.login !== DEPENDABOT_LOGIN) {
// Don't bother hitting the API if the PR author isn't Dependabot unless verification is disabled
if (!skipVerification && pr.user.login !== DEPENDABOT_LOGIN) {
core.debug(`PR author '${pr.user.login}' is not Dependabot.`)
return false
}
core.debug('Verifying the Pull Request contents are from Dependabot')
const { data: commits } = await client.rest.pulls.listCommits({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -35,7 +37,7 @@ export async function getMessage (client: InstanceType<typeof GitHub>, context:
const { commit, author } = commits[0]
if (author?.login !== DEPENDABOT_LOGIN) {
if (!skipVerification && author?.login !== DEPENDABOT_LOGIN) {
// TODO: Promote to setFailed
core.warning(
'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
}
if (!skipCommitVerification && !commit.verification?.verified) {
if (!skipVerification && !skipCommitVerification && !commit.verification?.verified) {
// TODO: Promote to setFailed
core.warning(
"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)
// 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)
let alertLookup: updateMetadata.alertLookup | undefined
if (core.getInput('alert-lookup')) {