@mui/internal-bundle-size-checker 1.0.9-canary.33 → 1.0.9-canary.35
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/package.json +2 -2
- package/src/builder.js +2 -2
- package/src/cli.js +12 -2
- package/src/git.js +18 -13
- package/src/renderMarkdownReport.js +4 -18
- package/src/renderMarkdownReport.test.js +81 -30
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.35",
|
|
4
4
|
"description": "Bundle size checker for MUI packages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@types/micromatch": "^4.0.9",
|
|
39
39
|
"@types/yargs": "^17.0.33"
|
|
40
40
|
},
|
|
41
|
-
"gitSha": "
|
|
41
|
+
"gitSha": "ea7dfcb14068be0dddaa7827a0d294fc5de6e986",
|
|
42
42
|
"scripts": {
|
|
43
43
|
"typescript": "tsc -p tsconfig.json",
|
|
44
44
|
"test": "pnpm -w test --project @mui/internal-bundle-size-checker"
|
package/src/builder.js
CHANGED
|
@@ -75,7 +75,7 @@ async function createViteConfig(entry, args) {
|
|
|
75
75
|
emptyOutDir: true,
|
|
76
76
|
rollupOptions: {
|
|
77
77
|
input: '/index.tsx',
|
|
78
|
-
external: externalsArray,
|
|
78
|
+
external: (id) => externalsArray.some((ext) => id === ext || id.startsWith(`${ext}/`)),
|
|
79
79
|
plugins: [
|
|
80
80
|
...(args.analyze
|
|
81
81
|
? [
|
|
@@ -108,7 +108,7 @@ async function createViteConfig(entry, args) {
|
|
|
108
108
|
},
|
|
109
109
|
|
|
110
110
|
define: {
|
|
111
|
-
'process.env.NODE_ENV': JSON.stringify(
|
|
111
|
+
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
112
112
|
},
|
|
113
113
|
logLevel: args.verbose ? 'info' : 'silent',
|
|
114
114
|
// Add plugins to handle virtual entry points
|
package/src/cli.js
CHANGED
|
@@ -85,7 +85,7 @@ async function reportCommand(argv) {
|
|
|
85
85
|
// Get current repo info and coerce with provided arguments
|
|
86
86
|
const currentRepo = await getCurrentRepoInfo();
|
|
87
87
|
const owner = argOwner ?? currentRepo.owner;
|
|
88
|
-
const repo = argRepo ?? currentRepo.
|
|
88
|
+
const repo = argRepo ?? currentRepo.name;
|
|
89
89
|
|
|
90
90
|
if (typeof pr !== 'number') {
|
|
91
91
|
throw new Error('Invalid pull request number. Please provide a valid --pr option.');
|
|
@@ -105,8 +105,18 @@ async function reportCommand(argv) {
|
|
|
105
105
|
pull_number: pr,
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
+
const getMergeBaseFromGithubApi = async (
|
|
109
|
+
/** @type {string} */ base,
|
|
110
|
+
/** @type {string} */ head,
|
|
111
|
+
) => {
|
|
112
|
+
const { data } = await octokit.repos.compareCommits({ owner, repo, base, head });
|
|
113
|
+
return data.merge_base_commit.sha;
|
|
114
|
+
};
|
|
115
|
+
|
|
108
116
|
// Generate and print the markdown report
|
|
109
|
-
const report = await renderMarkdownReport(prInfo
|
|
117
|
+
const report = await renderMarkdownReport(prInfo, undefined, {
|
|
118
|
+
getMergeBase: getMergeBaseFromGithubApi,
|
|
119
|
+
});
|
|
110
120
|
// eslint-disable-next-line no-console
|
|
111
121
|
console.log(report);
|
|
112
122
|
}
|
package/src/git.js
CHANGED
|
@@ -26,20 +26,25 @@ export async function getMergeBase(base, head) {
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Gets the current repository owner and name from git remote
|
|
29
|
-
* @returns {Promise<
|
|
29
|
+
* @returns {Promise<string | null>}
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
async function getRemoteUrl(remote = 'origin') {
|
|
32
32
|
try {
|
|
33
|
-
const { stdout } = await execa('git', ['remote', 'get-url',
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
const { stdout } = await execa('git', ['remote', 'get-url', remote]);
|
|
34
|
+
return stdout.trim();
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Gets the current repository owner and name from git remote
|
|
42
|
+
* @returns {Promise<{owner: string | null, name: string | null}>}
|
|
43
|
+
*/
|
|
44
|
+
export async function getCurrentRepoInfo() {
|
|
45
|
+
const remoteUrl = (await getRemoteUrl('upstream')) || (await getRemoteUrl('origin'));
|
|
46
|
+
if (!remoteUrl) {
|
|
47
|
+
return { owner: null, name: null };
|
|
44
48
|
}
|
|
49
|
+
return gitUrlParse(remoteUrl);
|
|
45
50
|
}
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
import { calculateSizeDiff } from './sizeDiff.js';
|
|
8
8
|
import { fetchSnapshot } from './fetchSnapshot.js';
|
|
9
9
|
import { displayPercentFormatter, byteSizeChangeFormatter } from './formatUtils.js';
|
|
10
|
-
import {
|
|
11
|
-
import { getCurrentRepoInfo, getMergeBase } from './git.js';
|
|
10
|
+
import { getMergeBase } from './git.js';
|
|
12
11
|
import { fetchSnapshotWithFallback } from './fetchSnapshotWithFallback.js';
|
|
13
12
|
|
|
14
13
|
/**
|
|
@@ -224,6 +223,7 @@ function getDetailsUrl(prInfo, options = {}) {
|
|
|
224
223
|
* @param {string[]} [options.track] - Array of bundle IDs to track
|
|
225
224
|
* @param {number} [options.fallbackDepth=3] - How many parent commits to try as fallback when base snapshot is missing
|
|
226
225
|
* @param {number} [options.maxDetailsLines=100] - Maximum number of bundles to show in details section
|
|
226
|
+
* @param {(base: string, head: string) => Promise<string>} [options.getMergeBase] - Custom function to get merge base commit
|
|
227
227
|
* @returns {Promise<string>} Markdown report
|
|
228
228
|
*/
|
|
229
229
|
export async function renderMarkdownReport(prInfo, circleciBuildNumber, options = {}) {
|
|
@@ -233,22 +233,8 @@ export async function renderMarkdownReport(prInfo, circleciBuildNumber, options
|
|
|
233
233
|
const repo = prInfo.base.repo.full_name;
|
|
234
234
|
const { fallbackDepth = 3 } = options;
|
|
235
235
|
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
const currentRepo = await getCurrentRepoInfo();
|
|
239
|
-
|
|
240
|
-
let baseCommit;
|
|
241
|
-
if (owner === currentRepo.owner && repoName === currentRepo.repo) {
|
|
242
|
-
baseCommit = await getMergeBase(prInfo.base.sha, prCommit);
|
|
243
|
-
} else {
|
|
244
|
-
const { data } = await octokit.repos.compareCommits({
|
|
245
|
-
owner,
|
|
246
|
-
repo: repoName,
|
|
247
|
-
base: prInfo.base.sha,
|
|
248
|
-
head: prCommit,
|
|
249
|
-
});
|
|
250
|
-
baseCommit = data.merge_base_commit.sha;
|
|
251
|
-
}
|
|
236
|
+
const getMergeBaseFn = options.getMergeBase || getMergeBase;
|
|
237
|
+
const baseCommit = await getMergeBaseFn(prInfo.base.sha, prCommit);
|
|
252
238
|
|
|
253
239
|
const [baseResult, prSnapshot] = await Promise.all([
|
|
254
240
|
fetchSnapshotWithFallback(repo, baseCommit, fallbackDepth),
|
|
@@ -3,29 +3,21 @@ import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
|
3
3
|
import { renderMarkdownReport } from './renderMarkdownReport.js';
|
|
4
4
|
import * as fetchSnapshotModule from './fetchSnapshot.js';
|
|
5
5
|
import * as fetchSnapshotWithFallbackModule from './fetchSnapshotWithFallback.js';
|
|
6
|
+
import * as gitModule from './git.js';
|
|
6
7
|
|
|
7
8
|
// Mock the fetchSnapshot module
|
|
8
9
|
vi.mock('./fetchSnapshot.js');
|
|
9
10
|
// Mock the fetchSnapshotWithFallback module
|
|
10
11
|
vi.mock('./fetchSnapshotWithFallback.js');
|
|
11
|
-
// Mock the
|
|
12
|
-
vi.mock('
|
|
13
|
-
Octokit: vi.fn(() => ({
|
|
14
|
-
repos: {
|
|
15
|
-
compareCommits: vi.fn(),
|
|
16
|
-
listCommits: vi.fn(),
|
|
17
|
-
},
|
|
18
|
-
pulls: {
|
|
19
|
-
get: vi.fn(),
|
|
20
|
-
},
|
|
21
|
-
})),
|
|
22
|
-
}));
|
|
12
|
+
// Mock the git module
|
|
13
|
+
vi.mock('./git.js');
|
|
23
14
|
|
|
24
15
|
describe('renderMarkdownReport', () => {
|
|
25
16
|
const mockFetchSnapshot = vi.mocked(fetchSnapshotModule.fetchSnapshot);
|
|
26
17
|
const mockFetchSnapshotWithFallback = vi.mocked(
|
|
27
18
|
fetchSnapshotWithFallbackModule.fetchSnapshotWithFallback,
|
|
28
19
|
);
|
|
20
|
+
const mockGetMergeBase = vi.mocked(gitModule.getMergeBase);
|
|
29
21
|
|
|
30
22
|
/** @type {PrInfo} */
|
|
31
23
|
const mockPrInfo = {
|
|
@@ -41,26 +33,13 @@ describe('renderMarkdownReport', () => {
|
|
|
41
33
|
},
|
|
42
34
|
};
|
|
43
35
|
|
|
44
|
-
beforeEach(
|
|
36
|
+
beforeEach(() => {
|
|
45
37
|
mockFetchSnapshot.mockClear();
|
|
46
38
|
mockFetchSnapshotWithFallback.mockClear();
|
|
39
|
+
mockGetMergeBase.mockClear();
|
|
47
40
|
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// Set up default mock for compareCommits to return the base commit SHA
|
|
52
|
-
vi.mocked(octokit.repos.compareCommits).mockResolvedValue(
|
|
53
|
-
/** @type {any} */ ({
|
|
54
|
-
data: {
|
|
55
|
-
merge_base_commit: {
|
|
56
|
-
sha: mockPrInfo.base.sha,
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
}),
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
// Clear any previous mock calls
|
|
63
|
-
vi.mocked(octokit.repos.compareCommits).mockClear();
|
|
41
|
+
// Set up default mock for getMergeBase
|
|
42
|
+
mockGetMergeBase.mockResolvedValue(mockPrInfo.base.sha);
|
|
64
43
|
});
|
|
65
44
|
|
|
66
45
|
it('should generate markdown report with size increases', async () => {
|
|
@@ -582,11 +561,83 @@ describe('renderMarkdownReport', () => {
|
|
|
582
561
|
});
|
|
583
562
|
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
584
563
|
|
|
585
|
-
const result = await renderMarkdownReport(mockPrInfo, undefined, {
|
|
564
|
+
const result = await renderMarkdownReport(mockPrInfo, undefined, {
|
|
565
|
+
fallbackDepth: 1,
|
|
566
|
+
});
|
|
586
567
|
|
|
587
568
|
expect(result).toContain(
|
|
588
569
|
'Using snapshot from parent commit parent1 (fallback from merge base abc123)',
|
|
589
570
|
);
|
|
590
571
|
expect(mockFetchSnapshotWithFallback).toHaveBeenCalledWith('mui/material-ui', 'abc123', 1);
|
|
591
572
|
});
|
|
573
|
+
|
|
574
|
+
it('should throw error when default getMergeBase fails', async () => {
|
|
575
|
+
const prSnapshot = {
|
|
576
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
// Mock getMergeBase to fail (simulating no merge base found)
|
|
580
|
+
mockGetMergeBase.mockRejectedValue(new Error('fatal: Not a valid object name abc123'));
|
|
581
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
582
|
+
|
|
583
|
+
await expect(renderMarkdownReport(mockPrInfo)).rejects.toThrow(
|
|
584
|
+
'fatal: Not a valid object name abc123',
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
// Verify that getMergeBase was called with correct parameters
|
|
588
|
+
expect(mockGetMergeBase).toHaveBeenCalledWith('abc123', 'def456');
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
it('should use custom getMergeBase function when provided', async () => {
|
|
592
|
+
const baseSnapshot = {
|
|
593
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
const prSnapshot = {
|
|
597
|
+
'@mui/material/Button/index.js': { parsed: 15400, gzip: 4600 },
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
const customGetMergeBase = vi.fn().mockResolvedValue('custom123');
|
|
601
|
+
|
|
602
|
+
// Reset mocks to ensure clean state for this test
|
|
603
|
+
mockFetchSnapshotWithFallback.mockReset();
|
|
604
|
+
mockFetchSnapshot.mockReset();
|
|
605
|
+
|
|
606
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
607
|
+
snapshot: baseSnapshot,
|
|
608
|
+
actualCommit: 'custom123',
|
|
609
|
+
});
|
|
610
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
611
|
+
|
|
612
|
+
const result = await renderMarkdownReport(mockPrInfo, undefined, {
|
|
613
|
+
getMergeBase: customGetMergeBase,
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
// Verify that custom getMergeBase was called instead of default
|
|
617
|
+
expect(customGetMergeBase).toHaveBeenCalledWith('abc123', 'def456');
|
|
618
|
+
expect(mockGetMergeBase).not.toHaveBeenCalled();
|
|
619
|
+
expect(mockFetchSnapshotWithFallback).toHaveBeenCalledWith('mui/material-ui', 'custom123', 3);
|
|
620
|
+
|
|
621
|
+
expect(result).toContain('**Total Size Change:** 🔺+400B');
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('should throw error when custom getMergeBase fails', async () => {
|
|
625
|
+
const prSnapshot = {
|
|
626
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
const customGetMergeBase = vi.fn().mockRejectedValue(new Error('Custom merge base error'));
|
|
630
|
+
|
|
631
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
632
|
+
|
|
633
|
+
await expect(
|
|
634
|
+
renderMarkdownReport(mockPrInfo, undefined, {
|
|
635
|
+
getMergeBase: customGetMergeBase,
|
|
636
|
+
}),
|
|
637
|
+
).rejects.toThrow('Custom merge base error');
|
|
638
|
+
|
|
639
|
+
// Verify that custom getMergeBase was called
|
|
640
|
+
expect(customGetMergeBase).toHaveBeenCalledWith('abc123', 'def456');
|
|
641
|
+
expect(mockGetMergeBase).not.toHaveBeenCalled();
|
|
642
|
+
});
|
|
592
643
|
});
|