Skip to content
This repository was archived by the owner on Jan 28, 2025. It is now read-only.

Commit 246acdf

Browse files
authored
chore: post handler size comparisons for non-fork PRs (#1320)
1 parent 8a118be commit 246acdf

File tree

6 files changed

+228
-69
lines changed

6 files changed

+228
-69
lines changed

.github/workflows/CI.yml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ jobs:
2828

2929
- run: yarn --frozen-lockfile
3030

31+
- name: Calculate and post handler sizes
32+
# TODO: handle commenting for fork/dependabot PRs somehow, either through a locked-down web API, periodic workflow, or pull_request_target event.
33+
if: (matrix.node-version == '14.x' && startsWith(github.head_ref, 'dependabot/') == false && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
34+
env:
35+
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
36+
GITHUB_NEW_SHA: ${{ github.event.pull_request.head.sha }}
37+
GITHUB_BASE_SHA: ${{ github.event.pull_request.base.sha }}
38+
PULL_REQUEST_ID: ${{ github.event.number }}
39+
run: yarn handlers:comment-handler-sizes
40+
3141
- run: yarn test
3242

3343
- run: yarn integration
@@ -45,11 +55,11 @@ jobs:
4555
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_ST }}
4656
AWS_DEFAULT_REGION: us-east-1
4757
GITHUB_SHA: ${{ github.sha }}
48-
run: yarn upload-handler-sizes
58+
run: yarn handlers:upload-handler-sizes
4959

5060
start-e2e-tests:
51-
# Note: we only run e2e tests automatically if this PR is not from a fork, as forks won't have access to secrets
52-
if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) }}
61+
# Note: we only run e2e tests automatically if this PR is not from a fork or dependabot, as forks won't have access to secrets
62+
if: ${{ startsWith(github.head_ref, 'dependabot/') == false && github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) }}
5363
runs-on: ubuntu-latest
5464

5565
steps:

package.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"integration": "jest --runInBand --config jest.integration.config.json --setupTestFrameworkScriptFile=./jest.integration.setup.js",
2727
"postinstall": "yarn packages-install && opencollective-postinstall",
2828
"docs": "cd documentation && yarn && yarn build",
29-
"upload-handler-sizes": "ts-node scripts/upload-handler-sizes.ts"
29+
"handlers:upload-handler-sizes": "ts-node scripts/upload-handler-sizes.ts",
30+
"handlers:comment-handler-sizes": "ts-node scripts/comment-handler-sizes.ts"
3031
},
3132
"repository": {
3233
"type": "git",
@@ -47,6 +48,9 @@
4748
"@sls-next/next-aws-cloudfront": "link:./packages/compat-layers/lambda-at-edge-compat",
4849
"@types/fs-extra": "^9.0.1",
4950
"@types/jest": "^26.0.23",
51+
"@types/lodash": "^4.14.170",
52+
"@types/node": "^15.12.5",
53+
"@types/node-fetch": "^2.5.10",
5054
"@types/react": "^17.0.9",
5155
"@types/react-dom": "^17.0.6",
5256
"@types/webpack": "^5.28.0",
@@ -117,7 +121,9 @@
117121
]
118122
},
119123
"dependencies": {
120-
"opencollective-postinstall": "^2.0.3"
124+
"opencollective-postinstall": "^2.0.3",
125+
"lodash": "^4.17.21",
126+
"node-fetch": "^2.6.1"
121127
},
122128
"collective": {
123129
"type": "opencollective",
@@ -133,6 +139,6 @@
133139
},
134140
"resolutions": {
135141
"which": "^2.0.1",
136-
"lodash": "^4.17.19"
142+
"lodash": "^4.17.21"
137143
}
138144
}

