From 9805bd3a6d25c366c219c357d26ccc74691d8e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Tue, 17 Jun 2025 10:43:17 +0200 Subject: [PATCH] ci: Monitor client bundle size (#16327) --- .bundlemonrc.json | 30 +++++++++ .github/workflows/ci-pull-requests.yml | 54 ++++++++++++++++ package.json | 1 + pnpm-lock.yaml | 89 ++++++++++++++++++++++++-- 4 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 .bundlemonrc.json diff --git a/.bundlemonrc.json b/.bundlemonrc.json new file mode 100644 index 0000000000..0bbf40d6bc --- /dev/null +++ b/.bundlemonrc.json @@ -0,0 +1,30 @@ +{ + "baseDir": "packages/frontend/editor-ui/dist", + "defaultCompression": "gzip", + "reportOutput": [ + [ + "github", + { + "checkRun": true, + "commitStatus": "off", + "prComment": true + } + ] + ], + "files": [ + { + "path": "*.wasm", + "friendlyName": "WASM Dependencies" + } + ], + "groups": [ + { + "groupName": "Editor UI - Total JS Size", + "path": "**/*.js" + }, + { + "groupName": "Editor UI - Total CSS Size", + "path": "**/*.css" + } + ] +} diff --git a/.github/workflows/ci-pull-requests.yml b/.github/workflows/ci-pull-requests.yml index c0eef22949..8f534f1494 100644 --- a/.github/workflows/ci-pull-requests.yml +++ b/.github/workflows/ci-pull-requests.yml @@ -12,11 +12,26 @@ jobs: runs-on: blacksmith-2vcpu-ubuntu-2204 env: NODE_OPTIONS: '--max-old-space-size=4096' + outputs: + frontend_changed: ${{ steps.paths-filter.outputs.frontend == 'true' }} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: refs/pull/${{ github.event.pull_request.number }}/merge + - name: Check for frontend changes + uses: dorny/paths-filter@v3 + id: paths-filter + with: + filters: | + frontend: + - packages/frontend/** + - packages/@n8n/design-system/** + - packages/@n8n/chat/** + - packages/@n8n/codemirror-lang/** + - .bundlemonrc.json + - .github/workflows/ci-pull-requests.yml + - name: Setup Environment and Build Project uses: ./.github/actions/setup-and-build with: @@ -29,6 +44,45 @@ jobs: - name: Run typecheck run: pnpm typecheck + - name: Upload Frontend Build Artifacts + if: steps.paths-filter.outputs.frontend == 'true' + uses: actions/upload-artifact@v4 + with: + name: editor-ui-dist + path: packages/frontend/editor-ui/dist/ + retention-days: 1 + + bundle-size-check: + name: Bundle Size Check + needs: install-and-build + if: needs.install-and-build.outputs.frontend_changed == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: refs/pull/${{ github.event.pull_request.number }}/merge + + - name: Setup pnpm CLI + uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: '22.x' + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Download Frontend Build Artifacts + uses: actions/download-artifact@v4 + with: + name: editor-ui-dist + path: packages/frontend/editor-ui/dist/ + + - name: BundleMon + uses: lironer/bundlemon-action@v1.2.0 + unit-test: name: Unit tests uses: ./.github/workflows/units-tests-reusable.yml diff --git a/package.json b/package.json index ccdbfa4a66..b6352b4d37 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@types/node": "*", "@types/supertest": "^6.0.3", "babel-plugin-transform-import-meta": "^2.3.2", + "bundlemon": "^3.1.0", "cross-env": "^7.0.3", "jest": "^29.6.2", "jest-environment-jsdom": "^29.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f29a4554c2..506c786a3a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -241,6 +241,9 @@ importers: babel-plugin-transform-import-meta: specifier: ^2.3.2 version: 2.3.3(@babel/core@7.26.10) + bundlemon: + specifier: ^3.1.0 + version: 3.1.0(typescript@5.8.2) cross-env: specifier: ^7.0.3 version: 7.0.3 @@ -7755,6 +7758,10 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + brotli-size@4.0.0: + resolution: {integrity: sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==} + engines: {node: '>= 10.16.0'} + browser-assert@1.2.1: resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==} @@ -7822,6 +7829,15 @@ packages: peerDependencies: esbuild: ^0.24.0 + bundlemon-utils@2.0.1: + resolution: {integrity: sha512-7wxHoOlzICvQyMRfVqoBpnM5pJt1JdcUxsYPNiFx3RlVmUEANh2xdEyoyTsVCqzeJC3rn+AbPuiermBwA3szAQ==} + engines: {node: '>=18'} + + bundlemon@3.1.0: + resolution: {integrity: sha512-8PAomH/fzAD/aXUKmphKmPm4Tl2L7mo51AAalO0EVAZE0cik58AM2x0CVdw4jutD069U2rSyRQstxHo2NEr+9Q==} + engines: {node: '>=18'} + hasBin: true + busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -8273,6 +8289,15 @@ packages: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: ^5.8.2 + peerDependenciesMeta: + typescript: + optional: true + cpu-features@0.0.10: resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==} engines: {node: '>=10.0.0'} @@ -8741,6 +8766,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + duplexer@0.1.1: + resolution: {integrity: sha512-sxNZ+ljy+RA1maXoUReeqBBpBC6RLKmg5ewzV+x+mSETmWNoKdZN6vcQjpFROemza23hGFskJtFNoUWUaQ+R4Q==} + duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} @@ -9687,6 +9715,10 @@ packages: resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} engines: {node: '>=14.0.0'} + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + handlebars@4.7.8: resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} engines: {node: '>=0.4.7'} @@ -20944,6 +20976,11 @@ snapshots: axios: 1.8.3 is-retry-allowed: 2.2.0 + axios-retry@4.5.0(axios@1.9.0): + dependencies: + axios: 1.9.0 + is-retry-allowed: 2.2.0 + axios@1.8.3: dependencies: follow-redirects: 1.15.9(debug@4.3.6) @@ -21158,6 +21195,10 @@ snapshots: dependencies: fill-range: 7.1.1 + brotli-size@4.0.0: + dependencies: + duplexer: 0.1.1 + browser-assert@1.2.1: {} browser-request@0.3.3: {} @@ -21224,6 +21265,27 @@ snapshots: esbuild: 0.24.0 load-tsconfig: 0.2.5 + bundlemon-utils@2.0.1: + dependencies: + bytes: 3.1.2 + + bundlemon@3.1.0(typescript@5.8.2): + dependencies: + axios: 1.9.0 + axios-retry: 4.5.0(axios@1.9.0) + brotli-size: 4.0.0 + bundlemon-utils: 2.0.1 + bytes: 3.1.2 + chalk: 4.1.2 + commander: 11.1.0 + cosmiconfig: 8.3.6(typescript@5.8.2) + gzip-size: 6.0.0 + micromatch: 4.0.8 + yup: 0.32.11 + transitivePeerDependencies: + - debug + - typescript + busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -21729,6 +21791,15 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 + cosmiconfig@8.3.6(typescript@5.8.2): + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.8.2 + cpu-features@0.0.10: dependencies: buildcheck: 0.0.6 @@ -22230,6 +22301,8 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + duplexer@0.1.1: {} + duplexer@0.1.2: {} duplexify@4.1.3: @@ -22591,7 +22664,7 @@ snapshots: eslint-import-resolver-node@0.3.9: dependencies: - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) is-core-module: 2.13.1 resolve: 1.22.8 transitivePeerDependencies: @@ -22616,7 +22689,7 @@ snapshots: eslint-module-utils@2.8.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) optionalDependencies: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.8.2) eslint: 8.57.0 @@ -22636,7 +22709,7 @@ snapshots: array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 array.prototype.flatmap: 1.3.2 - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 @@ -23465,7 +23538,7 @@ snapshots: array-parallel: 0.1.3 array-series: 0.1.5 cross-spawn: 7.0.6 - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -23555,6 +23628,10 @@ snapshots: - encoding - supports-color + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + handlebars@4.7.8: dependencies: minimist: 1.2.8 @@ -26362,7 +26439,7 @@ snapshots: pdf-parse@1.1.1: dependencies: - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) node-ensure: 0.0.0 transitivePeerDependencies: - supports-color @@ -27191,7 +27268,7 @@ snapshots: rhea@1.0.24: dependencies: - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color