Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,046 changes: 652 additions & 394 deletions build/main.js

Large diffs are not rendered by default.

39 changes: 14 additions & 25 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
"test": "vitest run"
},
"devDependencies": {
"@actions/core": "^2.0.1",
"@actions/github": "^6.0.1",
"@actions/core": "^2.0.2",
"@actions/github": "^7.0.0",
"@eslint/js": "^9.39.2",
"@types/node": "^25.0.3",
"esbuild": "^0.27.2",
Expand Down
86 changes: 82 additions & 4 deletions src/checks/dependency-size.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,82 @@ import {
} from '../npm.js';
import {formatBytes} from '../common.js';

interface PackageGroup {
added: Array<{version: string; size: number | null}>;
removed: Array<{version: string; size: number | null}>;
}

interface DisplayEntry {
label: string;
size: number | null;
sortSize: number;
}

function buildPackageGroups(
packageSizes: Map<string, number | null>
): Map<string, PackageGroup> {
const packageGroups = new Map<string, PackageGroup>();

for (const [pkgKey, size] of packageSizes.entries()) {
const atIndex = pkgKey.lastIndexOf('@');
const name = pkgKey.substring(0, atIndex);
const version = pkgKey.substring(atIndex + 1);

const group = packageGroups.get(name) ?? {added: [], removed: []};

if (size !== null && size < 0) {
group.removed.push({version, size});
} else {
group.added.push({version, size});
}

packageGroups.set(name, group);
}

return packageGroups;
}

function createDisplayEntries(
packageGroups: Map<string, PackageGroup>
): DisplayEntry[] {
const displayEntries: DisplayEntry[] = [];

for (const [name, group] of packageGroups.entries()) {
if (
group.added.length === 1 &&
group.removed.length === 1 &&
group.added[0].size !== null &&
group.removed[0].size !== null
) {
const netSize = group.added[0].size + group.removed[0].size;
displayEntries.push({
label: `${name}@${group.removed[0].version} → ${name}@${group.added[0].version}`,
size: netSize,
sortSize: netSize
});
} else {
for (const added of group.added) {
displayEntries.push({
label: `${name}@${added.version}`,
size: added.size,
sortSize: added.size ?? 0
});
}
for (const removed of group.removed) {
displayEntries.push({
label: `${name}@${removed.version}`,
size: removed.size,
sortSize: removed.size ?? 0
});
}
}
}

displayEntries.sort((a, b) => Math.abs(b.sortSize) - Math.abs(a.sortSize));

return displayEntries;
}

async function removeUnsupportedOptionalDependencies(
lockFile: ParsedLockFile,
versionInfo: Array<{name: string; version: string; isNewPackage?: boolean}>
Expand Down Expand Up @@ -118,11 +194,13 @@ export async function scanForDependencySize(
(sizeData !== null && sizeData.totalSize >= threshold);

if (shouldShow && sizeData !== null) {
const packageRows = Array.from(sizeData.packageSizes.entries())
.sort(([, a], [, b]) => (b ?? Infinity) - (a ?? Infinity))
const packageGroups = buildPackageGroups(sizeData.packageSizes);
const displayEntries = createDisplayEntries(packageGroups);

const packageRows = displayEntries
.map(
([pkg, size]) =>
`| ${pkg} | ${size === null ? '_Unknown_' : formatBytes(size)} |`
({label, size}) =>
`| ${label} | ${size === null ? '_Unknown_' : formatBytes(size)} |`
)
.join('\n');

Expand Down
133 changes: 133 additions & 0 deletions test/checks/__snapshots__/dependency-size_test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`scanForDependencySize > should not report changes below the threshold 1`] = `
{
"debug": [],
"error": [],
"info": [
"Found 1 new package versions",
"Found 0 removed package versions.",
"Added 27023 bytes for tinyexec@1.0.0",
"Total dependency size increase: 27 kB",
],
"warning": [],
}
`;

exports[`scanForDependencySize > should report negative upgrades on one line 1`] = `
[
"## 📊 Dependency Size Changes

> [!NOTE]
> :tada: This PR removes 138.5 kB of dependencies.

| 📦 Package | 📏 Size |
| --- | --- |
| chai@5.0.0 → chai@5.0.2 | -138.5 kB |

**Total size change:** -138.5 kB",
]
`;

exports[`scanForDependencySize > should report negative upgrades on one line 2`] = `
{
"debug": [],
"error": [],
"info": [
"Found 1 new package versions",
"Found 1 removed package versions.",
"Added 368262 bytes for chai@5.0.2",
"Subtracted 506753 bytes for chai@5.0.0",
"Total dependency size increase: -138.5 kB",
],
"warning": [],
}
`;

exports[`scanForDependencySize > should report new dependencies exceeding the threshold 1`] = `
[
"## 📊 Dependency Size Changes

> [!WARNING]
> This PR adds 23.6 MB of new dependencies, which exceeds the threshold of 1 kB.

| 📦 Package | 📏 Size |
| --- | --- |
| typescript@5.9.3 | 23.6 MB |

**Total size change:** 23.6 MB",
]
`;

exports[`scanForDependencySize > should report new dependencies exceeding the threshold 2`] = `
{
"debug": [],
"error": [],
"info": [
"Found 1 new package versions",
"Found 0 removed package versions.",
"Added 23625066 bytes for typescript@5.9.3",
"Total dependency size increase: 23.6 MB",
],
"warning": [],
}
`;

exports[`scanForDependencySize > should report removals when threshold is -1 1`] = `
[
"## 📊 Dependency Size Changes

> [!NOTE]
> :tada: This PR removes 27 kB of dependencies.

| 📦 Package | 📏 Size |
| --- | --- |
| tinyexec@1.0.0 | -27 kB |

**Total size change:** -27 kB",
]
`;

exports[`scanForDependencySize > should report removals when threshold is -1 2`] = `
{
"debug": [],
"error": [],
"info": [
"Found 0 new package versions",
"Found 1 removed package versions.",
"Subtracted 27023 bytes for tinyexec@1.0.0",
"Total dependency size increase: -27 kB",
],
"warning": [],
}
`;

exports[`scanForDependencySize > should report upgrades on one line 1`] = `
[
"## 📊 Dependency Size Changes

> [!WARNING]
> This PR adds 137.8 kB of new dependencies, which exceeds the threshold of 1 B.

| 📦 Package | 📏 Size |
| --- | --- |
| chai@5.0.2 → chai@5.0.3 | 137.8 kB |

**Total size change:** 137.8 kB",
]
`;

exports[`scanForDependencySize > should report upgrades on one line 2`] = `
{
"debug": [],
"error": [],
"info": [
"Found 1 new package versions",
"Found 1 removed package versions.",
"Added 506025 bytes for chai@5.0.3",
"Subtracted 368262 bytes for chai@5.0.2",
"Total dependency size increase: 137.8 kB",
],
"warning": [],
}
`;
Loading