Skip to content

Commit 5706dca

Browse files
committed
feat: rework size calc
1 parent 8a670fe commit 5706dca

File tree

3 files changed

+155
-44
lines changed

3 files changed

+155
-44
lines changed

main.js

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24170,6 +24170,28 @@ async function fetchPackageMetadata(packageName, version) {
2417024170
return null;
2417124171
}
2417224172
}
24173+
async function calculateTotalDependencySizeIncrease(newVersions) {
24174+
let totalSize = 0;
24175+
const processedPackages = /* @__PURE__ */ new Set();
24176+
for (const dep of newVersions) {
24177+
const packageKey = `${dep.name}@${dep.version}`;
24178+
if (processedPackages.has(packageKey)) {
24179+
continue;
24180+
}
24181+
try {
24182+
const metadata = await fetchPackageMetadata(dep.name, dep.version);
24183+
if (!metadata || metadata.dist?.unpackedSize === void 0) {
24184+
return null;
24185+
}
24186+
totalSize += metadata.dist.unpackedSize;
24187+
processedPackages.add(packageKey);
24188+
core2.info(`Added ${metadata.dist.unpackedSize} bytes for ${packageKey}`);
24189+
} catch {
24190+
return null;
24191+
}
24192+
}
24193+
return totalSize;
24194+
}
2417324195

