@node-core/utils 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +158 -0
- package/bin/get-metadata.js +11 -0
- package/bin/git-node.js +30 -0
- package/bin/ncu-ci.js +600 -0
- package/bin/ncu-config.js +101 -0
- package/bin/ncu-team.js +76 -0
- package/components/git/backport.js +70 -0
- package/components/git/epilogue.js +18 -0
- package/components/git/land.js +223 -0
- package/components/git/metadata.js +94 -0
- package/components/git/release.js +99 -0
- package/components/git/security.js +35 -0
- package/components/git/status.js +32 -0
- package/components/git/sync.js +24 -0
- package/components/git/v8.js +121 -0
- package/components/git/vote.js +84 -0
- package/components/git/wpt.js +87 -0
- package/components/metadata.js +49 -0
- package/lib/auth.js +133 -0
- package/lib/backport_session.js +302 -0
- package/lib/cache.js +107 -0
- package/lib/cherry_pick.js +304 -0
- package/lib/ci/build-types/benchmark_run.js +72 -0
- package/lib/ci/build-types/citgm_build.js +194 -0
- package/lib/ci/build-types/citgm_comparison_build.js +174 -0
- package/lib/ci/build-types/commit_build.js +112 -0
- package/lib/ci/build-types/daily_build.js +24 -0
- package/lib/ci/build-types/fanned_build.js +87 -0
- package/lib/ci/build-types/health_build.js +63 -0
- package/lib/ci/build-types/job.js +114 -0
- package/lib/ci/build-types/linter_build.js +35 -0
- package/lib/ci/build-types/normal_build.js +89 -0
- package/lib/ci/build-types/pr_build.js +101 -0
- package/lib/ci/build-types/test_build.js +186 -0
- package/lib/ci/build-types/test_run.js +41 -0
- package/lib/ci/ci_failure_parser.js +325 -0
- package/lib/ci/ci_type_parser.js +203 -0
- package/lib/ci/ci_utils.js +106 -0
- package/lib/ci/failure_aggregator.js +152 -0
- package/lib/ci/jenkins_constants.js +28 -0
- package/lib/ci/run_ci.js +120 -0
- package/lib/cli.js +192 -0
- package/lib/collaborators.js +140 -0
- package/lib/config.js +72 -0
- package/lib/figures.js +7 -0
- package/lib/file.js +43 -0
- package/lib/github/templates/next-security-release.md +97 -0
- package/lib/github/tree.js +162 -0
- package/lib/landing_session.js +506 -0
- package/lib/links.js +123 -0
- package/lib/mergeable_state.js +3 -0
- package/lib/metadata_gen.js +61 -0
- package/lib/pr_checker.js +605 -0
- package/lib/pr_data.js +115 -0
- package/lib/pr_summary.js +62 -0
- package/lib/prepare_release.js +772 -0
- package/lib/prepare_security.js +117 -0
- package/lib/proxy.js +21 -0
- package/lib/queries/DefaultBranchRef.gql +8 -0
- package/lib/queries/LastCommit.gql +16 -0
- package/lib/queries/PR.gql +37 -0
- package/lib/queries/PRComments.gql +27 -0
- package/lib/queries/PRCommits.gql +45 -0
- package/lib/queries/PRs.gql +25 -0
- package/lib/queries/Reviews.gql +23 -0
- package/lib/queries/SearchIssue.gql +51 -0
- package/lib/queries/Team.gql +22 -0
- package/lib/queries/TreeEntries.gql +12 -0
- package/lib/queries/VotePRInfo.gql +28 -0
- package/lib/release/utils.js +53 -0
- package/lib/request.js +185 -0
- package/lib/review_state.js +5 -0
- package/lib/reviews.js +178 -0
- package/lib/run.js +106 -0
- package/lib/session.js +415 -0
- package/lib/sync_session.js +15 -0
- package/lib/team_info.js +95 -0
- package/lib/update-v8/applyNodeChanges.js +49 -0
- package/lib/update-v8/backport.js +258 -0
- package/lib/update-v8/commitUpdate.js +26 -0
- package/lib/update-v8/common.js +35 -0
- package/lib/update-v8/constants.js +86 -0
- package/lib/update-v8/index.js +56 -0
- package/lib/update-v8/majorUpdate.js +171 -0
- package/lib/update-v8/minorUpdate.js +105 -0
- package/lib/update-v8/updateMaintainingDependencies.js +34 -0
- package/lib/update-v8/updateV8Clone.js +53 -0
- package/lib/update-v8/updateVersionNumbers.js +122 -0
- package/lib/update-v8/util.js +62 -0
- package/lib/user.js +4 -0
- package/lib/user_status.js +5 -0
- package/lib/utils.js +66 -0
- package/lib/verbosity.js +26 -0
- package/lib/voting_session.js +136 -0
- package/lib/wpt/index.js +243 -0
- package/lib/wpt/templates/README.md +16 -0
- package/package.json +69 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import nv from '@pkgjs/nv';
|
|
2
|
+
import auth from './auth.js';
|
|
3
|
+
import Request from './request.js';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
|
|
6
|
+
export default class SecurityReleaseSteward {
|
|
7
|
+
constructor(cli) {
|
|
8
|
+
this.cli = cli;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async start() {
|
|
12
|
+
const { cli } = this;
|
|
13
|
+
const credentials = await auth({
|
|
14
|
+
github: true,
|
|
15
|
+
h1: true
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const req = new Request(credentials);
|
|
19
|
+
const create = await cli.prompt(
|
|
20
|
+
'Create the Next Security Release issue?',
|
|
21
|
+
{ defaultAnswer: true });
|
|
22
|
+
if (create) {
|
|
23
|
+
const issue = new SecurityReleaseIssue(req);
|
|
24
|
+
const content = await issue.buildIssue(cli);
|
|
25
|
+
const data = await req.createIssue('Next Security Release', content, {
|
|
26
|
+
owner: 'nodejs-private',
|
|
27
|
+
repo: 'node-private'
|
|
28
|
+
});
|
|
29
|
+
if (data.html_url) {
|
|
30
|
+
cli.ok('Created: ' + data.html_url);
|
|
31
|
+
} else {
|
|
32
|
+
cli.error(data);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class SecurityReleaseIssue {
|
|
39
|
+
constructor(req) {
|
|
40
|
+
this.req = req;
|
|
41
|
+
this.content = '';
|
|
42
|
+
this.title = 'Next Security Release';
|
|
43
|
+
this.affectedLines = {};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getSecurityIssueTemplate() {
|
|
47
|
+
return fs.readFileSync(
|
|
48
|
+
new URL(
|
|
49
|
+
'./github/templates/next-security-release.md',
|
|
50
|
+
import.meta.url
|
|
51
|
+
),
|
|
52
|
+
'utf-8'
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async buildIssue(cli) {
|
|
57
|
+
this.content = this.getSecurityIssueTemplate();
|
|
58
|
+
cli.info('Getting triaged H1 reports...');
|
|
59
|
+
const reports = await this.req.getTriagedReports();
|
|
60
|
+
await this.fillReports(cli, reports);
|
|
61
|
+
|
|
62
|
+
this.fillAffectedLines(Object.keys(this.affectedLines));
|
|
63
|
+
|
|
64
|
+
const target = await cli.prompt('Enter target date in YYYY-MM-DD format:', {
|
|
65
|
+
questionType: 'input',
|
|
66
|
+
defaultAnswer: 'TBD'
|
|
67
|
+
});
|
|
68
|
+
this.fillTargetDate(target);
|
|
69
|
+
|
|
70
|
+
return this.content;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async fillReports(cli, reports) {
|
|
74
|
+
const supportedVersions = (await nv('supported'))
|
|
75
|
+
.map((v) => v.versionName + '.x')
|
|
76
|
+
.join(',');
|
|
77
|
+
|
|
78
|
+
let reportsContent = '';
|
|
79
|
+
for (const report of reports.data) {
|
|
80
|
+
const { id, attributes: { title }, relationships: { severity } } = report;
|
|
81
|
+
const reportLevel = severity.data.attributes.rating;
|
|
82
|
+
cli.separator();
|
|
83
|
+
cli.info(`Report: ${id} - ${title} (${reportLevel})`);
|
|
84
|
+
const include = await cli.prompt(
|
|
85
|
+
'Would you like to include this report to the next security release?',
|
|
86
|
+
{ defaultAnswer: true });
|
|
87
|
+
if (!include) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
reportsContent +=
|
|
92
|
+
` * **[${id}](https://hackerone.com/bugs?subject=nodejs&report_id=${id}) - ${title} (TBD) - (${reportLevel})**\n`;
|
|
93
|
+
const versions = await cli.prompt('Which active release lines this report affects?', {
|
|
94
|
+
questionType: 'input',
|
|
95
|
+
defaultAnswer: supportedVersions
|
|
96
|
+
});
|
|
97
|
+
for (const v of versions.split(',')) {
|
|
98
|
+
if (!this.affectedLines[v]) this.affectedLines[v] = true;
|
|
99
|
+
reportsContent += ` * ${v} - TBD\n`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.content = this.content.replace('%REPORTS%', reportsContent);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fillAffectedLines(affectedLines) {
|
|
106
|
+
let affected = '';
|
|
107
|
+
for (const line of affectedLines) {
|
|
108
|
+
affected += ` * ${line} - TBD\n`;
|
|
109
|
+
}
|
|
110
|
+
this.content =
|
|
111
|
+
this.content.replace('%AFFECTED_LINES%', affected);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
fillTargetDate(date) {
|
|
115
|
+
this.content = this.content.replace('%RELEASE_DATE%', date);
|
|
116
|
+
}
|
|
117
|
+
}
|
package/lib/proxy.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { globalAgent } from 'node:https';
|
|
2
|
+
import { spawnSync } from 'child_process';
|
|
3
|
+
|
|
4
|
+
import { ProxyAgent } from 'undici';
|
|
5
|
+
|
|
6
|
+
import { getMergedConfig } from './config.js';
|
|
7
|
+
|
|
8
|
+
export default function proxy() {
|
|
9
|
+
let proxyUrl = getMergedConfig().proxy;
|
|
10
|
+
if (proxyUrl == null || proxyUrl === '') {
|
|
11
|
+
proxyUrl = spawnSync(
|
|
12
|
+
'git',
|
|
13
|
+
['config', '--get', '--path', 'https.proxy']
|
|
14
|
+
).stdout.toString();
|
|
15
|
+
}
|
|
16
|
+
if (proxyUrl == null || proxyUrl === '') {
|
|
17
|
+
return globalAgent;
|
|
18
|
+
} else {
|
|
19
|
+
return new ProxyAgent(proxyUrl);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
query LastCommit($owner: String!, $repo: String!, $branch: String!, $path: String) {
|
|
2
|
+
repository(owner: $owner, name: $repo) {
|
|
3
|
+
ref(qualifiedName: $branch) {
|
|
4
|
+
target {
|
|
5
|
+
... on Commit {
|
|
6
|
+
history(first: 1, path: $path) {
|
|
7
|
+
nodes {
|
|
8
|
+
oid
|
|
9
|
+
messageHeadline
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
query PR($prid: Int!, $owner: String!, $repo: String!) {
|
|
2
|
+
repository(owner: $owner, name: $repo) {
|
|
3
|
+
pullRequest(number: $prid) {
|
|
4
|
+
createdAt,
|
|
5
|
+
authorAssociation,
|
|
6
|
+
author {
|
|
7
|
+
... on User {
|
|
8
|
+
login,
|
|
9
|
+
email,
|
|
10
|
+
name
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
url,
|
|
14
|
+
bodyHTML,
|
|
15
|
+
bodyText,
|
|
16
|
+
labels(first: 100) {
|
|
17
|
+
nodes {
|
|
18
|
+
name
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
files(first: 100) {
|
|
22
|
+
nodes {
|
|
23
|
+
path
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
title,
|
|
27
|
+
baseRefName,
|
|
28
|
+
headRefName,
|
|
29
|
+
changedFiles,
|
|
30
|
+
mergeable,
|
|
31
|
+
closed,
|
|
32
|
+
closedAt,
|
|
33
|
+
merged,
|
|
34
|
+
mergedAt
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
query Comments($prid: Int!, $owner: String!, $repo: String!, $after: String) {
|
|
2
|
+
repository(owner: $owner, name: $repo) {
|
|
3
|
+
pullRequest(number: $prid) {
|
|
4
|
+
comments(first: 100, after: $after) {
|
|
5
|
+
totalCount
|
|
6
|
+
pageInfo {
|
|
7
|
+
hasNextPage
|
|
8
|
+
endCursor
|
|
9
|
+
}
|
|
10
|
+
nodes {
|
|
11
|
+
publishedAt
|
|
12
|
+
bodyText
|
|
13
|
+
author {
|
|
14
|
+
login
|
|
15
|
+
}
|
|
16
|
+
reactions(content: THUMBS_UP, first: 100) {
|
|
17
|
+
nodes {
|
|
18
|
+
user {
|
|
19
|
+
login
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
query Commits($prid: Int!, $owner: String!, $repo: String!, $after: String) {
|
|
2
|
+
repository(owner: $owner, name: $repo) {
|
|
3
|
+
pullRequest(number: $prid) {
|
|
4
|
+
commits(last: 100, after: $after) {
|
|
5
|
+
totalCount
|
|
6
|
+
pageInfo {
|
|
7
|
+
hasNextPage
|
|
8
|
+
endCursor
|
|
9
|
+
}
|
|
10
|
+
nodes {
|
|
11
|
+
commit {
|
|
12
|
+
committedDate
|
|
13
|
+
author {
|
|
14
|
+
user {
|
|
15
|
+
login
|
|
16
|
+
}
|
|
17
|
+
email
|
|
18
|
+
name
|
|
19
|
+
}
|
|
20
|
+
committer {
|
|
21
|
+
email
|
|
22
|
+
name
|
|
23
|
+
}
|
|
24
|
+
oid
|
|
25
|
+
message
|
|
26
|
+
messageHeadline
|
|
27
|
+
authoredByCommitter
|
|
28
|
+
checkSuites(first: 100) {
|
|
29
|
+
nodes {
|
|
30
|
+
app {
|
|
31
|
+
slug
|
|
32
|
+
}
|
|
33
|
+
conclusion,
|
|
34
|
+
status
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
status {
|
|
38
|
+
state
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
query PRs($owner: String!, $repo: String!, $labels: [String!]) {
|
|
2
|
+
repository(owner: $owner, name: $repo) {
|
|
3
|
+
pullRequests(states: [OPEN], first: 20, labels: $labels) {
|
|
4
|
+
nodes {
|
|
5
|
+
title,
|
|
6
|
+
url,
|
|
7
|
+
number,
|
|
8
|
+
author {
|
|
9
|
+
... on User {
|
|
10
|
+
login,
|
|
11
|
+
email,
|
|
12
|
+
name
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
labels(first: 100) {
|
|
16
|
+
nodes {
|
|
17
|
+
name
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
baseRefName,
|
|
21
|
+
mergeable,
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
query Reviews($prid: Int!, $owner: String!, $repo: String!, $after: String) {
|
|
2
|
+
repository(owner: $owner, name: $repo) {
|
|
3
|
+
pullRequest(number: $prid) {
|
|
4
|
+
reviews(first: 100, after: $after) {
|
|
5
|
+
totalCount
|
|
6
|
+
pageInfo {
|
|
7
|
+
hasNextPage
|
|
8
|
+
endCursor
|
|
9
|
+
}
|
|
10
|
+
nodes {
|
|
11
|
+
bodyText
|
|
12
|
+
state
|
|
13
|
+
author {
|
|
14
|
+
login
|
|
15
|
+
}
|
|
16
|
+
authorCanPushToRepository
|
|
17
|
+
url
|
|
18
|
+
publishedAt
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
query SearchIssueByUser($queryString: String!, $isCommenter: Boolean!, $after: String) {
|
|
2
|
+
search(query: $queryString, type: ISSUE, first: 100, after: $after) {
|
|
3
|
+
nodes {
|
|
4
|
+
... on PullRequest {
|
|
5
|
+
url
|
|
6
|
+
publishedAt
|
|
7
|
+
author {
|
|
8
|
+
login
|
|
9
|
+
}
|
|
10
|
+
title
|
|
11
|
+
reviews(last: 100) @include(if: $isCommenter) {
|
|
12
|
+
nodes {
|
|
13
|
+
publishedAt
|
|
14
|
+
author {
|
|
15
|
+
login
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
labels(first: 100) {
|
|
20
|
+
nodes {
|
|
21
|
+
name
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
comments(last: 100) @include(if: $isCommenter) {
|
|
25
|
+
nodes {
|
|
26
|
+
publishedAt
|
|
27
|
+
author {
|
|
28
|
+
login
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
... on Issue {
|
|
34
|
+
publishedAt
|
|
35
|
+
url
|
|
36
|
+
author {
|
|
37
|
+
login
|
|
38
|
+
}
|
|
39
|
+
title
|
|
40
|
+
comments(last: 100) @include(if: $isCommenter) {
|
|
41
|
+
nodes {
|
|
42
|
+
publishedAt
|
|
43
|
+
author {
|
|
44
|
+
login
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
query team($org: String!, $team: String!, $after: String) {
|
|
2
|
+
organization(login: $org) {
|
|
3
|
+
login
|
|
4
|
+
team(slug: $team) {
|
|
5
|
+
name,
|
|
6
|
+
description,
|
|
7
|
+
members(first: 100, after: $after) {
|
|
8
|
+
totalCount
|
|
9
|
+
pageInfo {
|
|
10
|
+
hasNextPage
|
|
11
|
+
endCursor
|
|
12
|
+
}
|
|
13
|
+
nodes {
|
|
14
|
+
login,
|
|
15
|
+
name,
|
|
16
|
+
email,
|
|
17
|
+
url
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
query PR($prid: Int!, $owner: String!, $repo: String!) {
|
|
2
|
+
repository(owner: $owner, name: $repo) {
|
|
3
|
+
pullRequest(number: $prid) {
|
|
4
|
+
commits(first: 1) {
|
|
5
|
+
nodes {
|
|
6
|
+
commit {
|
|
7
|
+
oid
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
headRef {
|
|
12
|
+
name
|
|
13
|
+
repository {
|
|
14
|
+
sshUrl
|
|
15
|
+
url
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
closed
|
|
19
|
+
merged
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
viewer {
|
|
23
|
+
login
|
|
24
|
+
publicKeys(first: 1) {
|
|
25
|
+
totalCount
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export function getEOLDate(ltsStartDate) {
|
|
2
|
+
// Maintenance LTS lasts for 18 months.
|
|
3
|
+
const result = getLTSMaintenanceStartDate(ltsStartDate);
|
|
4
|
+
result.setMonth(result.getMonth() + 18);
|
|
5
|
+
return result;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getLTSMaintenanceStartDate(ltsStartDate) {
|
|
9
|
+
// Active LTS lasts for one year.
|
|
10
|
+
const result = new Date(ltsStartDate);
|
|
11
|
+
result.setMonth(result.getMonth() + 12);
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getStartLTSBlurb({ date, ltsCodename, versionComponents }) {
|
|
16
|
+
const dateFormat = { month: 'long', year: 'numeric' };
|
|
17
|
+
// TODO pull these from the schedule.json in the Release repo?
|
|
18
|
+
const mainDate = getLTSMaintenanceStartDate(date);
|
|
19
|
+
const mainStart = mainDate.toLocaleString('en-US', dateFormat);
|
|
20
|
+
const eolDate = getEOLDate(date);
|
|
21
|
+
const eol = eolDate.toLocaleString('en-US', dateFormat);
|
|
22
|
+
const { major } = versionComponents;
|
|
23
|
+
return [
|
|
24
|
+
/* eslint-disable max-len */
|
|
25
|
+
`This release marks the transition of Node.js ${major}.x into Long Term Support (LTS)`,
|
|
26
|
+
`with the codename '${ltsCodename}'. The ${major}.x release line now moves into "Active LTS"`,
|
|
27
|
+
`and will remain so until ${mainStart}. After that time, it will move into`,
|
|
28
|
+
`"Maintenance" until end of life in ${eol}.`
|
|
29
|
+
/* eslint-enable */
|
|
30
|
+
].join('\n');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function updateTestProcessRelease(test, options) {
|
|
34
|
+
const { versionComponents, ltsCodename } = options;
|
|
35
|
+
if (test.includes(ltsCodename)) {
|
|
36
|
+
return test;
|
|
37
|
+
}
|
|
38
|
+
const inLines = test.split('\n');
|
|
39
|
+
const outLines = [];
|
|
40
|
+
const { major, minor } = versionComponents;
|
|
41
|
+
for (const line of inLines) {
|
|
42
|
+
if (line === '} else {') {
|
|
43
|
+
outLines.push(`} else if (versionParts[0] === '${major}' ` +
|
|
44
|
+
`&& versionParts[1] >= ${minor}) {`
|
|
45
|
+
);
|
|
46
|
+
outLines.push(
|
|
47
|
+
` assert.strictEqual(process.release.lts, '${ltsCodename}');`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
outLines.push(line);
|
|
51
|
+
}
|
|
52
|
+
return outLines.join('\n');
|
|
53
|
+
}
|
package/lib/request.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
|
|
3
|
+
import { fetch } from 'undici';
|
|
4
|
+
|
|
5
|
+
import { CI_DOMAIN } from './ci/ci_type_parser.js';
|
|
6
|
+
import proxy from './proxy.js';
|
|
7
|
+
import {
|
|
8
|
+
isDebugVerbosity,
|
|
9
|
+
debuglog
|
|
10
|
+
} from './verbosity.js';
|
|
11
|
+
|
|
12
|
+
function wrappedFetch(url, options, ...args) {
|
|
13
|
+
if (isDebugVerbosity()) {
|
|
14
|
+
debuglog('[fetch]', url);
|
|
15
|
+
}
|
|
16
|
+
return fetch(url, options, ...args);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default class Request {
|
|
20
|
+
constructor(credentials) {
|
|
21
|
+
this.credentials = credentials;
|
|
22
|
+
this.proxyAgent = proxy();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
loadQuery(file) {
|
|
26
|
+
const filePath = new URL(`./queries/${file}.gql`, import.meta.url);
|
|
27
|
+
return fs.readFileSync(filePath, 'utf8');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async fetch(url, options) {
|
|
31
|
+
options.agent = this.proxyAgent;
|
|
32
|
+
if (url.startsWith(`https://${CI_DOMAIN}`)) {
|
|
33
|
+
options.headers = options.headers || {};
|
|
34
|
+
Object.assign(options.headers, this.getJenkinsHeaders());
|
|
35
|
+
}
|
|
36
|
+
return wrappedFetch(url, options);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async buffer(url, options = {}) {
|
|
40
|
+
const res = await this.fetch(url, options);
|
|
41
|
+
const buffer = await res.arrayBuffer();
|
|
42
|
+
return Buffer.from(buffer);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async text(url, options = {}) {
|
|
46
|
+
return this.fetch(url, options).then(res => res.text());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async json(url, options = {}) {
|
|
50
|
+
options.headers = options.headers || {};
|
|
51
|
+
const text = await this.text(url, options);
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(text);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
if (isDebugVerbosity()) {
|
|
56
|
+
debuglog('[Request] Cannot parse JSON response from',
|
|
57
|
+
url, ':\n', text);
|
|
58
|
+
}
|
|
59
|
+
throw e;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async createIssue(title, body, { owner, repo }) {
|
|
64
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/issues`;
|
|
65
|
+
const options = {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
Authorization: `Basic ${this.credentials.github}`,
|
|
69
|
+
'User-Agent': 'node-core-utils',
|
|
70
|
+
Accept: 'application/vnd.github+json'
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify({
|
|
73
|
+
title,
|
|
74
|
+
body
|
|
75
|
+
})
|
|
76
|
+
};
|
|
77
|
+
return this.json(url, options);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async gql(name, variables, path) {
|
|
81
|
+
const query = this.loadQuery(name);
|
|
82
|
+
if (path) {
|
|
83
|
+
const result = await this.queryAll(query, variables, path);
|
|
84
|
+
return result;
|
|
85
|
+
} else {
|
|
86
|
+
const result = await this.query(query, variables);
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
getJenkinsHeaders() {
|
|
92
|
+
const jenkinsCredentials = this.credentials.jenkins;
|
|
93
|
+
if (!jenkinsCredentials) {
|
|
94
|
+
throw new Error('The request has not been ' +
|
|
95
|
+
'authenticated with a Jenkins token');
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
Authorization: `Basic ${jenkinsCredentials}`,
|
|
99
|
+
'User-Agent': 'node-core-utils'
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async getTriagedReports() {
|
|
104
|
+
const url = 'https://api.hackerone.com/v1/reports?filter[program][]=nodejs&filter[state][]=triaged';
|
|
105
|
+
const options = {
|
|
106
|
+
method: 'GET',
|
|
107
|
+
headers: {
|
|
108
|
+
Authorization: `Basic ${this.credentials.h1}`,
|
|
109
|
+
'User-Agent': 'node-core-utils',
|
|
110
|
+
Accept: 'application/json'
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
return this.json(url, options);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// This is for github v4 API queries, for other types of queries
|
|
117
|
+
// use .text or .json
|
|
118
|
+
async query(query, variables) {
|
|
119
|
+
const githubCredentials = this.credentials.github;
|
|
120
|
+
if (!githubCredentials) {
|
|
121
|
+
throw new Error('The request has not been ' +
|
|
122
|
+
'authenticated with a GitHub token');
|
|
123
|
+
}
|
|
124
|
+
const url = 'https://api.github.com/graphql';
|
|
125
|
+
const options = {
|
|
126
|
+
agent: this.proxyAgent,
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: {
|
|
129
|
+
Authorization: `Basic ${githubCredentials}`,
|
|
130
|
+
'User-Agent': 'node-core-utils',
|
|
131
|
+
Accept: 'application/vnd.github.antiope-preview+json'
|
|
132
|
+
},
|
|
133
|
+
body: JSON.stringify({
|
|
134
|
+
query,
|
|
135
|
+
variables
|
|
136
|
+
})
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const result = await this.json(url, options);
|
|
140
|
+
if (result.errors) {
|
|
141
|
+
const { type, message } = result.errors[0];
|
|
142
|
+
const err = new Error(`[${type}] GraphQL request Error: ${message}`);
|
|
143
|
+
err.data = {
|
|
144
|
+
variables
|
|
145
|
+
};
|
|
146
|
+
throw err;
|
|
147
|
+
}
|
|
148
|
+
if (result.message) {
|
|
149
|
+
const err = new Error(`GraphQL request Error: ${result.message}`);
|
|
150
|
+
err.data = {
|
|
151
|
+
variables
|
|
152
|
+
};
|
|
153
|
+
throw err;
|
|
154
|
+
}
|
|
155
|
+
return result.data;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async queryAll(query, variables, path) {
|
|
159
|
+
let after = null;
|
|
160
|
+
let all = [];
|
|
161
|
+
// first page
|
|
162
|
+
do {
|
|
163
|
+
const varWithPage = Object.assign({
|
|
164
|
+
after
|
|
165
|
+
}, variables);
|
|
166
|
+
const data = await this.query(query, varWithPage);
|
|
167
|
+
let current = data;
|
|
168
|
+
for (const step of path) {
|
|
169
|
+
current = current[step];
|
|
170
|
+
}
|
|
171
|
+
// current should have:
|
|
172
|
+
// totalCount
|
|
173
|
+
// pageInfo { hasNextPage, endCursor }
|
|
174
|
+
// nodes
|
|
175
|
+
all = all.concat(current.nodes);
|
|
176
|
+
if (current.pageInfo.hasNextPage) {
|
|
177
|
+
after = current.pageInfo.endCursor;
|
|
178
|
+
} else {
|
|
179
|
+
after = null;
|
|
180
|
+
}
|
|
181
|
+
} while (after !== null);
|
|
182
|
+
|
|
183
|
+
return all;
|
|
184
|
+
}
|
|
185
|
+
}
|