@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.
Files changed (98) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +158 -0
  3. package/bin/get-metadata.js +11 -0
  4. package/bin/git-node.js +30 -0
  5. package/bin/ncu-ci.js +600 -0
  6. package/bin/ncu-config.js +101 -0
  7. package/bin/ncu-team.js +76 -0
  8. package/components/git/backport.js +70 -0
  9. package/components/git/epilogue.js +18 -0
  10. package/components/git/land.js +223 -0
  11. package/components/git/metadata.js +94 -0
  12. package/components/git/release.js +99 -0
  13. package/components/git/security.js +35 -0
  14. package/components/git/status.js +32 -0
  15. package/components/git/sync.js +24 -0
  16. package/components/git/v8.js +121 -0
  17. package/components/git/vote.js +84 -0
  18. package/components/git/wpt.js +87 -0
  19. package/components/metadata.js +49 -0
  20. package/lib/auth.js +133 -0
  21. package/lib/backport_session.js +302 -0
  22. package/lib/cache.js +107 -0
  23. package/lib/cherry_pick.js +304 -0
  24. package/lib/ci/build-types/benchmark_run.js +72 -0
  25. package/lib/ci/build-types/citgm_build.js +194 -0
  26. package/lib/ci/build-types/citgm_comparison_build.js +174 -0
  27. package/lib/ci/build-types/commit_build.js +112 -0
  28. package/lib/ci/build-types/daily_build.js +24 -0
  29. package/lib/ci/build-types/fanned_build.js +87 -0
  30. package/lib/ci/build-types/health_build.js +63 -0
  31. package/lib/ci/build-types/job.js +114 -0
  32. package/lib/ci/build-types/linter_build.js +35 -0
  33. package/lib/ci/build-types/normal_build.js +89 -0
  34. package/lib/ci/build-types/pr_build.js +101 -0
  35. package/lib/ci/build-types/test_build.js +186 -0
  36. package/lib/ci/build-types/test_run.js +41 -0
  37. package/lib/ci/ci_failure_parser.js +325 -0
  38. package/lib/ci/ci_type_parser.js +203 -0
  39. package/lib/ci/ci_utils.js +106 -0
  40. package/lib/ci/failure_aggregator.js +152 -0
  41. package/lib/ci/jenkins_constants.js +28 -0
  42. package/lib/ci/run_ci.js +120 -0
  43. package/lib/cli.js +192 -0
  44. package/lib/collaborators.js +140 -0
  45. package/lib/config.js +72 -0
  46. package/lib/figures.js +7 -0
  47. package/lib/file.js +43 -0
  48. package/lib/github/templates/next-security-release.md +97 -0
  49. package/lib/github/tree.js +162 -0
  50. package/lib/landing_session.js +506 -0
  51. package/lib/links.js +123 -0
  52. package/lib/mergeable_state.js +3 -0
  53. package/lib/metadata_gen.js +61 -0
  54. package/lib/pr_checker.js +605 -0
  55. package/lib/pr_data.js +115 -0
  56. package/lib/pr_summary.js +62 -0
  57. package/lib/prepare_release.js +772 -0
  58. package/lib/prepare_security.js +117 -0
  59. package/lib/proxy.js +21 -0
  60. package/lib/queries/DefaultBranchRef.gql +8 -0
  61. package/lib/queries/LastCommit.gql +16 -0
  62. package/lib/queries/PR.gql +37 -0
  63. package/lib/queries/PRComments.gql +27 -0
  64. package/lib/queries/PRCommits.gql +45 -0
  65. package/lib/queries/PRs.gql +25 -0
  66. package/lib/queries/Reviews.gql +23 -0
  67. package/lib/queries/SearchIssue.gql +51 -0
  68. package/lib/queries/Team.gql +22 -0
  69. package/lib/queries/TreeEntries.gql +12 -0
  70. package/lib/queries/VotePRInfo.gql +28 -0
  71. package/lib/release/utils.js +53 -0
  72. package/lib/request.js +185 -0
  73. package/lib/review_state.js +5 -0
  74. package/lib/reviews.js +178 -0
  75. package/lib/run.js +106 -0
  76. package/lib/session.js +415 -0
  77. package/lib/sync_session.js +15 -0
  78. package/lib/team_info.js +95 -0
  79. package/lib/update-v8/applyNodeChanges.js +49 -0
  80. package/lib/update-v8/backport.js +258 -0
  81. package/lib/update-v8/commitUpdate.js +26 -0
  82. package/lib/update-v8/common.js +35 -0
  83. package/lib/update-v8/constants.js +86 -0
  84. package/lib/update-v8/index.js +56 -0
  85. package/lib/update-v8/majorUpdate.js +171 -0
  86. package/lib/update-v8/minorUpdate.js +105 -0
  87. package/lib/update-v8/updateMaintainingDependencies.js +34 -0
  88. package/lib/update-v8/updateV8Clone.js +53 -0
  89. package/lib/update-v8/updateVersionNumbers.js +122 -0
  90. package/lib/update-v8/util.js +62 -0
  91. package/lib/user.js +4 -0
  92. package/lib/user_status.js +5 -0
  93. package/lib/utils.js +66 -0
  94. package/lib/verbosity.js +26 -0
  95. package/lib/voting_session.js +136 -0
  96. package/lib/wpt/index.js +243 -0
  97. package/lib/wpt/templates/README.md +16 -0
  98. package/package.json +69 -0