2417424196
// src/main.ts
2417524197
function formatBytes(bytes) {
@@ -24180,6 +24202,21 @@ function formatBytes(bytes) {
2418024202
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
2418124203
}
2418224204
var COMMENT_TAG = "<!-- dependency-diff-action -->";
24205+
function getLsCommand(lockfilePath, packageName) {
24206+
if (lockfilePath.endsWith("package-lock.json")) {
24207+
return `npm ls ${packageName}`;
24208+
}
24209+
if (lockfilePath.endsWith("pnpm-lock.yaml")) {
24210+
return `pnpm why ${packageName}`;
24211+
}
24212+
if (lockfilePath.endsWith("yarn.lock")) {
24213+
return `yarn why ${packageName}`;
24214+
}
24215+
if (lockfilePath.endsWith("bun.lock")) {
24216+
return `bun pm ls ${packageName}`;
24217+
}
24218+
return void 0;
24219+
}
2418324220
async function run() {
2418424221
try {
2418524222
const workspacePath = process2.env.GITHUB_WORKSPACE || process2.cwd();
@@ -24227,8 +24264,13 @@ async function run() {
2422724264
core3.getInput("size-threshold") || "100000",
2422824265
10
2422924266
);
24267+
const duplicateThreshold = parseInt(
24268+
core3.getInput("duplicate-threshold") || "1",
24269+
10
24270+
);
2423024271
core3.info(`Dependency threshold set to ${dependencyThreshold}`);
2423124272
core3.info(`Size threshold set to ${formatBytes(sizeThreshold)}`);
24273+
core3.info(`Duplicate threshold set to ${duplicateThreshold}`);
2423224274
const messages = [];
2423324275
const currentDepCount = Array.from(currentDeps.values()).reduce(
2423424276
(sum, versions) => sum + versions.size,
@@ -24247,6 +24289,24 @@ async function run() {
2424724289
`\u26A0\uFE0F **Dependency Count Warning**: This PR adds ${depIncrease} new dependencies (${baseDepCount} \u2192 ${currentDepCount}), which exceeds the threshold of ${dependencyThreshold}.`
2424824290
);
2424924291
}
24292+
const duplicateWarnings = [];
24293+
for (const [packageName, currentVersionSet] of currentDeps) {
24294+
if (currentVersionSet.size > duplicateThreshold) {
24295+
const versions = Array.from(currentVersionSet).sort();
24296+
const lsCommand = getLsCommand(lockfilePath, packageName);
24297+
duplicateWarnings.push(
24298+
`\u{1F4E6} **${packageName}**: ${currentVersionSet.size} versions (${versions.join(", ")})${lsCommand ? `
24299+
\u2514\u2500 ${lsCommand}` : ""}`
24300+
);
24301+
}
24302+
}
24303+
if (duplicateWarnings.length > 0) {
24304+
messages.push(
24305+
`\u26A0\uFE0F **Duplicate Dependencies Warning** (threshold: ${duplicateThreshold}):
24306+
24307+
${duplicateWarnings.join("\n")}`
24308+
);
24309+
}
2425024310
const newVersions = [];
2425124311
for (const [packageName, currentVersionSet] of currentDeps) {
2425224312
const baseVersionSet = baseDeps.get(packageName);
@@ -24262,28 +24322,15 @@ async function run() {
2426224322
}
2426324323
core3.info(`Found ${newVersions.length} new package versions`);
2426424324
if (newVersions.length > 0) {
24265-
const sizeWarnings = [];
24266-
for (const dep of newVersions) {
24267-
try {
24268-
const metadata = await fetchPackageMetadata(dep.name, dep.version);
24269-
if (metadata?.dist?.unpackedSize && metadata.dist.unpackedSize >= sizeThreshold) {
24270-
const label = dep.isNewPackage ? "new package" : "new version";
24271-
sizeWarnings.push(
24272-
`\u{1F4E6} **${dep.name}@${dep.version}** (${label}): ${formatBytes(metadata.dist.unpackedSize)}`
24273-
);
24274-
}
24275-
} catch (err) {
24276-
core3.info(
24277-
`Failed to check size for ${dep.name}@${dep.version}: ${err}`
24325+
try {
24326+
const totalSizeIncrease = await calculateTotalDependencySizeIncrease(newVersions);
24327+
if (totalSizeIncrease !== null && totalSizeIncrease >= sizeThreshold) {
24328+
messages.push(
24329+
`\u26A0\uFE0F **Large Dependency Size Increase**: This PR adds ${formatBytes(totalSizeIncrease)} of new dependencies, which exceeds the threshold of ${formatBytes(sizeThreshold)}.`
2427824330
);
2427924331
}
24280-
}
24281-
if (sizeWarnings.length > 0) {
24282-
messages.push(
24283-
`\u26A0\uFE0F **Large Package Warnings** (threshold: ${formatBytes(sizeThreshold)}):
24284-
24285-
${sizeWarnings.join("\n")}`
24286-
);
24332+
} catch (err) {
24333+
core3.info(`Failed to calculate total dependency size increase: ${err}`);
2428724334
}
2428824335
}
2428924336
if (messages.length === 0) {

src/main.ts

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as core from '@actions/core';
33
import * as github from '@actions/github';
44
import {parseLockfile, detectLockfile} from './lockfile.js';
55
import {getFileFromRef, getBaseRef} from './git.js';
6-
import {fetchPackageMetadata} from './npm.js';
6+
import {calculateTotalDependencySizeIncrease} from './npm.js';
77

88
function formatBytes(bytes: number): string {
99
if (bytes === 0) return '0 B';
@@ -15,6 +15,25 @@ function formatBytes(bytes: number): string {
1515

1616
const COMMENT_TAG = '<!-- dependency-diff-action -->';
1717

18+
function getLsCommand(
19+
lockfilePath: string,
20+
packageName: string
21+
): string | undefined {
22+
if (lockfilePath.endsWith('package-lock.json')) {
23+
return `npm ls ${packageName}`;
24+
}
25+
if (lockfilePath.endsWith('pnpm-lock.yaml')) {
26+
return `pnpm why ${packageName}`;
27+
}
28+
if (lockfilePath.endsWith('yarn.lock')) {
29+
return `yarn why ${packageName}`;
30+
}
31+
if (lockfilePath.endsWith('bun.lock')) {
32+
return `bun pm ls ${packageName}`;
33+
}
34+
return undefined;
35+
}
36+
1837
async function run(): Promise<void> {
1938
try {
2039
const workspacePath = process.env.GITHUB_WORKSPACE || process.cwd();
@@ -68,9 +87,14 @@ async function run(): Promise<void> {
6887
core.getInput('size-threshold') || '100000',
6988
10
7089
);
90+
const duplicateThreshold = parseInt(
91+
core.getInput('duplicate-threshold') || '1',
92+
10
93+
);
7194

7295
core.info(`Dependency threshold set to ${dependencyThreshold}`);
7396
core.info(`Size threshold set to ${formatBytes(sizeThreshold)}`);
97+
core.info(`Duplicate threshold set to ${duplicateThreshold}`);
7498

7599
const messages: string[] = [];
76100

@@ -95,6 +119,23 @@ async function run(): Promise<void> {
95119
);
96120
}
97121

122+
const duplicateWarnings: string[] = [];
123+
for (const [packageName, currentVersionSet] of currentDeps) {
124+
if (currentVersionSet.size > duplicateThreshold) {
125+
const versions = Array.from(currentVersionSet).sort();
126+
const lsCommand = getLsCommand(lockfilePath, packageName);
127+
duplicateWarnings.push(
128+
`📦 **${packageName}**: ${currentVersionSet.size} versions (${versions.join(', ')})${lsCommand ? `\n └─ ${lsCommand}` : ''}`
129+
);
130+
}
131+
}
132+
133+
if (duplicateWarnings.length > 0) {
134+
messages.push(
135+
`⚠️ **Duplicate Dependencies Warning** (threshold: ${duplicateThreshold}):\n\n${duplicateWarnings.join('\n')}`
136+
);
137+
}
138+
98139
const newVersions: Array<{
99140
name: string;
100141
version: string;
@@ -118,31 +159,17 @@ async function run(): Promise<void> {
118159
core.info(`Found ${newVersions.length} new package versions`);
119160

120161
if (newVersions.length > 0) {
121-
const sizeWarnings: string[] = [];
122-
123-
for (const dep of newVersions) {
124-
try {
125-
const metadata = await fetchPackageMetadata(dep.name, dep.version);
126-
if (
127-
metadata?.dist?.unpackedSize &&
128-
metadata.dist.unpackedSize >= sizeThreshold
129-
) {
130-
const label = dep.isNewPackage ? 'new package' : 'new version';
131-
sizeWarnings.push(
132-
`📦 **${dep.name}@${dep.version}** (${label}): ${formatBytes(metadata.dist.unpackedSize)}`
133-
);
134-
}
135-
} catch (err) {
136-
core.info(
137-
`Failed to check size for ${dep.name}@${dep.version}: ${err}`
162+
try {
163+
const totalSizeIncrease =
164+
await calculateTotalDependencySizeIncrease(newVersions);
165+
166+
if (totalSizeIncrease !== null && totalSizeIncrease >= sizeThreshold) {
167+
messages.push(
168+
`⚠️ **Large Dependency Size Increase**: This PR adds ${formatBytes(totalSizeIncrease)} of new dependencies, which exceeds the threshold of ${formatBytes(sizeThreshold)}.`
138169
);
139170
}
140-
}
141-
142-
if (sizeWarnings.length > 0) {
143-
messages.push(
144-
`⚠️ **Large Package Warnings** (threshold: ${formatBytes(sizeThreshold)}):\n\n${sizeWarnings.join('\n')}`
145-
);
171+
} catch (err) {
172+
core.info(`Failed to calculate total dependency size increase: ${err}`);
146173
}
147174
}
148175

src/npm.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ export interface PackageMetadata {
66
dist?: {
77
unpackedSize?: number;
88
};
9+
dependencies?: Record<string, string>;
10+
}
11+
12+
export interface PackageIndex {
13+
versions: Record<string, PackageMetadata>;
914
}
1015

1116
export async function fetchPackageMetadata(
@@ -24,3 +29,35 @@ export async function fetchPackageMetadata(
2429
return null;
2530
}
2631
}
32+
33+
export async function calculateTotalDependencySizeIncrease(
34+
newVersions: Array<{name: string; version: string}>
35+
): Promise<number | null> {
36+
let totalSize = 0;
37+
const processedPackages = new Set<string>();
38+
39+
for (const dep of newVersions) {
40+
const packageKey = `${dep.name}@${dep.version}`;
41+
42+
if (processedPackages.has(packageKey)) {
43+
continue;
44+
}
45+
46+
try {
47+
const metadata = await fetchPackageMetadata(dep.name, dep.version);
48+
49+
if (!metadata || metadata.dist?.unpackedSize === undefined) {
50+
return null;
51+
}
52+
53+
totalSize += metadata.dist.unpackedSize;
54+
processedPackages.add(packageKey);
55+
56+
core.info(`Added ${metadata.dist.unpackedSize} bytes for ${packageKey}`);
57+
} catch {
58+
return null;
59+
}
60+
}
61+
62+
return totalSize;
63+
}

0 commit comments

Comments
 (0)