@mui/internal-bundle-size-checker 1.0.9-canary.71 → 1.0.9-canary.73
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/build/cli.d.ts +0 -2
- package/build/index.d.ts +1 -2
- package/build/syncPrComment.d.ts +14 -0
- package/package.json +2 -8
- package/src/ciReport.js +7 -1
- package/src/cli.js +49 -156
- package/src/configLoader.js +5 -2
- package/src/index.js +1 -2
- package/src/syncPrComment.js +38 -0
- package/src/types.d.ts +0 -23
- package/src/uploadSnapshot.js +1 -71
- package/build/browser.d.ts +0 -12
- package/build/constants.d.ts +0 -1
- package/build/fetchSnapshot.d.ts +0 -7
- package/build/fetchSnapshotWithFallback.d.ts +0 -11
- package/build/renderMarkdownReport.d.ts +0 -43
- package/build/sizeDiff.d.ts +0 -18
- package/src/browser.js +0 -10
- package/src/constants.js +0 -1
- package/src/fetchSnapshot.js +0 -38
- package/src/fetchSnapshotWithFallback.js +0 -34
- package/src/renderMarkdownReport.js +0 -258
- package/src/renderMarkdownReport.test.js +0 -608
- package/src/sizeDiff.js +0 -169
package/build/cli.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
export type CommandLineArgs = import('./types.js').CommandLineArgs;
|
|
2
2
|
export type NormalizedBundleSizeCheckerConfig = import('./types.js').NormalizedBundleSizeCheckerConfig;
|
|
3
3
|
export type SizeSnapshotEntry = import('./types.js').SizeSnapshotEntry;
|
|
4
|
-
export type ReportCommandArgs = import('./types.js').ReportCommandArgs;
|
|
5
|
-
export type SizeSnapshot = import('./sizeDiff.js').SizeSnapshot;
|
package/build/index.d.ts
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type SyncPrCommentResult = {
|
|
2
|
+
success: boolean;
|
|
3
|
+
skipped?: boolean;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {{ success: boolean, skipped?: boolean }} SyncPrCommentResult
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Syncs a PR comment via the dashboard API.
|
|
10
|
+
* @param {string} repo - Repository in owner/repo format
|
|
11
|
+
* @param {Record<string, object>} sections - Section-specific parameters
|
|
12
|
+
* @returns {Promise<SyncPrCommentResult>}
|
|
13
|
+
*/
|
|
14
|
+
export declare function syncPrComment(repo: string, sections: Record<string, object>): Promise<SyncPrCommentResult>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-bundle-size-checker",
|
|
3
|
-
"version": "1.0.9-canary.
|
|
3
|
+
"version": "1.0.9-canary.73",
|
|
4
4
|
"description": "Bundle size checker for MUI packages.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,18 +21,12 @@
|
|
|
21
21
|
"default": "./src/index.js"
|
|
22
22
|
},
|
|
23
23
|
"./package.json": "./package.json",
|
|
24
|
-
"./browser": {
|
|
25
|
-
"types": "./build/browser.d.ts",
|
|
26
|
-
"default": "./src/browser.js"
|
|
27
|
-
},
|
|
28
24
|
"./ciReport": {
|
|
29
25
|
"types": "./build/ciReport.d.ts",
|
|
30
26
|
"default": "./src/ciReport.js"
|
|
31
27
|
}
|
|
32
28
|
},
|
|
33
29
|
"dependencies": {
|
|
34
|
-
"@aws-sdk/client-s3": "^3.1008.0",
|
|
35
|
-
"@aws-sdk/credential-providers": "^3.1008.0",
|
|
36
30
|
"@octokit/rest": "^22.0.1",
|
|
37
31
|
"chalk": "^5.6.2",
|
|
38
32
|
"env-ci": "^11.2.0",
|
|
@@ -50,7 +44,7 @@
|
|
|
50
44
|
"@types/micromatch": "4.0.10",
|
|
51
45
|
"@types/yargs": "17.0.35"
|
|
52
46
|
},
|
|
53
|
-
"gitSha": "
|
|
47
|
+
"gitSha": "f5e61069f527a1e0e95d5fc71428bcbae92ecb5f",
|
|
54
48
|
"scripts": {
|
|
55
49
|
"build": "tsgo -p tsconfig.build.json",
|
|
56
50
|
"test": "pnpm -w test --project @mui/internal-bundle-size-checker",
|
package/src/ciReport.js
CHANGED
|
@@ -25,7 +25,13 @@ const sizeSnapshotEntrySchema = z.object({
|
|
|
25
25
|
gzip: z.number(),
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
const
|
|
28
|
+
const snapshotMetadataSchema = z.object({
|
|
29
|
+
trackedBundles: z.array(z.string()).optional(),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const sizeSnapshotSchema = z
|
|
33
|
+
.record(z.string(), sizeSnapshotEntrySchema)
|
|
34
|
+
.and(z.object({ _metadata: snapshotMetadataSchema }).partial());
|
|
29
35
|
|
|
30
36
|
export const sizeSnapshotUploadSchema = ciReportUploadSchema(
|
|
31
37
|
'size-snapshot',
|
package/src/cli.js
CHANGED
|
@@ -11,33 +11,14 @@ import { pathToFileURL } from 'node:url';
|
|
|
11
11
|
import chalk from 'chalk';
|
|
12
12
|
import { loadConfig } from './configLoader.js';
|
|
13
13
|
import { uploadSnapshot } from './uploadSnapshot.js';
|
|
14
|
-
import {
|
|
15
|
-
import { octokit } from './github.js';
|
|
16
|
-
import { getCurrentRepoInfo } from './git.js';
|
|
17
|
-
import { notifyPr } from './notifyPr.js';
|
|
18
|
-
import { DASHBOARD_ORIGIN } from './constants.js';
|
|
14
|
+
import { syncPrComment } from './syncPrComment.js';
|
|
19
15
|
|
|
20
16
|
/**
|
|
21
17
|
* @typedef {import('./types.js').CommandLineArgs} CommandLineArgs
|
|
22
18
|
* @typedef {import('./types.js').NormalizedBundleSizeCheckerConfig} NormalizedBundleSizeCheckerConfig
|
|
23
19
|
* @typedef {import('./types.js').SizeSnapshotEntry} SizeSnapshotEntry
|
|
24
|
-
* @typedef {import('./types.js').ReportCommandArgs} ReportCommandArgs
|
|
25
20
|
*/
|
|
26
21
|
|
|
27
|
-
/**
|
|
28
|
-
* @param {string} repo
|
|
29
|
-
* @param {number} prNumber
|
|
30
|
-
* @param {string} bundleSizeInfo
|
|
31
|
-
*/
|
|
32
|
-
function formatComment(repo, prNumber, bundleSizeInfo) {
|
|
33
|
-
return [
|
|
34
|
-
'## Bundle size report',
|
|
35
|
-
bundleSizeInfo,
|
|
36
|
-
'<hr>',
|
|
37
|
-
`Check out the [code infra dashboard](${DASHBOARD_ORIGIN}/repository/${repo}/prs/${prNumber}) for more information about this PR.`,
|
|
38
|
-
].join('\n\n');
|
|
39
|
-
}
|
|
40
|
-
|
|
41
22
|
/**
|
|
42
23
|
*/
|
|
43
24
|
function getCiInfo() {
|
|
@@ -53,10 +34,6 @@ function getCiInfo() {
|
|
|
53
34
|
}
|
|
54
35
|
}
|
|
55
36
|
|
|
56
|
-
/**
|
|
57
|
-
* @typedef {import('./sizeDiff.js').SizeSnapshot} SizeSnapshot
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
37
|
// Default concurrency is set to the number of available CPU cores
|
|
61
38
|
const DEFAULT_CONCURRENCY = os.availableParallelism();
|
|
62
39
|
|
|
@@ -117,98 +94,44 @@ async function getBundleSizes(args, config) {
|
|
|
117
94
|
}
|
|
118
95
|
|
|
119
96
|
/**
|
|
120
|
-
* Posts initial "in progress" PR comment
|
|
97
|
+
* Posts initial "in progress" PR comment via dashboard API.
|
|
98
|
+
* Called for all CI builds — the server resolves the associated PR from
|
|
99
|
+
* OIDC claims. If no PR exists yet (branch pushed before PR created),
|
|
100
|
+
* the server returns a no-op response.
|
|
101
|
+
* @param {NormalizedBundleSizeCheckerConfig} config - The loaded configuration
|
|
121
102
|
* @returns {Promise<void>}
|
|
122
103
|
*/
|
|
123
|
-
async function postInitialPrComment() {
|
|
124
|
-
// /** @type {envCi.CircleCiEnv} */
|
|
104
|
+
async function postInitialPrComment(config) {
|
|
125
105
|
const ciInfo = getCiInfo();
|
|
126
106
|
|
|
127
|
-
if (!ciInfo
|
|
107
|
+
if (!ciInfo) {
|
|
128
108
|
return;
|
|
129
109
|
}
|
|
130
110
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
throw new Error('PR commenting enabled but repository information missing in CI PR build');
|
|
111
|
+
if (!ciInfo.slug) {
|
|
112
|
+
throw new Error('PR commenting enabled but repository information missing in CI build');
|
|
134
113
|
}
|
|
135
114
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const circleBuildUrl = process.env.CIRCLE_BUILD_URL;
|
|
139
|
-
|
|
140
|
-
if (!circleBuildNum || !circleBuildUrl) {
|
|
141
|
-
throw new Error(
|
|
142
|
-
'PR commenting enabled but CircleCI environment variables missing in CI PR build',
|
|
143
|
-
);
|
|
115
|
+
if (!config.upload) {
|
|
116
|
+
throw new Error('PR commenting requires upload configuration to determine the API URL');
|
|
144
117
|
}
|
|
145
118
|
|
|
146
119
|
try {
|
|
147
120
|
// eslint-disable-next-line no-console
|
|
148
|
-
console.log('Posting initial PR comment...');
|
|
149
|
-
|
|
150
|
-
const initialComment = formatComment(
|
|
151
|
-
ciInfo.slug,
|
|
152
|
-
prNumber,
|
|
153
|
-
`Bundle size will be reported once [CircleCI build #${circleBuildNum}](${circleBuildUrl}) finishes.\n\nStatus: 🟠 Processing...`,
|
|
154
|
-
);
|
|
121
|
+
console.log('Posting initial PR comment via dashboard API...');
|
|
155
122
|
|
|
156
|
-
await
|
|
123
|
+
const result = await syncPrComment(ciInfo.slug, { bundleSize: { status: 'pending' } });
|
|
157
124
|
|
|
158
125
|
// eslint-disable-next-line no-console
|
|
159
|
-
console.log(
|
|
126
|
+
console.log(
|
|
127
|
+
result.skipped ? 'No open PR found for this branch, skipping.' : 'Initial PR comment posted.',
|
|
128
|
+
);
|
|
160
129
|
} catch (/** @type {any} */ error) {
|
|
161
130
|
console.error('Failed to post initial PR comment:', error.message);
|
|
162
131
|
// Don't fail the build for comment failures
|
|
163
132
|
}
|
|
164
133
|
}
|
|
165
134
|
|
|
166
|
-
/**
|
|
167
|
-
* Report command handler
|
|
168
|
-
* @param {ReportCommandArgs} argv - Command line arguments
|
|
169
|
-
*/
|
|
170
|
-
async function reportCommand(argv) {
|
|
171
|
-
const { pr, owner: argOwner, repo: argRepo } = argv;
|
|
172
|
-
|
|
173
|
-
// Get current repo info and coerce with provided arguments
|
|
174
|
-
const currentRepo = await getCurrentRepoInfo();
|
|
175
|
-
const owner = argOwner ?? currentRepo.owner;
|
|
176
|
-
const repo = argRepo ?? currentRepo.name;
|
|
177
|
-
|
|
178
|
-
if (typeof pr !== 'number') {
|
|
179
|
-
throw new Error('Invalid pull request number. Please provide a valid --pr option.');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Validate that both owner and repo are available
|
|
183
|
-
if (!owner || !repo) {
|
|
184
|
-
throw new Error(
|
|
185
|
-
'Repository owner and name are required. Please provide --owner and --repo options, or run this command from within a git repository.',
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Fetch PR information
|
|
190
|
-
const { data: prInfo } = await octokit.pulls.get({
|
|
191
|
-
owner,
|
|
192
|
-
repo,
|
|
193
|
-
pull_number: pr,
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
const getMergeBaseFromGithubApi = async (
|
|
197
|
-
/** @type {string} */ base,
|
|
198
|
-
/** @type {string} */ head,
|
|
199
|
-
) => {
|
|
200
|
-
const { data } = await octokit.repos.compareCommits({ owner, repo, base, head });
|
|
201
|
-
return data.merge_base_commit.sha;
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
// Generate and print the markdown report
|
|
205
|
-
const report = await renderMarkdownReport(prInfo, {
|
|
206
|
-
getMergeBase: getMergeBaseFromGithubApi,
|
|
207
|
-
});
|
|
208
|
-
// eslint-disable-next-line no-console
|
|
209
|
-
console.log(report);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
135
|
/**
|
|
213
136
|
* Main runner function
|
|
214
137
|
* @param {CommandLineArgs} argv - Command line arguments
|
|
@@ -222,17 +145,28 @@ async function run(argv) {
|
|
|
222
145
|
|
|
223
146
|
// Post initial PR comment if enabled and in CI environment
|
|
224
147
|
if (config && config.comment) {
|
|
225
|
-
await postInitialPrComment();
|
|
148
|
+
await postInitialPrComment(config);
|
|
226
149
|
}
|
|
227
150
|
|
|
228
151
|
// eslint-disable-next-line no-console
|
|
229
152
|
console.log(`Starting bundle size snapshot creation with ${concurrency} workers...`);
|
|
230
153
|
|
|
231
154
|
const bundleSizes = await getBundleSizes(argv, config);
|
|
155
|
+
// Get tracked bundles from config
|
|
156
|
+
const trackedBundles = config.entrypoints
|
|
157
|
+
.filter((entry) => entry.track === true)
|
|
158
|
+
.map((entry) => entry.id);
|
|
159
|
+
|
|
232
160
|
const sortedBundleSizes = Object.fromEntries(
|
|
233
161
|
bundleSizes.sort((a, b) => a[0].localeCompare(b[0])),
|
|
234
162
|
);
|
|
235
163
|
|
|
164
|
+
// Add metadata with tracked bundles to the snapshot
|
|
165
|
+
if (trackedBundles.length > 0) {
|
|
166
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
167
|
+
sortedBundleSizes._metadata = /** @type {any} */ ({ trackedBundles });
|
|
168
|
+
}
|
|
169
|
+
|
|
236
170
|
// Ensure output directory exists
|
|
237
171
|
await fs.mkdir(path.dirname(snapshotDestPath), { recursive: true });
|
|
238
172
|
await fs.writeFile(snapshotDestPath, JSON.stringify(sortedBundleSizes, null, 2));
|
|
@@ -246,11 +180,7 @@ async function run(argv) {
|
|
|
246
180
|
if (config && config.upload) {
|
|
247
181
|
try {
|
|
248
182
|
// eslint-disable-next-line no-console
|
|
249
|
-
console.log(
|
|
250
|
-
config.upload.legacyUpload
|
|
251
|
-
? 'Uploading bundle size snapshot directly to S3 (legacy)...'
|
|
252
|
-
: `Uploading bundle size snapshot via dashboard API at ${config.upload.apiUrl}...`,
|
|
253
|
-
);
|
|
183
|
+
console.log(`Uploading bundle size snapshot via dashboard API at ${config.upload.apiUrl}...`);
|
|
254
184
|
const { key } = await uploadSnapshot(snapshotDestPath, config.upload);
|
|
255
185
|
// eslint-disable-next-line no-console
|
|
256
186
|
console.log(`Bundle size snapshot uploaded to S3 with key: ${key}`);
|
|
@@ -264,54 +194,40 @@ async function run(argv) {
|
|
|
264
194
|
console.log('No upload configuration provided, skipping upload.');
|
|
265
195
|
}
|
|
266
196
|
|
|
267
|
-
// Post PR comment if enabled and in CI environment
|
|
197
|
+
// Post final PR comment via dashboard API if enabled and in CI environment.
|
|
198
|
+
// The server resolves the associated PR from OIDC claims — if no PR exists
|
|
199
|
+
// for this branch, the server returns a no-op response.
|
|
268
200
|
if (config && config.comment) {
|
|
269
201
|
const ciInfo = getCiInfo();
|
|
270
202
|
|
|
271
|
-
|
|
272
|
-
if (!ciInfo || !ciInfo.isPr) {
|
|
203
|
+
if (!ciInfo) {
|
|
273
204
|
// eslint-disable-next-line no-console
|
|
274
|
-
console.log('Not in a CI
|
|
205
|
+
console.log('Not in a CI environment, skipping PR comment.');
|
|
275
206
|
return;
|
|
276
207
|
}
|
|
277
208
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
throw new Error('PR commenting enabled but repository information missing in CI PR build');
|
|
209
|
+
if (!ciInfo.slug) {
|
|
210
|
+
throw new Error('PR commenting enabled but repository information missing in CI build');
|
|
281
211
|
}
|
|
282
212
|
|
|
283
|
-
|
|
213
|
+
if (!config.upload) {
|
|
214
|
+
throw new Error('PR commenting requires upload configuration to determine the API URL');
|
|
215
|
+
}
|
|
284
216
|
|
|
285
217
|
// eslint-disable-next-line no-console
|
|
286
|
-
console.log('
|
|
287
|
-
|
|
288
|
-
// Get tracked bundles from config
|
|
289
|
-
const trackedBundles = config.entrypoints
|
|
290
|
-
.filter((entry) => entry.track === true)
|
|
291
|
-
.map((entry) => entry.id);
|
|
292
|
-
|
|
293
|
-
// Get PR info for renderMarkdownReport
|
|
294
|
-
const { data: prInfo } = await octokit.pulls.get({
|
|
295
|
-
owner: ciInfo.slug.split('/')[0],
|
|
296
|
-
repo: ciInfo.slug.split('/')[1],
|
|
297
|
-
pull_number: prNumber,
|
|
298
|
-
});
|
|
218
|
+
console.log('Syncing PR comment via dashboard API...');
|
|
299
219
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
220
|
+
const result = await syncPrComment(ciInfo.slug, {
|
|
221
|
+
bundleSize: {
|
|
222
|
+
status: 'complete',
|
|
223
|
+
trackedBundles: trackedBundles.length > 0 ? trackedBundles : undefined,
|
|
224
|
+
},
|
|
303
225
|
});
|
|
304
226
|
|
|
305
|
-
// Post or update PR comment
|
|
306
|
-
await notifyPr(
|
|
307
|
-
ciInfo.slug,
|
|
308
|
-
prNumber,
|
|
309
|
-
'bundle-size-report',
|
|
310
|
-
formatComment(ciInfo.slug, prNumber, report),
|
|
311
|
-
);
|
|
312
|
-
|
|
313
227
|
// eslint-disable-next-line no-console
|
|
314
|
-
console.log(
|
|
228
|
+
console.log(
|
|
229
|
+
result.skipped ? 'No open PR found for this branch, skipping.' : 'PR comment synced.',
|
|
230
|
+
);
|
|
315
231
|
}
|
|
316
232
|
}
|
|
317
233
|
|
|
@@ -359,29 +275,6 @@ yargs(process.argv.slice(2))
|
|
|
359
275
|
handler: run,
|
|
360
276
|
}),
|
|
361
277
|
)
|
|
362
|
-
.command(
|
|
363
|
-
/** @type {import('yargs').CommandModule<{}, ReportCommandArgs>} */ ({
|
|
364
|
-
command: 'report',
|
|
365
|
-
describe: 'Generate a markdown report for a pull request',
|
|
366
|
-
builder: (cmdYargs) => {
|
|
367
|
-
return cmdYargs
|
|
368
|
-
.option('pr', {
|
|
369
|
-
describe: 'Pull request number',
|
|
370
|
-
type: 'number',
|
|
371
|
-
demandOption: true,
|
|
372
|
-
})
|
|
373
|
-
.option('owner', {
|
|
374
|
-
describe: 'Repository owner (defaults to current git repo owner)',
|
|
375
|
-
type: 'string',
|
|
376
|
-
})
|
|
377
|
-
.option('repo', {
|
|
378
|
-
describe: 'Repository name (defaults to current git repo name)',
|
|
379
|
-
type: 'string',
|
|
380
|
-
});
|
|
381
|
-
},
|
|
382
|
-
handler: reportCommand,
|
|
383
|
-
}),
|
|
384
|
-
)
|
|
385
278
|
.help()
|
|
386
279
|
.strict(true)
|
|
387
280
|
.version(false)
|
package/src/configLoader.js
CHANGED
|
@@ -80,7 +80,6 @@ export function applyUploadConfigDefaults(uploadConfig, ciInfo) {
|
|
|
80
80
|
throw new Error('Missing required field: upload.branch. Please specify a branch name.');
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
const legacyUpload = uploadConfig.legacyUpload ?? false;
|
|
84
83
|
const apiUrl =
|
|
85
84
|
uploadConfig.apiUrl ||
|
|
86
85
|
process.env.CI_REPORT_API_URL ||
|
|
@@ -96,7 +95,6 @@ export function applyUploadConfigDefaults(uploadConfig, ciInfo) {
|
|
|
96
95
|
? Boolean(uploadConfig.isPullRequest)
|
|
97
96
|
: Boolean(isPr),
|
|
98
97
|
apiUrl,
|
|
99
|
-
legacyUpload,
|
|
100
98
|
};
|
|
101
99
|
|
|
102
100
|
// Add PR number from CI environment if available
|
|
@@ -216,6 +214,11 @@ async function normalizeEntries(entries, configPath) {
|
|
|
216
214
|
).flat();
|
|
217
215
|
|
|
218
216
|
for (const entry of result) {
|
|
217
|
+
if (entry.id.startsWith('_')) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`Entry id "${entry.id}" must not start with "_". Ids starting with "_" are reserved for internal metadata.`,
|
|
220
|
+
);
|
|
221
|
+
}
|
|
219
222
|
if (usedIds.has(entry.id)) {
|
|
220
223
|
throw new Error(`Duplicate entry id found: "${entry.id}". Entry ids must be unique.`);
|
|
221
224
|
}
|
package/src/index.js
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
const DEFAULT_API_URL = 'https://code-infra-dashboard.onrender.com';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {{ success: boolean, skipped?: boolean }} SyncPrCommentResult
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Syncs a PR comment via the dashboard API.
|
|
11
|
+
* @param {string} repo - Repository in owner/repo format
|
|
12
|
+
* @param {Record<string, object>} sections - Section-specific parameters
|
|
13
|
+
* @returns {Promise<SyncPrCommentResult>}
|
|
14
|
+
*/
|
|
15
|
+
export async function syncPrComment(repo, sections) {
|
|
16
|
+
const oidcToken = process.env.CIRCLE_OIDC_TOKEN_V2;
|
|
17
|
+
if (!oidcToken) {
|
|
18
|
+
throw new Error('CIRCLE_OIDC_TOKEN_V2 environment variable is required for PR comment sync');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const apiUrl = process.env.CI_REPORT_API_URL || DEFAULT_API_URL;
|
|
22
|
+
const url = new URL('/api/ci-reports/sync-pr-comment', apiUrl);
|
|
23
|
+
|
|
24
|
+
const response = await fetch(url, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${oidcToken}` },
|
|
27
|
+
body: JSON.stringify({ repo, sections }),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
const responseText = await response.text();
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Sync PR comment API returned ${response.status} ${response.statusText}: ${responseText}`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return response.json();
|
|
38
|
+
}
|
package/src/types.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ export interface UploadConfig {
|
|
|
4
4
|
branch?: string; // Optional branch name (defaults to current Git branch)
|
|
5
5
|
isPullRequest?: boolean; // Whether this is a pull request build (defaults to CI detection)
|
|
6
6
|
apiUrl?: string; // Dashboard API URL (defaults to https://code-infra-dashboard.onrender.com)
|
|
7
|
-
legacyUpload?: boolean; // Upload directly to S3 instead of using the dashboard API
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
// Normalized upload configuration where all properties are defined
|
|
@@ -14,7 +13,6 @@ export interface NormalizedUploadConfig {
|
|
|
14
13
|
isPullRequest: boolean; // Whether this is a pull request build
|
|
15
14
|
prNumber?: string; // PR number (from CI environment)
|
|
16
15
|
apiUrl: string; // Dashboard API URL
|
|
17
|
-
legacyUpload: boolean; // Whether to use direct S3 upload
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
// EntryPoint types
|
|
@@ -63,12 +61,6 @@ export interface CommandLineArgs {
|
|
|
63
61
|
debug?: boolean;
|
|
64
62
|
}
|
|
65
63
|
|
|
66
|
-
export interface ReportCommandArgs {
|
|
67
|
-
pr?: number;
|
|
68
|
-
owner?: string;
|
|
69
|
-
repo?: string;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
64
|
// Diff command argument types
|
|
73
65
|
export interface DiffCommandArgs {
|
|
74
66
|
base: string;
|
|
@@ -83,21 +75,6 @@ export interface PrCommandArgs {
|
|
|
83
75
|
output?: 'json' | 'markdown';
|
|
84
76
|
}
|
|
85
77
|
|
|
86
|
-
export interface PrInfo {
|
|
87
|
-
number: number;
|
|
88
|
-
base: {
|
|
89
|
-
ref: string;
|
|
90
|
-
sha: string;
|
|
91
|
-
repo: {
|
|
92
|
-
full_name: string;
|
|
93
|
-
};
|
|
94
|
-
};
|
|
95
|
-
head: {
|
|
96
|
-
ref: string;
|
|
97
|
-
sha: string;
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
78
|
export interface SizeSnapshotEntry {
|
|
102
79
|
parsed: number;
|
|
103
80
|
gzip: number;
|
package/src/uploadSnapshot.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import { S3Client, PutObjectCommand, PutObjectTaggingCommand } from '@aws-sdk/client-s3';
|
|
3
2
|
import { execa } from 'execa';
|
|
4
|
-
import { fromEnv } from '@aws-sdk/credential-providers';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* @typedef {import('./types.js').NormalizedUploadConfig} NormalizedUploadConfig
|
|
@@ -16,20 +14,6 @@ async function getCurrentCommitSHA() {
|
|
|
16
14
|
return stdout.trim();
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
/**
|
|
20
|
-
* Sanitizes a string to be used as an S3 tag value
|
|
21
|
-
* See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#tag-restrictions
|
|
22
|
-
* @param {string} str
|
|
23
|
-
* @returns {string}
|
|
24
|
-
*/
|
|
25
|
-
function sanitizeS3TagString(str) {
|
|
26
|
-
// Replace disallowed characters with underscore
|
|
27
|
-
const safe = str.replace(/[^a-zA-Z0-9 +\-=.:/@]+/g, '_');
|
|
28
|
-
// Truncate to max lengths (256 for value)
|
|
29
|
-
const maxLen = 256;
|
|
30
|
-
return safe.length > maxLen ? safe.substring(0, maxLen) : safe;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
17
|
/**
|
|
34
18
|
* Uploads the snapshot via the dashboard API (server-side proxied to S3).
|
|
35
19
|
* @param {string} apiUrl - Base URL of the CI report API
|
|
@@ -39,8 +23,6 @@ function sanitizeS3TagString(str) {
|
|
|
39
23
|
* @returns {Promise<{key:string}>}
|
|
40
24
|
*/
|
|
41
25
|
async function uploadViaApi(apiUrl, fileContent, uploadConfig, sha) {
|
|
42
|
-
const { branch, prNumber } = uploadConfig;
|
|
43
|
-
|
|
44
26
|
/** @type {import('./ciReport.js').SizeSnapshotUpload} */
|
|
45
27
|
const requestBody = {
|
|
46
28
|
version: 1,
|
|
@@ -48,8 +30,7 @@ async function uploadViaApi(apiUrl, fileContent, uploadConfig, sha) {
|
|
|
48
30
|
commitSha: sha,
|
|
49
31
|
repo: uploadConfig.repo,
|
|
50
32
|
reportType: 'size-snapshot',
|
|
51
|
-
branch,
|
|
52
|
-
prNumber: prNumber ? Number(prNumber) : undefined,
|
|
33
|
+
branch: uploadConfig.branch,
|
|
53
34
|
report: JSON.parse(fileContent.toString('utf-8')),
|
|
54
35
|
};
|
|
55
36
|
|
|
@@ -81,53 +62,6 @@ async function uploadViaApi(apiUrl, fileContent, uploadConfig, sha) {
|
|
|
81
62
|
return { key: result.key };
|
|
82
63
|
}
|
|
83
64
|
|
|
84
|
-
/**
|
|
85
|
-
* Uploads the snapshot directly to S3 using AWS credentials.
|
|
86
|
-
* @param {Buffer} fileContent - The file content to upload
|
|
87
|
-
* @param {NormalizedUploadConfig} uploadConfig - The normalized upload configuration
|
|
88
|
-
* @param {string} sha - The commit SHA
|
|
89
|
-
* @returns {Promise<{key:string}>}
|
|
90
|
-
*/
|
|
91
|
-
async function uploadDirectToS3(fileContent, uploadConfig, sha) {
|
|
92
|
-
const { branch, isPullRequest } = uploadConfig;
|
|
93
|
-
|
|
94
|
-
// Create S3 client (uses AWS credentials from environment)
|
|
95
|
-
const client = new S3Client({
|
|
96
|
-
region: process.env.AWS_REGION_ARTIFACTS || process.env.AWS_REGION || 'eu-central-1',
|
|
97
|
-
credentials: fromEnv(),
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// S3 bucket and key
|
|
101
|
-
const bucket = 'mui-org-ci';
|
|
102
|
-
const key = `artifacts/${uploadConfig.repo}/${sha}/size-snapshot.json`;
|
|
103
|
-
|
|
104
|
-
// Upload the file first
|
|
105
|
-
await client.send(
|
|
106
|
-
new PutObjectCommand({
|
|
107
|
-
Bucket: bucket,
|
|
108
|
-
Key: key,
|
|
109
|
-
Body: fileContent,
|
|
110
|
-
ContentType: 'application/json',
|
|
111
|
-
}),
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
// Then add tags to the uploaded object
|
|
115
|
-
await client.send(
|
|
116
|
-
new PutObjectTaggingCommand({
|
|
117
|
-
Bucket: bucket,
|
|
118
|
-
Key: key,
|
|
119
|
-
Tagging: {
|
|
120
|
-
TagSet: [
|
|
121
|
-
{ Key: 'isPullRequest', Value: isPullRequest ? 'yes' : 'no' },
|
|
122
|
-
{ Key: 'branch', Value: sanitizeS3TagString(branch) },
|
|
123
|
-
],
|
|
124
|
-
},
|
|
125
|
-
}),
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
return { key };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
65
|
/**
|
|
132
66
|
* Uploads the size snapshot to S3
|
|
133
67
|
* @param {string} snapshotPath - The path to the size snapshot JSON file
|
|
@@ -142,9 +76,5 @@ export async function uploadSnapshot(snapshotPath, uploadConfig, commitSha) {
|
|
|
142
76
|
fs.promises.readFile(snapshotPath),
|
|
143
77
|
]);
|
|
144
78
|
|
|
145
|
-
if (uploadConfig.legacyUpload) {
|
|
146
|
-
return uploadDirectToS3(fileContent, uploadConfig, sha);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
79
|
return uploadViaApi(uploadConfig.apiUrl, fileContent, uploadConfig, sha);
|
|
150
80
|
}
|
package/build/browser.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export { calculateSizeDiff } from './sizeDiff.js';
|
|
2
|
-
export { fetchSnapshot } from './fetchSnapshot.js';
|
|
3
|
-
export type Size = import('./types.js').Size;
|
|
4
|
-
export type SizeSnapshot = import('./types.js').SizeSnapshot;
|
|
5
|
-
export type ComparisonResult = import('./types.js').ComparisonResult;
|
|
6
|
-
export type SizeSnapshotEntry = import('./types.js').SizeSnapshotEntry;
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {import('./types.js').Size} Size
|
|
9
|
-
* @typedef {import('./types.js').SizeSnapshot} SizeSnapshot
|
|
10
|
-
* @typedef {import('./types.js').ComparisonResult} ComparisonResult
|
|
11
|
-
* @typedef {import('./types.js').SizeSnapshotEntry} SizeSnapshotEntry
|
|
12
|
-
*/
|
package/build/constants.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const DASHBOARD_ORIGIN = "https://frontend-public.mui.com";
|
package/build/fetchSnapshot.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {string} repo - The name of the repository e.g. 'mui/material-ui'
|
|
4
|
-
* @param {string} sha - The commit SHA
|
|
5
|
-
* @returns {Promise<import('./sizeDiff.js').SizeSnapshot>} - The size snapshot data
|
|
6
|
-
*/
|
|
7
|
-
export declare function fetchSnapshot(repo: string, sha: string): Promise<import('./sizeDiff.js').SizeSnapshot>;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Attempts to fetch a snapshot with fallback to parent commits
|
|
3
|
-
* @param {string} repo - Repository name
|
|
4
|
-
* @param {string} commit - The commit SHA to start from
|
|
5
|
-
* @param {number} [fallbackDepth=3] - How many parent commits to try as fallback
|
|
6
|
-
* @returns {Promise<{snapshot: import('./sizeDiff.js').SizeSnapshot | null, actualCommit: string | null}>}
|
|
7
|
-
*/
|
|
8
|
-
export declare function fetchSnapshotWithFallback(repo: string, commit: string, fallbackDepth?: number): Promise<{
|
|
9
|
-
snapshot: import('./sizeDiff.js').SizeSnapshot | null;
|
|
10
|
-
actualCommit: string | null;
|
|
11
|
-
}>;
|