Skip to content

Commit eb405a1

Browse files
authored
feat(git-node): add git node benchmark (#1114)
1 parent 0ead0a1 commit eb405a1

6 files changed

Lines changed: 729 additions & 1 deletion

File tree

components/git/benchmark.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import auth from '../../lib/auth.js';
2+
import { parsePRFromURL } from '../../lib/links.js';
3+
import CLI from '../../lib/cli.js';
4+
import Request from '../../lib/request.js';
5+
import { runPromise } from '../../lib/run.js';
6+
import BenchmarkSession from '../../lib/benchmark.js';
7+
8+
export const command = 'benchmark <identifier>';
9+
export const describe =
10+
'Trigger the benchmark GitHub Actions workflow for a pull request';
11+
12+
const options = {
13+
owner: {
14+
alias: 'o',
15+
describe: 'GitHub owner of the PR repository',
16+
default: 'nodejs',
17+
type: 'string'
18+
},
19+
repo: {
20+
alias: 'r',
21+
describe: 'GitHub repository of the PR',
22+
default: 'node',
23+
type: 'string'
24+
},
25+
'workflow-owner': {
26+
describe: 'GitHub owner of the repository hosting the benchmark workflow ' +
27+
'(defaults to the PR owner)',
28+
type: 'string'
29+
},
30+
'workflow-repo': {
31+
describe: 'GitHub repository hosting the benchmark workflow ' +
32+
'(defaults to the PR repository)',
33+
type: 'string'
34+
},
35+
workflow: {
36+
describe: 'The workflow file to dispatch',
37+
default: 'benchmark.yml',
38+
type: 'string'
39+
},
40+
ref: {
41+
describe: 'The git ref of the workflow repository to run the workflow from',
42+
default: 'main',
43+
type: 'string'
44+
},
45+
runs: {
46+
describe: 'How many times to repeat each benchmark',
47+
type: 'number'
48+
}
49+
};
50+
51+
let yargsInstance;
52+
53+
export function builder(yargs) {
54+
yargsInstance = yargs;
55+
return yargs
56+
.options(options)
57+
.positional('identifier', {
58+
type: 'string',
59+
describe: 'ID or URL of the pull request. A commit URL ' +
60+
'(…/pull/<id>/commits/<sha>) benchmarks that commit instead of the ' +
61+
'PR head.'
62+
})
63+
.example('git node benchmark 12344',
64+
'Pick benchmark categories to run on ' +
65+
'https://github.com/nodejs/node/pull/12344')
66+
.example('git node benchmark https://github.com/nodejs/node/pull/12344',
67+
'Pick benchmark categories to run on ' +
68+
'https://github.com/nodejs/node/pull/12344')
69+
.example(
70+
'git node benchmark ' +
71+
'https://github.com/nodejs/node/pull/12344/commits/abc1234',
72+
'Benchmark commit abc1234 rather than the current PR head')
73+
.wrap(90);
74+
}
75+
76+
const COMMIT_URL_RE = /\/pull\/\d+\/commits\/([0-9a-f]{7,40})/i;
77+
78+
// Parse the positional identifier into { prid, owner?, repo?, commit? }.
79+
// A PR commit URL (…/pull/<id>/commits/<sha>) also yields the commit SHA.
80+
export function parseIdentifier(identifier) {
81+
const prid = Number.parseInt(identifier);
82+
if (!Number.isNaN(prid)) {
83+
return { prid };
84+
}
85+
const parsed = parsePRFromURL(identifier);
86+
if (!parsed) {
87+
return undefined;
88+
}
89+
const commit = COMMIT_URL_RE.exec(identifier);
90+
if (commit) {
91+
parsed.commit = commit[1];
92+
}
93+
return parsed;
94+
}
95+
96+
export function handler(argv) {
97+
const parsed = parseIdentifier(argv.identifier);
98+
if (!parsed) {
99+
return yargsInstance.showHelp();
100+
}
101+
Object.assign(argv, parsed);
102+
103+
return runPromise(main(argv));
104+
}
105+
106+
async function main(argv) {
107+
const cli = new CLI(process.stderr);
108+
const credentials = await auth({ github: true });
109+
const request = new Request(credentials);
110+
const session = new BenchmarkSession(cli, request, argv);
111+
return session.start();
112+
}

docs/git-node.md

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ A custom Git command for managing pull requests. You can run it as
2828
- [Usage](#usage)
2929
- [`git node status`](#git-node-status)
3030
- [Example](#example-2)
31-
- [`git node wpt`](#git-node-wpt)
31+
- [`git node benchmark`](#git-node-benchmark)
3232
- [Example](#example-3)
33+
- [`git node wpt`](#git-node-wpt)
34+
- [Example](#example-4)
3335

3436
## `git node land`
3537

@@ -568,6 +570,66 @@ Upstream: upstream
568570
Branch: main
569571
```
570572

573+
## `git node benchmark`
574+
575+
Trigger the [`benchmark.yml`][] GitHub Actions workflow on a pull request. The
576+
command fetches the PR, then prompts you to pick which benchmark categories to
577+
run (the folders in [`benchmark/`][] at the PR head). Categories whose files are
578+
touched by the PR are checked by default; if the PR touches no benchmark file,
579+
the pre-selection is guessed from the PR's subsystem labels. You are then prompted for an optional
580+
filter substring; if the PR touches a single benchmark file and only that file's
581+
category is selected, the filter is pre-filled with that file's name. Finally you
582+
are asked whether the workflow should post the results as a comment on the PR. It
583+
then dispatches the workflow with the PR number and its head commit.
584+
585+
```
586+
git-node benchmark <identifier>
587+
588+
Trigger the benchmark GitHub Actions workflow for a pull request
589+
590+
Positionals:
591+
identifier ID or URL of the pull request; a commit URL
592+
(…/pull/<id>/commits/<sha>) benchmarks that commit [string] [required]
593+
594+
Options:
595+
--version Show version number [boolean]
596+
--help Show help [boolean]
597+
--owner, -o GitHub owner of the PR repository [string] [default: "nodejs"]
598+
--repo, -r GitHub repository of the PR [string] [default: "node"]
599+
--workflow-owner GitHub owner of the repository hosting the benchmark workflow
600+
(defaults to the PR owner) [string]
601+
--workflow-repo GitHub repository hosting the benchmark workflow (defaults to the PR
602+
repository) [string]
603+
--workflow The workflow file to dispatch [string] [default: "benchmark.yml"]
604+
--ref The git ref of the workflow repository to run the workflow from
605+
[string] [default: "main"]
606+
--runs How many times to repeat each benchmark [number]
607+
```
608+
609+
The workflow is dispatched on the PR's repository by default. When the workflow
610+
lives in a different repository (for example a fork that hosts `benchmark.yml`),
611+
pass `--workflow-owner`/`--workflow-repo`, and the PR repository is forwarded to
612+
the workflow so it fetches the PR from the right place.
613+
614+
### Example
615+
616+
```bash
617+
# Interactively pick benchmark categories to run on nodejs/node#12344
618+
# (categories touched by the PR are pre-selected)
619+
$ git node benchmark 12344
620+
# is equivalent to
621+
$ git node benchmark https://github.com/nodejs/node/pull/12344
622+
623+
# Repeat each benchmark 10 times (the filter is asked interactively)
624+
$ git node benchmark 12344 --runs 10
625+
626+
# Dispatch the workflow hosted on a fork for a nodejs/node PR
627+
$ git node benchmark 12344 --workflow-owner my-user --workflow-repo node
628+
629+
# Benchmark a specific PR commit instead of the current PR head
630+
$ git node benchmark https://github.com/nodejs/node/pull/12344/commits/abc1234
631+
```
632+
571633
## `git node wpt`
572634

573635
Update or patch the Web Platform Tests in core.
@@ -603,3 +665,5 @@ $ git node wpt url --commit=43feb7f612fe9160639e09a47933a29834904d69
603665

604666
[node.js abi version registry]: https://github.com/nodejs/node/blob/main/doc/abi_version_registry.json
605667
[Security Release Process]: https://github.com/nodejs/node/blob/main/doc/contributing/security-release-process.md
668+
[`benchmark.yml`]: https://github.com/nodejs/node/blob/main/.github/workflows/benchmark.yml
669+
[`benchmark/`]: https://github.com/nodejs/node/tree/main/benchmark

0 commit comments

Comments
 (0)