←  github actions

Views:

Build Size Comparison for Pull Requests

We can write a workflow to automate and check the difference between the size of pull request and base branch build, with a nice comment on the same pull request showing the size difference and percentage change.


Here's how it will look

build-compare-comment

Prerequisites for this workflow

  • Install get-folder-size package as dev dependency, to get the size of your build folder.
npm i -D get-folder-size
  • A script which will run after your build command and get the stats of your build folder into a stats.json file. Following is the scripts/build-size.js which we will be using for the same.
/* scripts/build-size.js */

import getFolderSize from "get-folder-size";
import path from "path";
import fs from "fs";

function humanFileSize(size) {
  var i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
  return (
    (size / Math.pow(1024, i)).toFixed(2) * 1 +
    " " +
    ["B", "kB", "MB", "GB", "TB"][i]
  );
}

const getSize = async () => {
  const size = await getFolderSize.loose("./dist"); // Your build folder path here
  const readableSize = humanFileSize(size);
  return {
    size: {
      bytes: size,
      readableString: readableSize,
    },
  };
};

(async () => {
  const result = await getSize();
  const filePath = path.resolve("./stats.json");
  fs.writeFileSync(filePath, `${JSON.stringify(result)}`);
})();
  • Important: The above script needs to be merged to the base branch (before writing workflow) so that it would be available when size needs to be computed at the workflow.
  • Github Personal Access Token - official documentation for creating a personal access token.
  • A template markdown file for your comment i.e. comment.md inside your .github/workflows folder.
## Bundle Size Difference

| Old size | New size | Diff                     |
| -------- | -------- | ------------------------ |
| {OLD}    | {NEW}    | {DIFF} ({DIFF_PERCENT}%) |

Workflow to comment Build Size Comparison

The workflow will be divided into three jobs - build-base, build-pr and report. The first two jobs will build respective code and get the final build folder statistics into a stats.json file which will be eventually uploaded as artifact to be used by the report job. The report job will access the build size of both base and pull request branch and compute the difference and difference percentage and pass that information to next step to comment it on the pull request.

name: Build Size Compare

on:
  pull_request:
    branches:
      - main
    types: [opened, synchronize, reopened]

jobs:
  build-base:
    name: Build base
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          ref: ${{ github.base_ref }}

      - name: Install deps (with cache)
        uses: bahmutov/npm-install@v1.7.10
        with:
          working-directory: "./"
          useLockFile: false

      - name: Build
        run: npm run build
        env:
          CI: false

      - name: build stats file
        run: node ./scripts/build-size.js

      - name: Upload pr stats.json
        uses: actions/upload-artifact@v2
        with:
          name: base
          path: ./stats.json
          retention-days: 1

  build-pr:
    name: Build PR
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Install deps (with cache)
        uses: bahmutov/npm-install@v1.7.10
        with:
          working-directory: "./"
          useLockFile: false

      - name: Build
        run: npm run build
        env:
          CI: false

      - name: build stats file
        run: node ./scripts/build-size.js

      - name: Upload pr stats.json
        uses: actions/upload-artifact@v2
        with:
          name: pr
          path: ./stats.json
          retention-days: 1

  report:
    name: Generate report
    runs-on: ubuntu-latest
    needs: [build-base, build-pr]

    steps:
      - name: Checkout PR
        uses: actions/checkout@v2

      - name: Download base stats
        uses: actions/download-artifact@v2
        with:
          name: base
          path: base

      - name: Download PR stats
        uses: actions/download-artifact@v2
        with:
          name: pr
          path: pr

      - name: Getting build size
        id: get-build-size
        uses: actions/github-script@v6
        with:
          script: |
            const fs = require('fs');

            function humanFileSize(size) {
              var i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
              return (
                (size / Math.pow(1024, i)).toFixed(2) * 1 +
                ' ' +
                ['B', 'kB', 'MB', 'GB', 'TB'][i]
              );
            }

            const baseResultString = fs.readFileSync('./base/stats.json', 'utf-8');
            const prResultString = fs.readFileSync('./pr/stats.json', 'utf-8');
            const baseSize = JSON.parse(baseResultString).size;
            const prSize = JSON.parse(prResultString).size;
            const baseSizeString = baseSize.readableString;
            const prSizeString = prSize.readableString;
            const diffInBytes = prSize.bytes - baseSize.bytes;
            const diffSizeString = humanFileSize(diffInBytes);
            const diffPerc = (diffInBytes*100) / baseSize.bytes;

            core.setOutput("baseSizeString", baseSizeString);
            core.setOutput("prSizeString", prSizeString);
            core.setOutput("diffSizeString", diffSizeString);
            core.setOutput("percent", diffPerc.toFixed(2));

      - name: Comment
        uses: NejcZdovc/comment-pr@v1.1.1
        with:
          file: "comment.md"
        env:
          GITHUB_TOKEN: ${{secrets.GH_ACTION_EXAMPLES_PAT}}
          OLD: ${{steps.get-build-size.outputs.baseSizeString}}
          NEW: ${{steps.get-build-size.outputs.prSizeString}}
          DIFF: ${{steps.get-build-size.outputs.diffSizeString}}
          DIFF_PERCENT: ${{steps.get-build-size.outputs.percent}}

Result

I have created a new pull request with a demo image which will increase the build size, and with the above workflow we'll be getting a comment about this information. Here's the result for above workflow, you can also view it on the pull request

build-compare-result