scripts/comment-handler-sizes.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#!/usr/bin/env node
2+
3+
import fetch from "node-fetch";
4+
import { calculateHandlerSizes } from "./handler-size-utils";
5+
import { Octokit } from "@octokit/rest";
6+
import * as _ from "lodash";
7+
8+
/**
9+
* Get sizes that were calculated from existing commit SHA
10+
* @param commitSha
11+
*/
12+
const getCommitSizes = async (
13+
commitSha: string
14+
): Promise<Record<string, any>> => {
15+
const SIZES_URL =
16+
process.env.SIZES_URL ?? "https://d3m7nebxuhlnm8.cloudfront.net";
17+
18+
const url = `${SIZES_URL}/sizes-github-sha-${commitSha}.json`;
19+
20+
console.info("Retrieving url at: " + url);
21+
22+
const response = await fetch(url);
23+
24+
if (response.ok) {
25+
return JSON.parse(await response.text());
26+
} else {
27+
console.warn(
28+
"Unable to get commit sizes due to response status: " + response.status
29+
);
30+
return {};
31+
}
32+
};
33+
34+
const postCommentToPullRequest = async (
35+
prNumber: number,
36+
comment: string
37+
): Promise<void> => {
38+
const octokit = new Octokit({
39+
auth: `token ${process.env.GITHUB_TOKEN}`
40+
});
41+
42+
// Try to find existing report comment
43+
const comments = await octokit.issues.listComments({
44+
owner: "serverless-nextjs",
45+
repo: "serverless-next.js",
46+
issue_number: prNumber
47+
});
48+
49+
let existingCommentId;
50+
51+
for (const comment of comments.data) {
52+
if (
53+
comment.body?.includes("# Handler Size Report") &&
54+
comment.user?.login === "slsnextbot"
55+
) {
56+
existingCommentId = comment.id;
57+
break;
58+
}
59+
}
60+
61+
if (existingCommentId) {
62+
await octokit.issues.updateComment({
63+
comment_id: existingCommentId,
64+
owner: "serverless-nextjs",
65+
repo: "serverless-next.js",
66+
issue_number: prNumber,
67+
body: comment
68+
});
69+
} else {
70+
await octokit.issues.createComment({
71+
owner: "serverless-nextjs",
72+
repo: "serverless-next.js",
73+
issue_number: prNumber,
74+
body: comment
75+
});
76+
}
77+
};
78+
79+
const main = async (): Promise<void> => {
80+
const PULL_REQUEST_ID = parseInt(process.env.PULL_REQUEST_ID ?? "0");
81+
const GITHUB_BASE_SHA = process.env.GITHUB_BASE_SHA ?? "";
82+
const GITHUB_NEW_SHA = process.env.GITHUB_NEW_SHA ?? "";
83+
84+
console.info("Get base commit's sizes");
85+
86+
// Get sizes from base branch commit
87+
const baseSizes = await getCommitSizes(GITHUB_BASE_SHA);
88+
89+
console.info("Calculate all uncompressed handler sizes");
90+
91+
// Get sizes from PR branch latest commit
92+
const newSizes: Record<string, any> = calculateHandlerSizes();
93+
94+
let output = "# Handler Size Report\n";
95+
96+
if (_.isEqual(baseSizes, newSizes)) {
97+
output += "> No changes to handler sizes.\n";
98+
} else {
99+
output += "> There are changes to handler sizes. Please review.";
100+
}
101+
102+
output += `### Base Handler Sizes (kB) (commit ${GITHUB_BASE_SHA})\n`;
103+
output += "```ts\n";
104+
output += JSON.stringify(baseSizes, null, 4) + "\n";
105+
output += "```\n";
106+
output += `### New Handler Sizes (kB) (commit ${GITHUB_NEW_SHA})\n`;
107+
output += "```ts\n";
108+
output += JSON.stringify(newSizes, null, 4) + "\n";
109+
output += "```\n";
110+
111+
// Post comment to pull request
112+
await postCommentToPullRequest(PULL_REQUEST_ID, output);
113+
};
114+
115+
main()
116+
.then(() => {
117+
console.info("Commented handler sizes successfully.");
118+
process.exit(0);
119+
})
120+
.catch((error) => {
121+
console.error(`Unhandled error: ${error}`);
122+
process.exit(1);
123+
});

scripts/handler-size-utils.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import * as path from "path";
2+
import * as fs from "fs";
3+
4+
type HandlerConfiguration = {
5+
path: string;
6+
handlers: Record<string, Record<string, string>>;
7+
};
8+
9+
export const PLATFORM_CONFIGS: Record<string, HandlerConfiguration> = {
10+
"Lambda@Edge": {
11+
path: "packages/libs/lambda-at-edge",
12+
handlers: {
13+
"Default Lambda": {
14+
Standard: "dist/default-handler/standard",
15+
Minified: "dist/default-handler/minified"
16+
},
17+
"API Lambda": {
18+
Standard: "dist/api-handler/standard",
19+
Minified: "dist/api-handler/minified"
20+
},
21+
"Image Lambda": {
22+
Standard: "dist/image-handler/standard",
23+
Minified: "dist/image-handler/minified"
24+
},
25+
"Regeneration Lambda": {
26+
Standard: "dist/regeneration-handler/standard",
27+
Minified: "dist/regeneration-handler/minified"
28+
}
29+
}
30+
}
31+
};
32+
33+
export const getDirectorySizeInKilobytes = (
34+
directoryPath: string
35+
): number | undefined => {
36+
let size = 0;
37+
38+
if (fs.existsSync(directoryPath)) {
39+
fs.readdirSync(directoryPath).forEach((file) => {
40+
size += fs.statSync(path.join(directoryPath, file)).size;
41+
});
42+
return Math.round(size / 1024);
43+
} else {
44+
return undefined;
45+
}
46+
};
47+
48+
export const calculateHandlerSizes = (): Record<string, any> => {
49+
const sizes: Record<string, any> = {};
50+
51+
for (const [platform, platformConfig] of Object.entries(PLATFORM_CONFIGS)) {
52+
sizes[platform] = {};
53+
const packagePath = platformConfig.path;
54+
for (const [handler, handlerConfig] of Object.entries(
55+
platformConfig.handlers
56+
)) {
57+
sizes[platform][handler] = {};
58+
for (const [handlerType, handlerPath] of Object.entries(handlerConfig)) {
59+
const relativePath = path.join(packagePath, handlerPath);
60+
sizes[platform][handler][handlerType] =
61+
getDirectorySizeInKilobytes(relativePath);
62+
}
63+
}
64+
}
65+
66+
return sizes;
67+
};

