diff --git a/.github/scripts/compare-packages-size.js b/.github/scripts/compare-packages-size.js index 172b39e..b1e6a5c 100644 --- a/.github/scripts/compare-packages-size.js +++ b/.github/scripts/compare-packages-size.js @@ -1,8 +1,10 @@ import path from "node:path"; import { execSync as exec } from "node:child_process"; -import { statSync as stat, existsSync as exists } from "node:fs"; +import { statSync as stat, existsSync as exists, writeFileSync as write_file } from "node:fs"; import { globSync as glob } from "glob"; +const MAIN_WORKTREE = ".worktrees/main"; + function size(file) { return exists(file) ? stat(file).size : null; } @@ -17,44 +19,73 @@ function format(bytes) { : `${bytes} B`; } -function delta(a, b) { - if (a == null || b == null) { +function delta(pr, main) { + if (pr == null || main == null) { return null; } - return a - b; + return pr - main; } -function icon(d) { - if (d == null) { +function icon(delta) { + if (delta == null) { return "—"; } - if (d > 0) return "⬆️"; - if (d < 0) return "⬇️"; - return "➡️"; + if (delta > 0) return "🔴"; + if (delta < 0) return "🟢"; + return ""; } -const pr_files = glob("dist/**/*.min.js"); -const pr_sizes = Object.fromEntries(pr_files.map(f => [f, size(f)])); - -exec("git fetch origin main", { stdio: "inherit" }); -exec("git checkout origin/main", { stdio: "ignore" }); -exec("npm ci --include=dev", { stdio: "inherit" }); -exec("npm run build", { stdio: "inherit" }); - -const main_sizes = Object.fromEntries(pr_files.map(f => [f, size(f)])); +function has_local_origin_main() { + try { + exec('git show-ref --verify --quiet refs/remotes/origin/main', { stdio: ["pipe", "pipe", "pipe"] }); + return true; + } + catch { + return false; + } +} -let md = ` +function generate_report(files, pr, main) { + let md = ` ### 📦 Bundle size comparison -| Name | main | PR | Δ | -|------|------|----|---| +| Name | main | PR | Δ | Delta | +|------|-----:|---:|---|-------:| `; -for (const file of pr_files) { - const d = delta(pr_sizes[file], main_sizes[file]); + for (const file of files) { + const d = delta(pr[file], main[file]); + + md += `| ${path.basename(file)} | ${format(main[file])} | ${format(pr[file])} | ${icon(d)} | ${format(d)} |\n`; + } - md += `| \`${path.basename(file)}\` | ${format(main_sizes[file])} | ${format(pr_sizes[file])} | ${icon(d)} ${format(d)} |\n`; + console.log(md); + process.env.SIZE_REPORT_OUTPUT && write_file(process.env.SIZE_REPORT_OUTPUT, md.trim()); } -console.log(md); +try { + // + // PR build + // + exec("npm run build", { stdio: "inherit" }); + + const pr_files = glob("dist/**/*.min.js"); + const pr_sizes = Object.fromEntries(pr_files.map(f => [f, size(f)])); + + // + // Main build + // + has_local_origin_main() || exec("git fetch origin main", { stdio: "inherit" }); + exec(`git worktree add ${MAIN_WORKTREE} origin/main`, { stdio: "ignore" }); + exec("npm ci --include=dev", { cwd: MAIN_WORKTREE, stdio: "inherit" }); + exec("npm run build", { cwd: MAIN_WORKTREE, stdio: "inherit" }); + + const main_sizes = Object.fromEntries( + pr_files.map(f => [f, size(path.join(MAIN_WORKTREE, f))])); + + generate_report(pr_files, pr_sizes, main_sizes); +} +finally { + exec(`git worktree remove ${MAIN_WORKTREE}`, { stdio: "inherit" }); +} diff --git a/.github/workflows/pr-diff-size.yml b/.github/workflows/pr-diff-size.yml index 691562d..5ebbd61 100644 --- a/.github/workflows/pr-diff-size.yml +++ b/.github/workflows/pr-diff-size.yml @@ -27,16 +27,13 @@ jobs: uses: actions/checkout@v4 - name: Install Dependencies - run: npm ci + run: npm ci --include=dev - - name: Build - run: npm run build - env: - NODE_ENV: production - SKIP_GIT_TAG_RESOLUTION: true + - name: Prepate report path + run: echo "SIZE_REPORT_OUTPUT=$RUNNER_TEMP/comment-${{ github.event.pull_request.number }}.md" >> $GITHUB_ENV - name: Run size comparison - run: npm run size-diff-report > comment.md + run: npm run size-report env: NODE_ENV: production SKIP_GIT_TAG_RESOLUTION: true @@ -46,8 +43,8 @@ jobs: with: script: | const fs = require('fs'); - const body = fs.readFileSync('./comment.md', 'utf8'); - const pr_number = context.payload.workflow_run.pull_requests[0].number; + const body = fs.readFileSync(process.env.SIZE_REPORT_OUTPUT, 'utf8'); + const pr_number = context.issue.number; const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, diff --git a/package.json b/package.json index a18dfaa..e3f7e32 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "scripts": { "build": "cross-env NODE_ENV=production gulp build", "build:debug": "gulp build", - "size-diff-report": "node .github/scripts/compare-packages-size.js", + "size-report": "cross-env NODE_ENV=production SKIP_GIT_TAG_RESOLUTION=true node .github/scripts/compare-packages-size.js", "test": "gulp build && vitest run && playwright test", "test:playwright": "playwright test", "test:vitest": "vitest run"