package/lib/figures.js ADDED
@@ -0,0 +1,7 @@
1
+ import chalk from 'chalk';
2
+ import figures from 'figures';
3
+
4
+ export const warning = chalk.yellow(figures.warning);
5
+ export const error = chalk.red(figures.cross);
6
+ export const info = chalk.blue(figures.info);
7
+ export const success = chalk.green(figures.tick);
package/lib/file.js ADDED
@@ -0,0 +1,43 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ export function appendFile(file, content) {
5
+ const parts = path.parse(file);
6
+ if (!fs.existsSync(parts.dir)) {
7
+ fs.mkdirSync(parts.dir, { recursive: true });
8
+ }
9
+ // TODO(joyeecheung): what if the file is a dir?
10
+ fs.appendFileSync(file, content, 'utf8');
11
+ };
12
+
13
+ export function writeFile(file, content) {
14
+ const parts = path.parse(file);
15
+ if (parts.dir !== '' && !fs.existsSync(parts.dir)) {
16
+ fs.mkdirSync(parts.dir, { recursive: true });
17
+ }
18
+ // TODO(joyeecheung): what if the file is a dir?
19
+ fs.writeFileSync(file, content, 'utf8');
20
+ };
21
+
22
+ export function writeJson(file, obj) {
23
+ writeFile(file, `${JSON.stringify(obj, null, 2)}\n`);
24
+ };
25
+
26
+ export function readFile(file) {
27
+ if (fs.existsSync(file)) {
28
+ return fs.readFileSync(file, 'utf8');
29
+ }
30
+ return '';
31
+ };
32
+
33
+ export function readJson(file) {
34
+ const content = readFile(file);
35
+ if (content) {
36
+ return JSON.parse(content);
37
+ }
38
+ return {};
39
+ };
40
+
41
+ export function removeDirectory(directory) {
42
+ return fs.promises.rm(directory, { recursive: true, force: true });
43
+ }
@@ -0,0 +1,97 @@
1
+ ## Planning
2
+
3
+ * [X] Open an [issue](https://github.com/nodejs-private/node-private) titled
4
+ `Next Security Release`, and put this checklist in the description.
5
+
6
+ * [ ] Get agreement on the list of vulnerabilities to be addressed:
7
+ %REPORTS%
8
+
9
+ * [ ] PR release announcements in [private](https://github.com/nodejs-private/nodejs.org-private):
10
+ * [ ] pre-release: %PRE_RELEASE_PRIV%
11
+ * [ ] post-release: %POS_RELEASE_PRIV%
12
+ * List vulnerabilities in order of descending severity
13
+ * Ask the HackerOne reporter if they would like to be credited on the
14
+ security release blog page
15
+
16
+ * [ ] Get agreement on the planned date for the release: %RELEASE_DATE%
17
+
18
+ * [ ] Get release team volunteers for all affected lines:
19
+ %AFFECTED_LINES%
20
+
21
+ ## Announcement (one week in advance of the planned release)
22
+
23
+ * [ ] Verify that GitHub Actions are working as normal: <https://www.githubstatus.com/>.
24
+
25
+ * [ ] Check that all vulnerabilities are ready for release integration:
26
+ * PRs against all affected release lines or cherry-pick clean
27
+ * Approved
28
+ * (optional) Approved by the reporter
29
+ * Build and send the binary to the reporter according to its architecture
30
+ and ask for a review. This step is important to avoid insufficient fixes
31
+ between Security Releases.
32
+ * Have CVEs
33
+ * Make sure that dependent libraries have CVEs for their issues. We should
34
+ only create CVEs for vulnerabilities in Node.js itself. This is to avoid
35
+ having duplicate CVEs for the same vulnerability.
36
+ * Described in the pre/post announcements
37
+
38
+ * [ ] Pre-release announcement to nodejs.org blog: TBD
39
+ (Re-PR the pre-approved branch from nodejs-private/nodejs.org-private to
40
+ nodejs/nodejs.org)
41
+
42
+ * [ ] Pre-release announcement [email](https://groups.google.com/forum/#!forum/nodejs-sec): TBD
43
+ * Subject: `Node.js security updates for all active release lines, Month Year`
44
+
45
+ * [ ] CC `oss-security@lists.openwall.com` on pre-release
46
+ * [ ] Forward the email you receive to `oss-security@lists.openwall.com`.
47
+
48
+ * [ ] Create a new issue in [nodejs/tweet](https://github.com/nodejs/tweet/issues)
49
+
50
+ * [ ] Request releaser(s) to start integrating the PRs to be released.
51
+
52
+ * [ ] Notify [docker-node](https://github.com/nodejs/docker-node/issues) of upcoming security release date: TBD
53
+
54
+ * [ ] Notify build-wg of upcoming security release date by opening an issue
55
+ in [nodejs/build](https://github.com/nodejs/build/issues) to request WG members are available to fix any CI issues: TBD
56
+
57
+ ## Release day
58
+
59
+ * [ ] [Lock CI](https://github.com/nodejs/build/blob/HEAD/doc/jenkins-guide.md#before-the-release)
60
+
61
+ * [ ] The releaser(s) run the release process to completion.
62
+
63
+ * [ ] [Unlock CI](https://github.com/nodejs/build/blob/HEAD/doc/jenkins-guide.md#after-the-release)
64
+
65
+ * [ ] Post-release announcement to Nodejs.org blog: https://github.com/nodejs/nodejs.org/pull/5447
66
+ * (Re-PR the pre-approved branch from nodejs-private/nodejs.org-private to
67
+ nodejs/nodejs.org)
68
+
69
+ * [ ] Post-release announcement in reply email: TBD
70
+
71
+ * [ ] Create a new issue in nodejs/tweet
72
+
73
+ * [ ] Comment in [docker-node][] issue that release is ready for integration.
74
+ The docker-node team will build and release docker image updates.
75
+
76
+ * [ ] For every H1 report resolved:
77
+ * Close as Resolved
78
+ * Request Disclosure
79
+ * Request publication of H1 CVE requests
80
+ * (Check that the "Version Fixed" field in the CVE is correct, and provide
81
+ links to the release blogs in the "Public Reference" section)
82
+
83
+ * [ ] PR machine-readable JSON descriptions of the vulnerabilities to the
84
+ [core](https://github.com/nodejs/security-wg/tree/HEAD/vuln/core)
85
+ vulnerability DB. https://github.com/nodejs/security-wg/pull/1029
86
+ * For each vulnerability add a `#.json` file, one can copy an existing
87
+ [json](https://github.com/nodejs/security-wg/blob/0d82062d917cb9ddab88f910559469b2b13812bf/vuln/core/78.json)
88
+ file, and increment the latest created file number and use that as the name
89
+ of the new file to be added. For example, `79.json`.
90
+
91
+ * [ ] Close this issue
92
+
93
+ * [ ] Make sure the PRs for the vulnerabilities are closed.
94
+
95
+ * [ ] PR in that you stewarded the release in
96
+ [Security release stewards](https://github.com/nodejs/node/blob/HEAD/doc/contributing/security-release-process.md#security-release-stewards).
97
+ If necessary add the next rotation of the steward rotation.
@@ -0,0 +1,162 @@
1
+ import { flatten } from '../utils.js';
2
+
3
+ const COMMIT_QUERY = 'LastCommit';
4
+ const TREE_QUERY = 'TreeEntries';
5
+
6
+ export default class GitHubTree {
7
+ constructor(cli, request, argv) {
8
+ this.cli = cli;
9
+ this.request = request;
10
+
11
+ this.owner = argv.owner;
12
+ this.repo = argv.repo;
13
+ this.branch = argv.branch;
14
+
15
+ if (argv.path.endsWith('/')) {
16
+ this.path = argv.path.slice(0, argv.path - 1);
17
+ } else {
18
+ this.path = argv.path;
19
+ }
20
+
21
+ this.lastCommit = argv.commit || null;
22
+ }
23
+
24
+ get repoUrl() {
25
+ const base = 'https://github.com';
26
+ const { owner, repo } = this;
27
+ return `${base}/${owner}/${repo}`;
28
+ }
29
+
30
+ async _getLastCommit() {
31
+ const { request, owner, repo, branch, path } = this;
32
+ const data = await request.gql(COMMIT_QUERY, {
33
+ owner,
34
+ repo,
35
+ branch,
36
+ path
37
+ });
38
+ return data.repository.ref.target.history.nodes[0].oid;
39
+ }
40
+
41
+ /**
42
+ * @returns {string} the hash of the last commit in the tree
43
+ */
44
+ async getLastCommit() {
45
+ if (this.lastCommit) {
46
+ return this.lastCommit;
47
+ }
48
+ this.lastCommit = await this._getLastCommit();
49
+ return this.lastCommit;
50
+ }
51
+
52
+ getPermanentUrl() {
53
+ if (!this.lastCommit) {
54
+ throw new Error('Call await tree.getLastCommit() first');
55
+ }
56
+ const commit = this.lastCommit;
57
+ return `${this.repoUrl}/tree/${commit.slice(0, 10)}/${this.path}`;
58
+ }
59
+
60
+ async buffer(assetPath) {
61
+ await this.getLastCommit();
62
+ const url = this.getAssetUrl(assetPath);
63
+ return this.request.buffer(url);
64
+ }
65
+
66
+ /**
67
+ * Get the url of an asset. If the assetPath starts with `/`,
68
+ * it will be treated as an absolute path and the
69
+ * the path of the tree will not be prefixed in the url.
70
+ * @param {string} assetPath
71
+ */
72
+ getAssetUrl(assetPath) {
73
+ if (!this.lastCommit) {
74
+ throw new Error('Call await tree.getLastCommit() first');
75
+ }
76
+ const base = 'https://raw.githubusercontent.com';
77
+ const { owner, repo, lastCommit, path } = this;
78
+ const prefix = `${base}/${owner}/${repo}/${lastCommit}`;
79
+ if (assetPath.startsWith('/')) { // absolute
80
+ return `${prefix}/${assetPath}`;
81
+ } else {
82
+ return `${prefix}/${path}/${assetPath}`;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Get a list of files inside the tree (recursively).
88
+ * The returned file names will be relative to the path of the tree,
89
+ * e.g. `url/resources/data.json` in a tree with `url` as path
90
+ * will be `resources/data.json`
91
+ *
92
+ * @returns {{name: string, type: string}[]}
93
+ */
94
+ async getFiles(path) {
95
+ if (!path) {
96
+ path = this.path;
97
+ }
98
+ let lastCommit = this.lastCommit;
99
+ if (!lastCommit) {
100
+ lastCommit = await this.getLastCommit();
101
+ }
102
+ const { request, owner, repo } = this;
103
+
104
+ const expression = `${lastCommit}:${path}`;
105
+ this.cli.updateSpinner(`Querying files for ${path}`);
106
+ const data = await request.gql(TREE_QUERY, {
107
+ owner,
108
+ repo,
109
+ expression
110
+ });
111
+ const files = data.repository.object.entries;
112
+
113
+ const dirs = files.filter((file) => file.type === 'tree');
114
+ const nondirs = files.filter((file) => file.type !== 'tree');
115
+
116
+ if (dirs.length) {
117
+ const expanded = await Promise.all(
118
+ dirs.map((dir) =>
119
+ this.getFiles(`${path}/${dir.name}`)
120
+ .then(files => files.map(
121
+ ({ name, type }) => ({ name: `${dir.name}/${name}`, type })
122
+ ))
123
+ )
124
+ );
125
+ return nondirs.concat(flatten(expanded));
126
+ } else {
127
+ return nondirs;
128
+ }
129
+ }
130
+
131
+ getCacheKey() {
132
+ const { branch, owner, repo, path } = this;
133
+ return `tree-${owner}-${repo}-${branch}-${clean(path)}`;
134
+ }
135
+ }
136
+
137
+ function clean(path) {
138
+ if (!path) {
139
+ return '';
140
+ }
141
+ return path.replace('/', '-');
142
+ }
143
+
144
+ // Uncomment this when testing to avoid extra network costs
145
+ // import Cache from '../cache.js';
146
+ // const treeCache = new Cache();
147
+
148
+ // treeCache.wrap(GitHubTree, {
149
+ // _getLastCommit() {
150
+ // return { key: `${this.getCacheKey()}-commit`, ext: '.json' };
151
+ // },
152
+ // getFiles(path) {
153
+ // return {
154
+ // key: `${this.getCacheKey()}-${clean(path)}-files`,
155
+ // ext: '.json'
156
+ // };
157
+ // },
158
+ // text(assetPath) {
159
+ // return { key: `${this.getCacheKey()}-${clean(assetPath)}`, ext: '.txt' };
160
+ // }
161
+ // });
162
+ // treeCache.enable();