scripts/upload-handler-sizes.ts

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,7 @@
11
#!/usr/bin/env node
22

3-
import * as path from "path";
4-
import * as fs from "fs";
53
import * as AWS from "aws-sdk";
6-
7-
type HandlerConfiguration = {
8-
path: string;
9-
handlers: Record<string, Record<string, string>>;
10-
};
11-
12-
const PLATFORM_CONFIGS: Record<string, HandlerConfiguration> = {
13-
"Lambda@Edge": {
14-
path: "packages/libs/lambda-at-edge",
15-
handlers: {
16-
"Default Lambda": {
17-
Standard: "dist/default-handler/standard",
18-
Minified: "dist/default-handler/minified"
19-
},
20-
"API Lambda": {
21-
Standard: "dist/api-handler/standard",
22-
Minified: "dist/api-handler/minified"
23-
},
24-
"Image Lambda": {
25-
Standard: "dist/image-handler/standard",
26-
Minified: "dist/image-handler/minified"
27-
},
28-
"Regeneration Lambda": {
29-
Standard: "dist/regeneration-handler/standard",
30-
Minified: "dist/regeneration-handler/minified"
31-
}
32-
}
33-
}
34-
};
35-
36-
const getDirectorySizeInKilobytes = (
37-
directoryPath: string
38-
): number | undefined => {
39-
let size = 0;
40-
41-
if (fs.existsSync(directoryPath)) {
42-
fs.readdirSync(directoryPath).forEach((file) => {
43-
size += fs.statSync(path.join(directoryPath, file)).size;
44-
});
45-
return Math.round(size / 1024);
46-
} else {
47-
return undefined;
48-
}
49-
};
4+
import { handlerSizeUtils } from "./handler-size-utils";
505

516
const uploadHandlerSizesToS3 = async (
527
sizes: Record<string, any>
@@ -65,22 +20,7 @@ const uploadHandlerSizesToS3 = async (
6520

6621
console.info("Calculate all uncompressed handler sizes");
6722

68-
const sizes: Record<string, any> = {};
69-
70-
for (const [platform, platformConfig] of Object.entries(PLATFORM_CONFIGS)) {
71-
sizes[platform] = {};
72-
const packagePath = platformConfig.path;
73-
for (const [handler, handlerConfig] of Object.entries(
74-
platformConfig.handlers
75-
)) {
76-
sizes[platform][handler] = {};
77-
for (const [handlerType, handlerPath] of Object.entries(handlerConfig)) {
78-
const relativePath = path.join(packagePath, handlerPath);
79-
sizes[platform][handler][handlerType] =
80-
getDirectorySizeInKilobytes(relativePath);
81-
}
82-
}
83-
}
23+
const sizes: Record<string, any> = handlerSizeUtils();
8424

8525
console.log("Calculated sizes: " + JSON.stringify(sizes, null, 2));
8626

yarn.lock

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3507,7 +3507,7 @@
35073507
dependencies:
35083508
"@types/node" "*"
35093509

3510-
"@types/lodash@^4.14.123":
3510+
"@types/lodash@^4.14.123", "@types/lodash@^4.14.170":
35113511
version "4.14.170"
35123512
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz#0d67711d4bf7f4ca5147e9091b847479b87925d6"
35133513
integrity sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==
@@ -3527,6 +3527,14 @@
35273527
resolved "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"
35283528
integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
35293529

3530+
"@types/node-fetch@^2.5.10":
3531+
version "2.5.10"
3532+
resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.10.tgz#9b4d4a0425562f9fcea70b12cb3fcdd946ca8132"
3533+
integrity sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==
3534+
dependencies:
3535+
"@types/node" "*"
3536+
form-data "^3.0.0"
3537+
35303538
"@types/node@*":
35313539
version "15.3.1"
35323540
resolved "https://registry.npmjs.org/@types/node/-/node-15.3.1.tgz#23a06b87eedb524016616e886b116b8fdcb180af"
@@ -3537,6 +3545,11 @@
35373545
resolved "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz#1f2b42c4be7156ff4a6f914b2fb03d05fa84e38d"
35383546
integrity sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==
35393547

3548+
"@types/node@^15.12.5":
3549+
version "15.12.5"
3550+
resolved "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz#9a78318a45d75c9523d2396131bd3cca54b2d185"
3551+
integrity sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg==
3552+
35403553
"@types/normalize-package-data@^2.4.0":
35413554
version "2.4.0"
35423555
resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"

0 commit comments

Comments
 (0)