@mui/internal-bundle-size-checker 1.0.9-canary.72 → 1.0.9-canary.74
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/syncPrComment.d.ts +1 -2
- package/package.json +2 -4
- package/src/ciReport.js +7 -1
- package/src/cli.js +13 -60
- package/src/configLoader.js +10 -2
- package/src/syncPrComment.js +2 -3
- package/src/types.d.ts +2 -2
- package/src/uploadSnapshot.js +3 -70
package/build/syncPrComment.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export type SyncPrCommentResult = {
|
|
|
8
8
|
/**
|
|
9
9
|
* Syncs a PR comment via the dashboard API.
|
|
10
10
|
* @param {string} repo - Repository in owner/repo format
|
|
11
|
-
* @param {Record<string, object>} sections - Section-specific parameters
|
|
12
11
|
* @returns {Promise<SyncPrCommentResult>}
|
|
13
12
|
*/
|
|
14
|
-
export declare function syncPrComment(repo: string
|
|
13
|
+
export declare function syncPrComment(repo: string): 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.74",
|
|
4
4
|
"description": "Bundle size checker for MUI packages.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,8 +27,6 @@
|
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@aws-sdk/client-s3": "^3.1008.0",
|
|
31
|
-
"@aws-sdk/credential-providers": "^3.1008.0",
|
|
32
30
|
"@octokit/rest": "^22.0.1",
|
|
33
31
|
"chalk": "^5.6.2",
|
|
34
32
|
"env-ci": "^11.2.0",
|
|
@@ -46,7 +44,7 @@
|
|
|
46
44
|
"@types/micromatch": "4.0.10",
|
|
47
45
|
"@types/yargs": "17.0.35"
|
|
48
46
|
},
|
|
49
|
-
"gitSha": "
|
|
47
|
+
"gitSha": "fcc57442eeb92486028b70bb43a2b7d09eaa7e52",
|
|
50
48
|
"scripts": {
|
|
51
49
|
"build": "tsgo -p tsconfig.build.json",
|
|
52
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
|
@@ -93,45 +93,6 @@ async function getBundleSizes(args, config) {
|
|
|
93
93
|
return sizeArrays.flat();
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
/**
|
|
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
|
|
102
|
-
* @returns {Promise<void>}
|
|
103
|
-
*/
|
|
104
|
-
async function postInitialPrComment(config) {
|
|
105
|
-
const ciInfo = getCiInfo();
|
|
106
|
-
|
|
107
|
-
if (!ciInfo) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (!ciInfo.slug) {
|
|
112
|
-
throw new Error('PR commenting enabled but repository information missing in CI build');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (!config.upload) {
|
|
116
|
-
throw new Error('PR commenting requires upload configuration to determine the API URL');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
try {
|
|
120
|
-
// eslint-disable-next-line no-console
|
|
121
|
-
console.log('Posting initial PR comment via dashboard API...');
|
|
122
|
-
|
|
123
|
-
const result = await syncPrComment(ciInfo.slug, { bundleSize: { status: 'pending' } });
|
|
124
|
-
|
|
125
|
-
// eslint-disable-next-line no-console
|
|
126
|
-
console.log(
|
|
127
|
-
result.skipped ? 'No open PR found for this branch, skipping.' : 'Initial PR comment posted.',
|
|
128
|
-
);
|
|
129
|
-
} catch (/** @type {any} */ error) {
|
|
130
|
-
console.error('Failed to post initial PR comment:', error.message);
|
|
131
|
-
// Don't fail the build for comment failures
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
96
|
/**
|
|
136
97
|
* Main runner function
|
|
137
98
|
* @param {CommandLineArgs} argv - Command line arguments
|
|
@@ -143,19 +104,25 @@ async function run(argv) {
|
|
|
143
104
|
|
|
144
105
|
const config = await loadConfig(rootDir);
|
|
145
106
|
|
|
146
|
-
// Post initial PR comment if enabled and in CI environment
|
|
147
|
-
if (config && config.comment) {
|
|
148
|
-
await postInitialPrComment(config);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
107
|
// eslint-disable-next-line no-console
|
|
152
108
|
console.log(`Starting bundle size snapshot creation with ${concurrency} workers...`);
|
|
153
109
|
|
|
154
110
|
const bundleSizes = await getBundleSizes(argv, config);
|
|
111
|
+
// Get tracked bundles from config
|
|
112
|
+
const trackedBundles = config.entrypoints
|
|
113
|
+
.filter((entry) => entry.track === true)
|
|
114
|
+
.map((entry) => entry.id);
|
|
115
|
+
|
|
155
116
|
const sortedBundleSizes = Object.fromEntries(
|
|
156
117
|
bundleSizes.sort((a, b) => a[0].localeCompare(b[0])),
|
|
157
118
|
);
|
|
158
119
|
|
|
120
|
+
// Add metadata with tracked bundles to the snapshot
|
|
121
|
+
if (trackedBundles.length > 0) {
|
|
122
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
123
|
+
sortedBundleSizes._metadata = /** @type {any} */ ({ trackedBundles });
|
|
124
|
+
}
|
|
125
|
+
|
|
159
126
|
// Ensure output directory exists
|
|
160
127
|
await fs.mkdir(path.dirname(snapshotDestPath), { recursive: true });
|
|
161
128
|
await fs.writeFile(snapshotDestPath, JSON.stringify(sortedBundleSizes, null, 2));
|
|
@@ -169,11 +136,7 @@ async function run(argv) {
|
|
|
169
136
|
if (config && config.upload) {
|
|
170
137
|
try {
|
|
171
138
|
// eslint-disable-next-line no-console
|
|
172
|
-
console.log(
|
|
173
|
-
config.upload.legacyUpload
|
|
174
|
-
? 'Uploading bundle size snapshot directly to S3 (legacy)...'
|
|
175
|
-
: 'Uploading bundle size snapshot via dashboard API...',
|
|
176
|
-
);
|
|
139
|
+
console.log(`Uploading bundle size snapshot via dashboard API at ${config.upload.apiUrl}...`);
|
|
177
140
|
const { key } = await uploadSnapshot(snapshotDestPath, config.upload);
|
|
178
141
|
// eslint-disable-next-line no-console
|
|
179
142
|
console.log(`Bundle size snapshot uploaded to S3 with key: ${key}`);
|
|
@@ -210,17 +173,7 @@ async function run(argv) {
|
|
|
210
173
|
// eslint-disable-next-line no-console
|
|
211
174
|
console.log('Syncing PR comment via dashboard API...');
|
|
212
175
|
|
|
213
|
-
|
|
214
|
-
const trackedBundles = config.entrypoints
|
|
215
|
-
.filter((entry) => entry.track === true)
|
|
216
|
-
.map((entry) => entry.id);
|
|
217
|
-
|
|
218
|
-
const result = await syncPrComment(ciInfo.slug, {
|
|
219
|
-
bundleSize: {
|
|
220
|
-
status: 'complete',
|
|
221
|
-
trackedBundles: trackedBundles.length > 0 ? trackedBundles : undefined,
|
|
222
|
-
},
|
|
223
|
-
});
|
|
176
|
+
const result = await syncPrComment(ciInfo.slug);
|
|
224
177
|
|
|
225
178
|
// eslint-disable-next-line no-console
|
|
226
179
|
console.log(
|
package/src/configLoader.js
CHANGED
|
@@ -80,7 +80,10 @@ 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
|
|
83
|
+
const apiUrl =
|
|
84
|
+
uploadConfig.apiUrl ||
|
|
85
|
+
process.env.CI_REPORT_API_URL ||
|
|
86
|
+
'https://code-infra-dashboard.onrender.com';
|
|
84
87
|
|
|
85
88
|
// Return the normalized config
|
|
86
89
|
/** @type {NormalizedUploadConfig} */
|
|
@@ -91,7 +94,7 @@ export function applyUploadConfigDefaults(uploadConfig, ciInfo) {
|
|
|
91
94
|
uploadConfig.isPullRequest !== undefined
|
|
92
95
|
? Boolean(uploadConfig.isPullRequest)
|
|
93
96
|
: Boolean(isPr),
|
|
94
|
-
|
|
97
|
+
apiUrl,
|
|
95
98
|
};
|
|
96
99
|
|
|
97
100
|
// Add PR number from CI environment if available
|
|
@@ -211,6 +214,11 @@ async function normalizeEntries(entries, configPath) {
|
|
|
211
214
|
).flat();
|
|
212
215
|
|
|
213
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
|
+
}
|
|
214
222
|
if (usedIds.has(entry.id)) {
|
|
215
223
|
throw new Error(`Duplicate entry id found: "${entry.id}". Entry ids must be unique.`);
|
|
216
224
|
}
|
package/src/syncPrComment.js
CHANGED
|
@@ -9,10 +9,9 @@ const DEFAULT_API_URL = 'https://code-infra-dashboard.onrender.com';
|
|
|
9
9
|
/**
|
|
10
10
|
* Syncs a PR comment via the dashboard API.
|
|
11
11
|
* @param {string} repo - Repository in owner/repo format
|
|
12
|
-
* @param {Record<string, object>} sections - Section-specific parameters
|
|
13
12
|
* @returns {Promise<SyncPrCommentResult>}
|
|
14
13
|
*/
|
|
15
|
-
export async function syncPrComment(repo
|
|
14
|
+
export async function syncPrComment(repo) {
|
|
16
15
|
const oidcToken = process.env.CIRCLE_OIDC_TOKEN_V2;
|
|
17
16
|
if (!oidcToken) {
|
|
18
17
|
throw new Error('CIRCLE_OIDC_TOKEN_V2 environment variable is required for PR comment sync');
|
|
@@ -24,7 +23,7 @@ export async function syncPrComment(repo, sections) {
|
|
|
24
23
|
const response = await fetch(url, {
|
|
25
24
|
method: 'POST',
|
|
26
25
|
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${oidcToken}` },
|
|
27
|
-
body: JSON.stringify({ repo
|
|
26
|
+
body: JSON.stringify({ repo }),
|
|
28
27
|
});
|
|
29
28
|
|
|
30
29
|
if (!response.ok) {
|
package/src/types.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export interface UploadConfig {
|
|
|
3
3
|
repo?: string; // The repository name (e.g., "mui/material-ui")
|
|
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
7
|
}
|
|
8
8
|
|
|
9
9
|
// Normalized upload configuration where all properties are defined
|
|
@@ -12,7 +12,7 @@ export interface NormalizedUploadConfig {
|
|
|
12
12
|
branch: string; // Branch name
|
|
13
13
|
isPullRequest: boolean; // Whether this is a pull request build
|
|
14
14
|
prNumber?: string; // PR number (from CI environment)
|
|
15
|
-
|
|
15
|
+
apiUrl: string; // Dashboard API URL
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
// EntryPoint types
|
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,29 +14,15 @@ 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).
|
|
19
|
+
* @param {string} apiUrl - Base URL of the CI report API
|
|
35
20
|
* @param {Buffer} fileContent - The file content to upload
|
|
36
21
|
* @param {NormalizedUploadConfig} uploadConfig - The normalized upload configuration
|
|
37
22
|
* @param {string} sha - The commit SHA
|
|
38
23
|
* @returns {Promise<{key:string}>}
|
|
39
24
|
*/
|
|
40
|
-
async function uploadViaApi(fileContent, uploadConfig, sha) {
|
|
41
|
-
const apiUrl = process.env.CI_REPORT_API_URL || 'https://code-infra-dashboard.onrender.com';
|
|
25
|
+
async function uploadViaApi(apiUrl, fileContent, uploadConfig, sha) {
|
|
42
26
|
/** @type {import('./ciReport.js').SizeSnapshotUpload} */
|
|
43
27
|
const requestBody = {
|
|
44
28
|
version: 1,
|
|
@@ -78,53 +62,6 @@ async function uploadViaApi(fileContent, uploadConfig, sha) {
|
|
|
78
62
|
return { key: result.key };
|
|
79
63
|
}
|
|
80
64
|
|
|
81
|
-
/**
|
|
82
|
-
* Uploads the snapshot directly to S3 using AWS credentials.
|
|
83
|
-
* @param {Buffer} fileContent - The file content to upload
|
|
84
|
-
* @param {NormalizedUploadConfig} uploadConfig - The normalized upload configuration
|
|
85
|
-
* @param {string} sha - The commit SHA
|
|
86
|
-
* @returns {Promise<{key:string}>}
|
|
87
|
-
*/
|
|
88
|
-
async function uploadDirectToS3(fileContent, uploadConfig, sha) {
|
|
89
|
-
const { branch, isPullRequest } = uploadConfig;
|
|
90
|
-
|
|
91
|
-
// Create S3 client (uses AWS credentials from environment)
|
|
92
|
-
const client = new S3Client({
|
|
93
|
-
region: process.env.AWS_REGION_ARTIFACTS || process.env.AWS_REGION || 'eu-central-1',
|
|
94
|
-
credentials: fromEnv(),
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// S3 bucket and key
|
|
98
|
-
const bucket = 'mui-org-ci';
|
|
99
|
-
const key = `artifacts/${uploadConfig.repo}/${sha}/size-snapshot.json`;
|
|
100
|
-
|
|
101
|
-
// Upload the file first
|
|
102
|
-
await client.send(
|
|
103
|
-
new PutObjectCommand({
|
|
104
|
-
Bucket: bucket,
|
|
105
|
-
Key: key,
|
|
106
|
-
Body: fileContent,
|
|
107
|
-
ContentType: 'application/json',
|
|
108
|
-
}),
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
// Then add tags to the uploaded object
|
|
112
|
-
await client.send(
|
|
113
|
-
new PutObjectTaggingCommand({
|
|
114
|
-
Bucket: bucket,
|
|
115
|
-
Key: key,
|
|
116
|
-
Tagging: {
|
|
117
|
-
TagSet: [
|
|
118
|
-
{ Key: 'isPullRequest', Value: isPullRequest ? 'yes' : 'no' },
|
|
119
|
-
{ Key: 'branch', Value: sanitizeS3TagString(branch) },
|
|
120
|
-
],
|
|
121
|
-
},
|
|
122
|
-
}),
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
return { key };
|
|
126
|
-
}
|
|
127
|
-
|
|
128
65
|
/**
|
|
129
66
|
* Uploads the size snapshot to S3
|
|
130
67
|
* @param {string} snapshotPath - The path to the size snapshot JSON file
|
|
@@ -139,9 +76,5 @@ export async function uploadSnapshot(snapshotPath, uploadConfig, commitSha) {
|
|
|
139
76
|
fs.promises.readFile(snapshotPath),
|
|
140
77
|
]);
|
|
141
78
|
|
|
142
|
-
|
|
143
|
-
return uploadDirectToS3(fileContent, uploadConfig, sha);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return uploadViaApi(fileContent, uploadConfig, sha);
|
|
79
|
+
return uploadViaApi(uploadConfig.apiUrl, fileContent, uploadConfig, sha);
|
|
147
80
|
}
|