Skip to content

Commit

Permalink
feat(ncu-ci): require --certify-safe flag
Browse files Browse the repository at this point in the history
Or ensure the PR has received at least one approving review since last
time it was pushed.
  • Loading branch information
aduh95 committed Apr 24, 2024
1 parent 78ad337 commit 55e4f43
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 7 deletions.
7 changes: 6 additions & 1 deletion bin/ncu-ci.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ const args = yargs(hideBin(process.argv))
describe: 'ID of the PR',
type: 'number'
})
.positional('certify-safe', {
describe: 'If not provided, the command will reject PRs that have ' +
'been pushed since the last review',
type: 'boolean'
})
.option('owner', {
default: '',
describe: 'GitHub repository owner'
Expand Down Expand Up @@ -291,7 +296,7 @@ class RunPRJobCommand {
this.cli.setExitCode(1);
return;
}
const jobRunner = new RunPRJob(cli, request, owner, repo, prid);
const jobRunner = new RunPRJob(cli, request, owner, repo, prid, this.argv.certifySafe);
if (!(await jobRunner.start())) {
this.cli.setExitCode(1);
process.exitCode = 1;
Expand Down
15 changes: 13 additions & 2 deletions lib/ci/run_ci.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from './ci_type_parser.js';
import PRData from '../pr_data.js';
import { debuglog } from '../verbosity.js';
import PRChecker from '../pr_checker.js';

export const CI_CRUMB_URL = `https://${CI_DOMAIN}/crumbIssuer/api/json`;
const CI_PR_NAME = CI_TYPES.get(CI_TYPES_KEYS.PR).jobName;
Expand All @@ -16,13 +17,16 @@ const CI_V8_NAME = CI_TYPES.get(CI_TYPES_KEYS.V8).jobName;
export const CI_V8_URL = `https://${CI_DOMAIN}/job/${CI_V8_NAME}/build`;

export class RunPRJob {
constructor(cli, request, owner, repo, prid) {
constructor(cli, request, owner, repo, prid, certifySafe) {
this.cli = cli;
this.request = request;
this.owner = owner;
this.repo = repo;
this.prid = prid;
this.prData = new PRData({ prid, owner, repo }, cli, request);
this.certifySafe =
certifySafe ||
new PRChecker(cli, this.prData, request, {}).checkCommitsAfterReview();
}

async getCrumb() {
Expand Down Expand Up @@ -62,7 +66,13 @@ export class RunPRJob {
}

async start() {
const { cli } = this;
const { cli, certifySafe } = this;

if (!certifySafe) {
cli.error('Refusing to run CI on potentially unsafe PR');
return false;
}

cli.startSpinner('Validating Jenkins credentials');
const crumb = await this.getCrumb();

Expand All @@ -75,6 +85,7 @@ export class RunPRJob {

try {
cli.startSpinner('Starting PR CI job');
throw 'NOOO'

Check failure on line 88 in lib/ci/run_ci.js

View workflow job for this annotation

GitHub Actions / Lint using ESLint

Expected an error object to be thrown

Check failure on line 88 in lib/ci/run_ci.js

View workflow job for this annotation

GitHub Actions / Lint using ESLint

Missing semicolon
const response = await this.request.fetch(CI_PR_URL, {

Check failure on line 89 in lib/ci/run_ci.js

View workflow job for this annotation

GitHub Actions / Lint using ESLint

Unreachable code
method: 'POST',
headers: {
Expand Down
1 change: 1 addition & 0 deletions lib/pr_checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ export default class PRChecker {
);

if (reviewIndex === -1) {
cli.warn('No approving reviews found');
return false;
}

Expand Down
8 changes: 4 additions & 4 deletions test/unit/ci_start.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('Jenkins', () => {
.returns(Promise.resolve({ crumb }))
};

const jobRunner = new RunPRJob(cli, request, owner, repo, prid);
const jobRunner = new RunPRJob(cli, request, owner, repo, prid, true);
assert.strictEqual(await jobRunner.start(), false);
});

Expand All @@ -61,7 +61,7 @@ describe('Jenkins', () => {
json: sinon.stub().throws()
};

const jobRunner = new RunPRJob(cli, request, owner, repo, prid);
const jobRunner = new RunPRJob(cli, request, owner, repo, prid, true);
assert.strictEqual(await jobRunner.start(), false);
});

Expand Down Expand Up @@ -89,7 +89,7 @@ describe('Jenkins', () => {
json: sinon.stub().withArgs(CI_CRUMB_URL)
.returns(Promise.resolve({ crumb }))
};
const jobRunner = new RunPRJob(cli, request, owner, repo, prid);
const jobRunner = new RunPRJob(cli, request, owner, repo, prid, true);
assert.ok(await jobRunner.start());

Check failure on line 93 in test/unit/ci_start.test.js

View workflow job for this annotation

GitHub Actions / Test on Node.js / test (20, ubuntu-latest)

should start node-pull-request

[Error [ERR_TEST_FAILURE]: false == true] { code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: AssertionError [ERR_ASSERTION]: false == true at TestContext.<anonymous> (file:///home/runner/work/node-core-utils/node-core-utils/test/unit/ci_start.test.js:93:12) at async Test.run (node:internal/test_runner/test:640:9) at async Suite.processPendingSubtests (node:internal/test_runner/test:382:7) { generatedMessage: true, code: 'ERR_ASSERTION', actual: false, expected: true, operator: '==' } }

Check failure on line 93 in test/unit/ci_start.test.js

View workflow job for this annotation

GitHub Actions / Test on Node.js / test (20, macos-latest)

should start node-pull-request

[Error [ERR_TEST_FAILURE]: false == true] { code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: AssertionError [ERR_ASSERTION]: false == true at TestContext.<anonymous> (file:///Users/runner/work/node-core-utils/node-core-utils/test/unit/ci_start.test.js:93:12) at async Test.run (node:internal/test_runner/test:640:9) at async Suite.processPendingSubtests (node:internal/test_runner/test:382:7) { generatedMessage: true, code: 'ERR_ASSERTION', actual: false, expected: true, operator: '==' } }

Check failure on line 93 in test/unit/ci_start.test.js

View workflow job for this annotation

GitHub Actions / Test on Node.js / test (18, ubuntu-latest)

should start node-pull-request

[Error [ERR_TEST_FAILURE]: false == true] { failureType: 'testCodeFailure', cause: AssertionError [ERR_ASSERTION]: false == true at TestContext.<anonymous> (file:///home/runner/work/node-core-utils/node-core-utils/test/unit/ci_start.test.js:93:12) at async Test.run (node:internal/test_runner/test:632:9) at async Suite.processPendingSubtests (node:internal/test_runner/test:374:7) { generatedMessage: true, code: 'ERR_ASSERTION', actual: false, expected: true, operator: '==' }, code: 'ERR_TEST_FAILURE' }

Check failure on line 93 in test/unit/ci_start.test.js

View workflow job for this annotation

GitHub Actions / Test on Node.js / test (18, macos-latest)

should start node-pull-request

[Error [ERR_TEST_FAILURE]: false == true] { failureType: 'testCodeFailure', cause: AssertionError [ERR_ASSERTION]: false == true at TestContext.<anonymous> (file:///Users/runner/work/node-core-utils/node-core-utils/test/unit/ci_start.test.js:93:12) at async Test.run (node:internal/test_runner/test:632:9) at async Suite.processPendingSubtests (node:internal/test_runner/test:374:7) { generatedMessage: true, code: 'ERR_ASSERTION', actual: false, expected: true, operator: '==' }, code: 'ERR_TEST_FAILURE' }

Check failure on line 93 in test/unit/ci_start.test.js

View workflow job for this annotation

GitHub Actions / Test on Node.js / test (21, ubuntu-latest, experimental)

should start node-pull-request

[Error [ERR_TEST_FAILURE]: false == true] { code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: AssertionError [ERR_ASSERTION]: false == true at TestContext.<anonymous> (file:///home/runner/work/node-core-utils/node-core-utils/test/unit/ci_start.test.js:93:12) at async Test.run (node:internal/test_runner/test:640:9) at async Suite.processPendingSubtests (node:internal/test_runner/test:382:7) { generatedMessage: true, code: 'ERR_ASSERTION', actual: false, expected: true, operator: '==' } }

Check failure on line 93 in test/unit/ci_start.test.js

View workflow job for this annotation

GitHub Actions / Test on Node.js / test (21, macos-latest, experimental)

should start node-pull-request

[Error [ERR_TEST_FAILURE]: false == true] { code: 'ERR_TEST_FAILURE', failureType: 'testCodeFailure', cause: AssertionError [ERR_ASSERTION]: false == true at TestContext.<anonymous> (file:///Users/runner/work/node-core-utils/node-core-utils/test/unit/ci_start.test.js:93:12) at async Test.run (node:internal/test_runner/test:640:9) at async Suite.processPendingSubtests (node:internal/test_runner/test:382:7) { generatedMessage: true, code: 'ERR_ASSERTION', actual: false, expected: true, operator: '==' } }
});

Expand All @@ -108,7 +108,7 @@ describe('Jenkins', () => {
json: sinon.stub().withArgs(CI_CRUMB_URL)
.returns(Promise.resolve({ crumb }))
};
const jobRunner = new RunPRJob(cli, request, owner, repo, prid);
const jobRunner = new RunPRJob(cli, request, owner, repo, prid, true);
assert.strictEqual(await jobRunner.start(), false);
});
});

0 comments on commit 55e4f43

Please sign in to comment.