ci(frontend): publish nightly bundle-analyzer report; add Storybook/analyzer badges

Two related visibility gaps, fixed together since both ride on the same
nightly build:

1. superset-storybook.netlify.app has been live and populated with real,
   current component stories the whole time (Netlify's own git integration
   auto-builds and deploys it, no CI workflow involved) -- but there was no
   link to it anywhere in the repo. Added a README badge.

2. BUNDLE_ANALYZER=true npm run build has always produced a browsable
   treemap of what's actually in the bundle, but only ever locally, on
   request. Now rides along in the same nightly build that already refreshes
   the bundle-size baseline (BUNDLE_ANALYZER and BUNDLE_SIZE_STATS are
   independent env-gated additions to webpack.config.js, so one production
   build produces both), publishing the treemap (report.html) to Netlify --
   the same host already trusted for Storybook and docs previews, reusing
   the existing NETLIFY_AUTH_TOKEN secret. Deliberately does not publish the
   sibling statistics.html sunburst chart: webpack.config.js documents it as
   routinely exceeding 100MB for this app (it's .gitignore'd for exactly
   that reason), too large for a static site page.

The Netlify publish step is gated on NETLIFY_BUNDLE_ANALYZER_SITE_ID and
no-ops until that secret exists -- safe to merge now. Turning it on just
needs a new (free) Netlify site named superset-bundle-analyzer and its
site ID added as that secret; nothing else in the workflow depends on it.
The README badge points at that same URL in anticipation.
This commit is contained in:
Evan Rusackas
2026-07-28 10:10:16 -07:00
parent f7e29c15d5
commit 7bdc6e0bed
2 changed files with 44 additions and 8 deletions

View File

@@ -1,11 +1,13 @@
name: Frontend bundle size (nightly baseline)
name: Frontend bundle size (nightly baseline + analyzer)
# Refreshes the bundle-size baseline that superset-frontend.yml's `bundle-size`
# job compares PRs against. Deliberately NOT triggered on every push to
# master: a day-old baseline is fine for catching relative regressions on
# PRs, and building the production bundle on every one of the many pushes
# master gets per day would burn CI time for no benefit a nightly refresh
# doesn't already cover.
# job compares PRs against, and publishes a browsable bundle-analyzer treemap
# report of the same build. Deliberately NOT triggered on every push to
# master: a day-old baseline/report is fine for catching relative
# regressions on PRs and for browsing what's actually in the bundle, and
# building the production bundle on every one of the many pushes master
# gets per day would burn CI time for no benefit a nightly refresh doesn't
# already cover.
on:
schedule:
- cron: "0 6 * * *"
@@ -65,16 +67,27 @@ jobs:
restore-keys: |
bundle-size-history-
- name: Build production bundle with stats
# BUNDLE_ANALYZER rides along in the same build as BUNDLE_SIZE_STATS --
# they're independent env-gated additions in webpack.config.js (one
# sets `config.stats`, the other pushes plugins), so one production
# build produces both the numeric stats.json and the analyzer's
# report.html. Only report.html is mounted out, not
# BUNDLE_ANALYZER's sibling `statistics.html` sunburst -- that file is
# documented in webpack.config.js as routinely exceeding 100MB for
# this app (it's .gitignore'd for exactly that reason), too large to
# publish as a static site page.
- name: Build production bundle with stats and analyzer report
run: |
mkdir -p ${{ github.workspace }}/superset-frontend/bundle-stats
mkdir -p ${{ github.workspace }}/superset-frontend/.temp_cache
mkdir -p ${{ github.workspace }}/superset/static/assets
docker run \
-v ${{ github.workspace }}/superset-frontend/bundle-stats:/app/superset-frontend/bundle-stats \
-v ${{ github.workspace }}/superset-frontend/.temp_cache:/app/superset-frontend/.temp_cache \
-v ${{ github.workspace }}/superset/static/assets:/app/superset/static/assets \
--rm $TAG \
bash -c \
"npm i && BUNDLE_SIZE_STATS=true npm run build -- --json=bundle-stats/stats.json"
"npm i && BUNDLE_SIZE_STATS=true BUNDLE_ANALYZER=true npm run build -- --json=bundle-stats/stats.json"
- name: Summarize bundle size
run: |
@@ -98,3 +111,24 @@ jobs:
with:
path: bundle-size-history.json
key: bundle-size-history-${{ github.run_id }}
# Publishes the treemap to Netlify (the same host already used for
# superset-storybook.netlify.app and docs previews, reusing the
# existing NETLIFY_AUTH_TOKEN). Skipped until
# NETLIFY_BUNDLE_ANALYZER_SITE_ID exists -- create a new (free)
# Netlify site named superset-bundle-analyzer and add its site ID as
# that secret to turn this on; nothing else in this workflow depends
# on it.
- name: Publish bundle analyzer report to Netlify
if: ${{ secrets.NETLIFY_BUNDLE_ANALYZER_SITE_ID != '' }}
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_BUNDLE_ANALYZER_SITE_ID }}
run: |
mkdir -p netlify-publish
cp superset/static/assets/report.html netlify-publish/index.html
# zizmor: ignore[adhoc-packages] - netlify-cli is a one-shot CI deploy
# tool, not an application dependency; a global/npx install has no
# lockfile context. Version pinned above the floor set by other
# ad-hoc installs in this repo (bump deliberately when upgrading).
npx --yes netlify-cli@27.0.1 deploy --prod --dir=netlify-publish

View File

@@ -31,6 +31,8 @@ under the License.
[![Open PRs](https://img.shields.io/github/issues-pr/apache/superset)](https://github.com/apache/superset/pulls)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](http://bit.ly/join-superset-slack)
[![Documentation](https://img.shields.io/badge/docs-apache.org-blue.svg)](https://superset.apache.org)
[![Storybook](https://img.shields.io/badge/storybook-live-ff4785.svg)](https://superset-storybook.netlify.app)
[![Bundle Analyzer](https://img.shields.io/badge/bundle%20analyzer-nightly-8dd6f9.svg)](https://superset-bundle-analyzer.netlify.app)
<picture width="500">
<source