@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
@@ -0,0 +1,72 @@
1
+ import { fold } from '../ci_utils.js';
2
+ import { Job } from './job.js';
3
+
4
+ export class BenchmarkRun extends Job {
5
+ constructor(cli, request, id) {
6
+ const path = `job/benchmark-node-micro-benchmarks/${id}/`;
7
+ super(cli, request, path);
8
+
9
+ this.results = '';
10
+ this.significantResults = '';
11
+ }
12
+
13
+ async getResults() {
14
+ const { path, cli } = this;
15
+ cli.startSpinner(`Querying results of ${path}`);
16
+ const text = await this.getConsoleText();
17
+ const index = text.indexOf('improvement');
18
+ if (index === -1) {
19
+ throw new Error('Not finished');
20
+ }
21
+ const breakIndex = text.lastIndexOf('\n', index);
22
+ const results = text.slice(breakIndex + 1)
23
+ .replace(/\nSending e-mails[\s\S]+/mg, '');
24
+ this.results = results;
25
+ cli.stopSpinner('Data downloaded');
26
+ this.significantResults = this.getSignificantResults(results);
27
+ return results;
28
+ }
29
+
30
+ getSignificantResults(data) {
31
+ const lines = data.split('\n');
32
+ const significant = lines.filter(line => line.indexOf('*') !== -1);
33
+ return significant.slice(0, -3).join('\n');
34
+ }
35
+
36
+ display() {
37
+ const { cli, results, significantResults } = this;
38
+ cli.log(results);
39
+ cli.separator('significant results');
40
+ cli.log(significantResults);
41
+ }
42
+
43
+ formatAsMarkdown() {
44
+ const { results, significantResults } = this;
45
+ const output = (fold('Benchmark results', results) + '\n\n' +
46
+ fold('Significant impact', significantResults) + '\n');
47
+ return output;
48
+ }
49
+
50
+ formatAsJson() {
51
+ const results = this.significantResults.split('\n').slice(1);
52
+ const json = [];
53
+ for (const line of results) {
54
+ const star = line.indexOf('*');
55
+ const name = line.slice(0, star).trim();
56
+ const [file, ...config] = name.split(' ');
57
+ const confidence = line.match(/(\*+)/)[1];
58
+ const lastStar = line.lastIndexOf('*');
59
+ const [improvement, ...accuracy] =
60
+ line.slice(lastStar + 1).split(/\s*%/).map(i => i.trim() + '%');
61
+ accuracy.pop(); // remove the last empty item
62
+ json.push({
63
+ file,
64
+ config,
65
+ confidence,
66
+ improvement,
67
+ accuracy
68
+ });
69
+ }
70
+ return json;
71
+ }
72
+ }
@@ -0,0 +1,194 @@
1
+ import { flatten } from '../../utils.js';
2
+ import { getNodeName, pad } from '../ci_utils.js';
3
+ import {
4
+ CITGM_MAIN_TREE,
5
+ CITGM_REPORT_TREE
6
+ } from '../jenkins_constants.js';
7
+ import CIFailureParser from '../ci_failure_parser.js';
8
+ import { TestBuild } from './test_build.js';
9
+
10
+ const {
11
+ FAILURE_TYPES: { NCU_FAILURE },
12
+ FAILURE_CONSTRUCTORS: {
13
+ [NCU_FAILURE]: NCUFailure
14
+ }
15
+ } = CIFailureParser;
16
+
17
+ export class CITGMBuild extends TestBuild {
18
+ constructor(cli, request, job) {
19
+ const { jobid, noBuild } = job;
20
+ const path = noBuild
21
+ ? `job/citgm-smoker-nobuild/${jobid}/`
22
+ : `job/citgm-smoker/${jobid}/`;
23
+
24
+ const tree = CITGM_MAIN_TREE;
25
+
26
+ super(cli, request, path, tree);
27
+
28
+ this.id = jobid;
29
+ this.noBuild = noBuild;
30
+ this.failures = [];
31
+ }
32
+
33
+ async getResults() {
34
+ const { apiUrl, cli } = this;
35
+
36
+ let headerData;
37
+ try {
38
+ headerData = await this.getBuildData('Summary');
39
+ } catch (err) {
40
+ cli.stopSpinner('Failed to download Summary data',
41
+ cli.SPINNER_STATUS.FAILED);
42
+ this.failures.push(new NCUFailure({ url: this.apiUrl }, err.message));
43
+ return this.failures;
44
+ }
45
+ const { result } = headerData;
46
+
47
+ this.setBuildData(headerData);
48
+
49
+ // CITGM jobs store results in a different location than
50
+ // they do summary data, so we need to update the endpoint
51
+ // and issue a second API call in order to fetch result data.
52
+ this.tree = CITGM_REPORT_TREE;
53
+ this.updatePath(true);
54
+ let resultData;
55
+ try {
56
+ resultData = await this.getBuildData('Results');
57
+ } catch (err) {
58
+ cli.stopSpinner('Failed to download Results data',
59
+ cli.SPINNER_STATUS.FAILED);
60
+ this.failures.push(new NCUFailure({ url: apiUrl }, err.message));
61
+ return this.failures;
62
+ }
63
+
64
+ this.results = this.parseResults(resultData);
65
+
66
+ // Update id again so that it correctly displays in Summary output.
67
+ this.updatePath(false);
68
+
69
+ return { result };
70
+ }
71
+
72
+ parseResults(data) {
73
+ const { childReports, totalCount, skipCount, failCount } = data;
74
+ const results = { all: {}, failures: {}, statistics: {} };
75
+ const failureStatuses = ['FAILED', 'REGRESSION'];
76
+
77
+ const passCount = totalCount - failCount - skipCount;
78
+ results.statistics.passed = passCount;
79
+ results.statistics.total = totalCount;
80
+ results.statistics.skipped = skipCount;
81
+ results.statistics.failed = failCount;
82
+
83
+ childReports.forEach(platform => {
84
+ const cases = flatten(platform.result.suites[0].cases);
85
+ const url = platform.child.url;
86
+ const nodeName = getNodeName(url);
87
+
88
+ results.all[nodeName] = { url, modules: cases };
89
+
90
+ const failedModules = cases.filter(c => {
91
+ return failureStatuses.includes(c.status);
92
+ });
93
+
94
+ results.failures[nodeName] = { url, modules: failedModules };
95
+ });
96
+
97
+ return results;
98
+ }
99
+
100
+ updatePath(testReport) {
101
+ const { id, noBuild } = this;
102
+ if (testReport) {
103
+ this.path = noBuild
104
+ ? `job/citgm-smoker-nobuild/${id}/testReport/`
105
+ : `job/citgm-smoker/${id}/testReport/`;
106
+ } else {
107
+ this.path = noBuild
108
+ ? `job/citgm-smoker-nobuild/${id}/`
109
+ : `job/citgm-smoker/${id}/`;
110
+ }
111
+ }
112
+
113
+ display() {
114
+ const { failures } = this;
115
+
116
+ if (failures.length) {
117
+ for (const failure of failures) {
118
+ this.displayFailure(failure);
119
+ }
120
+ return;
121
+ }
122
+
123
+ this.displayHeader();
124
+ this.displayBuilds();
125
+ }
126
+
127
+ displayBuilds() {
128
+ const { cli, results } = this;
129
+ const { failed, skipped, passed, total } = results.statistics;
130
+
131
+ cli.separator('Statistics');
132
+ console.table({
133
+ Failed: failed,
134
+ Skipped: skipped,
135
+ Passed: passed,
136
+ Total: total
137
+ });
138
+
139
+ cli.separator('Failures');
140
+ const output = {};
141
+ for (const platform in results.failures) {
142
+ const modules = results.failures[platform].modules;
143
+ const failures = modules.map(f => f.name);
144
+
145
+ output[platform] = failures;
146
+ }
147
+
148
+ console.table(output);
149
+ }
150
+
151
+ formatAsJson() {
152
+ const { jobUrl, results, sourceURL } = this;
153
+
154
+ const result = {
155
+ source: sourceURL,
156
+ upstream: jobUrl,
157
+ ...results.statistics,
158
+ ...results.failures
159
+ };
160
+
161
+ return JSON.parse(JSON.stringify(result));
162
+ }
163
+
164
+ formatAsMarkdown() {
165
+ const { jobUrl, result, results, id } = this;
166
+
167
+ let output = `# CITGM Data for [${id}](${jobUrl})\n\n`;
168
+
169
+ const { failed, skipped, passed, total } = results.statistics;
170
+
171
+ output += `## Statistics for job [${id}](${jobUrl})\n\n`;
172
+ output += '| FAILED | SKIPPED | PASSED | TOTAL |\n';
173
+ output += '| -------- | --------- | -------- | ------- |\n';
174
+ output += `| ${pad(failed, 8)} | ${pad(skipped, 9)} |`;
175
+ output += ` ${pad(passed, 8)} | ${pad(total, 7)} |\n\n`;
176
+
177
+ if (result === 'success') {
178
+ output += `Job [${id}](${jobUrl}) is green.`;
179
+ return output;
180
+ }
181
+
182
+ output += `## Failures in job [${id}](${jobUrl})\n\n`;
183
+ for (const failure in results.failures) {
184
+ const data = results.failures[failure];
185
+ output += `### [${failure}](${data.url})\n\n`;
186
+
187
+ const failures = data.modules.map(f => `* ${f.name}`);
188
+ const items = failures.length > 0 ? `${failures.join('\n')}` : 'None.';
189
+ output += `${items}\n\n`;
190
+ }
191
+
192
+ return output;
193
+ }
194
+ }
@@ -0,0 +1,174 @@
1
+ import { statusType } from '../ci_utils.js';
2
+ import { CITGMBuild } from './citgm_build.js';
3
+
4
+ export class CITGMComparisonBuild {
5
+ constructor(cli, request, job) {
6
+ const { jobid, jobid2, noBuild } = job;
7
+
8
+ const baseBuild = new CITGMBuild(cli, request, { jobid, noBuild });
9
+
10
+ // noBuild in a comparison build only applies to the base build.
11
+ const comparisonBuild = new CITGMBuild(cli, request, {
12
+ jobid: jobid2,
13
+ noBuild: false
14
+ });
15
+
16
+ this.cli = cli;
17
+ this.builds = { baseBuild, comparisonBuild };
18
+ this.results = {};
19
+ this.failures = { baseBuild: [], comparisonBuild: [] };
20
+ }
21
+
22
+ async getResults() {
23
+ const { builds } = this;
24
+ const { baseBuild, comparisonBuild } = builds;
25
+
26
+ // Result in a comparison context reflects
27
+ // whether or not there were failures in
28
+ // comparisonBuild not present in baseBuild,
29
+ // e.g if there were new failures.
30
+ let result = statusType.SUCCESS;
31
+
32
+ await baseBuild.getResults();
33
+ await comparisonBuild.getResults();
34
+
35
+ if (baseBuild.failures.length || comparisonBuild.failures.length) {
36
+ this.failures.baseBuild =
37
+ this.failures.baseBuild.concat(baseBuild.failures);
38
+ this.failures.comparisonBuild =
39
+ this.failures.comparisonBuild.concat(comparisonBuild.failures);
40
+ return;
41
+ }
42
+
43
+ const { failures: baseFailures } = baseBuild.results;
44
+ const { failures: comparisonFailures } = comparisonBuild.results;
45
+
46
+ const failures = {};
47
+ for (const platform in comparisonFailures) {
48
+ // Account for no failure on this platform, or different platform.
49
+ if (!Object.prototype.hasOwnProperty.call(baseFailures, platform)) {
50
+ failures[platform] = [];
51
+ continue;
52
+ }
53
+
54
+ const baseModules = baseFailures[platform].modules.map(f => {
55
+ return f.name;
56
+ });
57
+ const comparisonModules = comparisonFailures[platform].modules.map(f => {
58
+ return f.name;
59
+ });
60
+
61
+ // Filter for every failed module in the comparison job module set
62
+ // that is not present in the failure set for the base job module set.
63
+ const newFailures = comparisonModules.filter(f => {
64
+ return !baseModules.includes(f);
65
+ });
66
+ if (newFailures.length !== 0) {
67
+ result = statusType.FAILURE;
68
+ }
69
+
70
+ failures[platform] = newFailures;
71
+ }
72
+
73
+ this.results.failures = failures;
74
+ this.result = result;
75
+
76
+ return result;
77
+ }
78
+
79
+ display() {
80
+ const { builds, failures } = this;
81
+
82
+ if (failures.baseBuild.length || failures.comparisonBuild.length) {
83
+ for (const failure of failures.baseBuild) {
84
+ builds.baseBuild.displayFailure(failure);
85
+ }
86
+ for (const failure of failures.comparisonBuild) {
87
+ builds.comparisonBuild.displayFailure(failure);
88
+ }
89
+ return;
90
+ }
91
+
92
+ // Display header for both CITGM runs.
93
+ builds.baseBuild.displayHeader();
94
+ builds.comparisonBuild.displayHeader();
95
+
96
+ this.displayBuilds();
97
+ }
98
+
99
+ displayBuilds() {
100
+ const { builds, cli, results, result } = this;
101
+
102
+ const bID = builds.baseBuild.id;
103
+ const cID = builds.comparisonBuild.id;
104
+
105
+ cli.separator('Results');
106
+
107
+ if (result === statusType.SUCCESS) {
108
+ cli.log('\n\n');
109
+ const str = `No new failures in ${cID} compared to ${bID}`;
110
+ cli.log(`${statusType.SUCCESS}: ${str}\n\n`);
111
+ return;
112
+ }
113
+
114
+ const output = {};
115
+ let totalFailures = 0;
116
+ for (const platform in results.failures) {
117
+ const failures = results.failures[platform];
118
+ totalFailures += failures.length;
119
+
120
+ output[platform] = failures;
121
+ }
122
+
123
+ cli.log('\n\n');
124
+ const str = `${totalFailures} failures in ${cID} not present in ${bID}`;
125
+ cli.log(`${statusType.FAILURE}: ${str}\n\n`);
126
+ console.table(output);
127
+ }
128
+
129
+ formatAsJson() {
130
+ const { builds, results } = this;
131
+ const { baseBuild, comparisonBuild } = builds;
132
+
133
+ const result = {
134
+ baseBuild: {
135
+ source: baseBuild.sourceURL,
136
+ upstream: comparisonBuild.jobUrl
137
+ },
138
+ comparisonBuild: {
139
+ source: comparisonBuild.sourceURL,
140
+ upstream: baseBuild.jobUrl
141
+ },
142
+ ...results.failures
143
+ };
144
+
145
+ return JSON.parse(JSON.stringify(result));
146
+ }
147
+
148
+ formatAsMarkdown() {
149
+ const { builds, result, results } = this;
150
+ const { baseBuild, comparisonBuild } = builds;
151
+
152
+ const bLink = `[#${baseBuild.id}](${baseBuild.jobUrl})`;
153
+ const cLink = `[#${comparisonBuild.id}](${comparisonBuild.jobUrl})`;
154
+
155
+ let output = `# CITGM Data for ${bLink} - ${cLink}\n\n`;
156
+
157
+ if (result === 'success') {
158
+ const bID = baseBuild.id;
159
+ const cID = comparisonBuild.id;
160
+ output += `No new failures in ${cID} compared to ${bID}`;
161
+ return output;
162
+ }
163
+
164
+ output += `## New Failures in job ${cLink}\n\n`;
165
+ for (const failure in results.failures) {
166
+ const data = results.failures[failure];
167
+ output += `### ${failure}\n\n`;
168
+
169
+ const failures = data.map(f => `* ${f}`);
170
+ output += failures.length ? `${failures.join('\n')}\n\n` : 'None.\n\n';
171
+ }
172
+ return output;
173
+ }
174
+ }
@@ -0,0 +1,112 @@
1
+ import { flatten } from '../../utils.js';
2
+ import { statusType } from '../ci_utils.js';
3
+ import { COMMIT_TREE } from '../jenkins_constants.js';
4
+ import CIFailureParser from '../ci_failure_parser.js';
5
+ import { TestBuild } from './test_build.js';
6
+ import { FannedBuild } from './fanned_build.js';
7
+ import { LinterBuild } from './linter_build.js';
8
+ import { NormalBuild } from './normal_build.js';
9
+ import { TestRun } from './test_run.js';
10
+
11
+ const {
12
+ FAILURE_TYPES: {
13
+ BUILD_FAILURE,
14
+ NCU_FAILURE
15
+ },
16
+ FAILURE_CONSTRUCTORS: {
17
+ [BUILD_FAILURE]: BuildFailure,
18
+ [NCU_FAILURE]: NCUFailure
19
+ }
20
+ } = CIFailureParser;
21
+
22
+ export class CommitBuild extends TestBuild {
23
+ constructor(cli, request, id) {
24
+ const path = `job/node-test-commit/${id}/`;
25
+ const tree = COMMIT_TREE;
26
+ super(cli, request, path, tree);
27
+ }
28
+
29
+ getBuilds({ result, subBuilds }) {
30
+ if (result === statusType.SUCCESS) {
31
+ const builds = this.builds = {
32
+ failed: [], aborted: [], pending: [], unstable: []
33
+ };
34
+ return { result: statusType.SUCCESS, builds };
35
+ }
36
+
37
+ const failed = subBuilds.filter(build => {
38
+ return build.result === statusType.FAILURE;
39
+ });
40
+ const aborted = subBuilds.filter(build => {
41
+ return build.result === statusType.ABORTED;
42
+ });
43
+ const pending = subBuilds.filter(build => {
44
+ return build.result === null;
45
+ });
46
+ const unstable = subBuilds.filter(build => {
47
+ return build.result === statusType.UNSTABLE;
48
+ });
49
+
50
+ // build: { buildNumber, jobName, result, url }
51
+ const builds = this.builds = { failed, aborted, pending, unstable };
52
+ return { result, builds };
53
+ }
54
+
55
+ // Get the failures and their reasons of this build
56
+ async getResults(data) {
57
+ const { path, cli, request } = this;
58
+
59
+ if (!data) {
60
+ try {
61
+ data = await this.getBuildData();
62
+ } catch (err) {
63
+ this.failures = [
64
+ new NCUFailure({ url: this.apiUrl }, err.message)
65
+ ];
66
+ return this.failures;
67
+ }
68
+ }
69
+ this.setBuildData(data);
70
+ // No builds at all
71
+ if (data.result === statusType.FAILURE && !data.subBuilds.length) {
72
+ const failure = new BuildFailure(this, 'Failed to trigger sub builds');
73
+ this.failures = [failure];
74
+ return {
75
+ result: data.result,
76
+ builds: { failed: [], aborted: [], pending: [], unstable: [] },
77
+ failures: this.failures
78
+ };
79
+ }
80
+
81
+ const { result, builds } = this.getBuilds(data);
82
+
83
+ if (result !== statusType.FAILURE) {
84
+ return { result, builds, failures: [] };
85
+ }
86
+
87
+ if (!builds.failed.length) {
88
+ const failures = await this.parseConsoleText();
89
+ return { result, builds, failures };
90
+ }
91
+
92
+ cli.startSpinner(`Querying failures of ${path}`);
93
+ const promises = builds.failed.map(({ jobName, buildNumber, url }) => {
94
+ if (jobName.includes('fanned')) {
95
+ const cause = this.getCause(data.actions);
96
+ const isResumed = cause && cause._class.includes('ResumeCause');
97
+ return new FannedBuild(cli, request, jobName, buildNumber, isResumed)
98
+ .getResults();
99
+ } else if (jobName.includes('linter')) {
100
+ return new LinterBuild(cli, request, jobName, buildNumber).getResults();
101
+ } else if (jobName.includes('freestyle')) {
102
+ return new TestRun(cli, request, url).getResults();
103
+ }
104
+ return new NormalBuild(cli, request, jobName, buildNumber).getResults();
105
+ });
106
+ const rawFailures = await Promise.all(promises);
107
+
108
+ const failures = this.failures = flatten(rawFailures);
109
+ cli.stopSpinner('Data downloaded');
110
+ return { result, failures, builds };
111
+ }
112
+ }
@@ -0,0 +1,24 @@
1
+ import { PR_TREE } from '../jenkins_constants.js';
2
+ import { TestBuild } from './test_build.js';
3
+
4
+ export class DailyBuild extends TestBuild {
5
+ constructor(cli, request, id) {
6
+ const path = `job/node-daily-master/${id}/`;
7
+ const tree = PR_TREE;
8
+ super(cli, request, path, tree);
9
+
10
+ this.commitBuild = null;
11
+ }
12
+
13
+ formatAsMarkdown() {
14
+ if (!this.commitBuild) {
15
+ let result = 'Failed to trigger node-daily-master';
16
+ if (this.builtOn) {
17
+ result += ` on ${this.builtOn}`;
18
+ }
19
+ result += `\n\nURL: ${this.jobUrl}`;
20
+ return result;
21
+ }
22
+ return super.formatAsMarkdown();
23
+ }
24
+ }
@@ -0,0 +1,87 @@
1
+ import { statusType } from '../ci_utils.js';
2
+ import { flatten } from '../../utils.js';
3
+ import { FANNED_TREE } from '../jenkins_constants.js';
4
+ import CIFailureParser from '../ci_failure_parser.js';
5
+ import { Job } from './job.js';
6
+ import { NormalBuild } from './normal_build.js';
7
+
8
+ const {
9
+ FAILURE_TYPES: {
10
+ BUILD_FAILURE,
11
+ NCU_FAILURE,
12
+ GIT_FAILURE,
13
+ RESUME_FAILURE
14
+ },
15
+ FAILURE_CONSTRUCTORS: {
16
+ [BUILD_FAILURE]: BuildFailure,
17
+ [NCU_FAILURE]: NCUFailure,
18
+ [RESUME_FAILURE]: ResumeFailure
19
+ }
20
+ } = CIFailureParser;
21
+
22
+ export class FannedBuild extends Job {
23
+ constructor(cli, request, jobName, id, isResumed) {
24
+ // assert(jobName.includes('fanned'));
25
+ const path = `job/${jobName}/${id}/`;
26
+ const tree = FANNED_TREE;
27
+ super(cli, request, path, tree);
28
+
29
+ this.failures = [];
30
+ this.builtOn = undefined;
31
+ this.isResumed = isResumed;
32
+ }
33
+
34
+ // Get the failures and their reasons of this build
35
+ async getResults() {
36
+ const { cli, request } = this;
37
+
38
+ let data;
39
+ try {
40
+ data = await this.getAPIData();
41
+ } catch (err) {
42
+ this.failures = [
43
+ new NCUFailure({ url: this.apiUrl }, err.message)
44
+ ];
45
+ return this.failures;
46
+ }
47
+ this.builtOn = data.builtOn;
48
+
49
+ if (!data.subBuilds.length) {
50
+ this.failures = [
51
+ new BuildFailure(this, 'Failed to trigger fanned build')
52
+ ];
53
+ return this.failures;
54
+ }
55
+
56
+ const failedPhase = data.subBuilds.find(build => {
57
+ return build.result === statusType.FAILURE;
58
+ });
59
+
60
+ if (!failedPhase) {
61
+ return this.parseConsoleText();
62
+ }
63
+
64
+ const { jobName, buildNumber } = failedPhase;
65
+ const build = new NormalBuild(cli, request, jobName, buildNumber);
66
+ let failures = await build.getResults();
67
+ if (failures !== undefined) {
68
+ failures = flatten(failures);
69
+ }
70
+
71
+ if (this.isResumed) {
72
+ // XXX: if it's a resumed build, we replace the build/git failures
73
+ // with resume failures. Probably just a random guess, though
74
+ for (let i = 0; i < failures.length; ++i) {
75
+ const item = failures[i];
76
+ if (item.type === BUILD_FAILURE || item.type === GIT_FAILURE) {
77
+ failures[i] = new ResumeFailure(
78
+ item,
79
+ `Possible resume failure\n${item.reason}`
80
+ );
81
+ }
82
+ }
83
+ }
84
+ this.failures = failures;
85
+ return this.failures;
86
+ }
87
+ }