This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch change/33615-chart-data-query-context
in repository https://gitbox.apache.org/repos/asf/superset.git

commit b92270e3d43628f8a6e827c34bcb7c255c895d6a
Author: Eugene Olkhovski <[email protected]>
AuthorDate: Fri Aug 28 07:14:18 2026 -0400

    fix(charts): wire query_context parity bundle into build + registry smoke 
check (#33615)
    
    Make exact frontend-parity query_context synthesis the default in 
deployments
    and guard the generated registry (addresses review):
    
    - build-backend-querycontext: bundle non-JS assets (fonts/CSS/SVG/images) 
with
      the esbuild `empty` loader so the buildQuery bundle builds cleanly even 
as the
      registry broadens (backend runs only generateQueryContext in V8, never 
renders)
    - package.json: run the bundle build in the supported flow via a `postbuild`
      hook, and add gen/check scripts for the registry
    - gen-qc-registry: add `--check` mode; CI (lint-frontend) now regenerates 
the
      registry and rebuilds the bundle so a plugin added/removed without
      regenerating fails the build (smoke check requested in review)
    - MANIFEST.in: ship superset/commands/chart/_bundles/*.js so packaged
      distributions carry the bundle instead of silently falling back
    - pyproject: add optional `querycontext` extra (py-mini-racer) for the V8 
runtime
    - docs: README + generator docstring describe the wired build/package flow
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
 .github/workflows/superset-frontend.yml            |  5 +++++
 .gitignore                                         |  5 +++--
 MANIFEST.in                                        |  4 ++++
 pyproject.toml                                     |  5 +++++
 superset-frontend/package.json                     |  3 +++
 .../scripts/build-backend-querycontext.mjs         | 20 ++++++++++++++++--
 superset-frontend/scripts/gen-qc-registry.mjs      | 19 ++++++++++++++++-
 superset/commands/chart/_bundles/README.md         | 24 +++++++++++++++++-----
 superset/commands/chart/query_context_generator.py |  9 +++++---
 9 files changed, 81 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/superset-frontend.yml 
b/.github/workflows/superset-frontend.yml
index 9b7896c1176..dfdac041c2b 100644
--- a/.github/workflows/superset-frontend.yml
+++ b/.github/workflows/superset-frontend.yml
@@ -163,6 +163,11 @@ jobs:
           docker run --rm $TAG bash -c \
           "npm i && npm run plugins:build && npm run type"
 
+      - name: backend query_context registry + bundle (superset #33615)
+        run: |
+          docker run --rm $TAG bash -c \
+          "npm i && npm run check:backend-querycontext-registry && npm run 
build:backend-querycontext"
+
   validate-frontend:
     needs: frontend-build
     if: needs.frontend-build.outputs.should-run == 'true'
diff --git a/.gitignore b/.gitignore
index 9c17c161824..9e930be34a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -128,8 +128,9 @@ docker-compose.override.yml
 
 .temp_cache
 
-# Generated backend query_context bundle (built via
-# `npm run build:backend-querycontext`; see 
superset/commands/chart/_bundles/README.md)
+# Generated backend query_context bundle (built by `npm run build` via its
+# postbuild hook; shipped in packages through MANIFEST.in even though it stays
+# untracked here — see superset/commands/chart/_bundles/README.md)
 superset/commands/chart/_bundles/*.js
 
 # Jest test report
diff --git a/MANIFEST.in b/MANIFEST.in
index 4d7a98b2a7a..66efe22c3af 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -24,4 +24,8 @@ recursive-include superset/migrations *
 recursive-include superset/templates *
 recursive-include superset/translations *
 recursive-include superset/static *
+# Backend query_context parity bundle (#33615): a build artifact produced by
+# `npm run build` (postbuild). Ship it so deployments get exact frontend parity
+# by default instead of silently falling back to the generic derivation.
+recursive-include superset/commands/chart/_bundles *.js
 recursive-exclude tests *
diff --git a/pyproject.toml b/pyproject.toml
index 79ed07cbbfb..32aae99c2a6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -254,6 +254,11 @@ postgres = ["psycopg2-binary==2.9.13"]
 presto = ["pyhive[presto]>=0.7.0"]
 trino = ["trino>=0.339.0"]
 prophet = ["prophet>=1.4.0, <2"]
+# Exact frontend-parity query_context synthesis for chart import (#33615): runs
+# the real `buildQuery` bundle in V8 via py_mini_racer. Optional — without it 
the
+# importer falls back to the pure-Python generic derivation. Install this extra
+# (and ship the bundle, built by `npm run build`) to make exact parity the 
default.
+querycontext = ["py-mini-racer>=0.12.4, <1.0"]
 # sqlalchemy-redshift cuts hard from SQLAlchemy 1.4-only (0.8.x) to 2.0-only
 # (>=1.0.0) with no dual-compat release. Bumped now that Superset's own
 # SQLAlchemy 2.0 core bump has landed (discussion #40273).
diff --git a/superset-frontend/package.json b/superset-frontend/package.json
index 827d8a179ab..922327a95d7 100644
--- a/superset-frontend/package.json
+++ b/superset-frontend/package.json
@@ -41,6 +41,9 @@
     "_format": "oxfmt 
'./{src,spec,cypress-base,plugins,packages,.storybook}/**/*{.js,.jsx,.ts,.tsx,.css,.scss,.sass,.json}'",
     "build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 
NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --color 
--mode production",
     "build:backend-querycontext": "node 
scripts/build-backend-querycontext.mjs",
+    "postbuild": "npm run build:backend-querycontext",
+    "gen:backend-querycontext-registry": "node scripts/gen-qc-registry.mjs",
+    "check:backend-querycontext-registry": "node scripts/gen-qc-registry.mjs 
--check",
     "build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 
NODE_ENV=development webpack --mode=development --color",
     "build-instrumented": "cross-env NODE_ENV=production 
BABEL_ENV=instrumented webpack --mode=production --color",
     "build-storybook": "storybook build",
diff --git a/superset-frontend/scripts/build-backend-querycontext.mjs 
b/superset-frontend/scripts/build-backend-querycontext.mjs
index 67a3adba680..3d811e14d2d 100644
--- a/superset-frontend/scripts/build-backend-querycontext.mjs
+++ b/superset-frontend/scripts/build-backend-querycontext.mjs
@@ -58,8 +58,24 @@ build({
   target: 'es2020',
   legalComments: 'none',
   logLevel: 'info',
-  // esbuild infers the `ts` loader from the .ts extension; keep JSX off (these
-  // buildQuery modules are pure TS, no React).
+  // `buildQuery` modules are pure query logic, but they are reached through
+  // barrel imports that transitively pull in non-JS assets (fonts, CSS, SVGs,
+  // images) from the theme/UI layer. The backend runs only 
`generateQueryContext`
+  // in V8 and never renders any of that, so drop those assets with the `empty`
+  // loader instead of failing to bundle. (esbuild infers the `ts` loader from 
the
+  // .ts extension; these modules are pure TS, no JSX.)
+  loader: {
+    '.css': 'empty',
+    '.svg': 'empty',
+    '.png': 'empty',
+    '.jpg': 'empty',
+    '.jpeg': 'empty',
+    '.gif': 'empty',
+    '.woff': 'empty',
+    '.woff2': 'empty',
+    '.ttf': 'empty',
+    '.eot': 'empty',
+  },
 })
   .then(() => {
     // eslint-disable-next-line no-console
diff --git a/superset-frontend/scripts/gen-qc-registry.mjs 
b/superset-frontend/scripts/gen-qc-registry.mjs
index 5a6e5bd4364..3c798c5ace2 100644
--- a/superset-frontend/scripts/gen-qc-registry.mjs
+++ b/superset-frontend/scripts/gen-qc-registry.mjs
@@ -206,7 +206,24 @@ const header = `// Licensed to the Apache Software 
Foundation (ASF) under one
 // GENERATED by superset-frontend/scripts/gen-qc-registry.mjs — DO NOT EDIT.
 // Re-run: node scripts/gen-qc-registry.mjs
 `;
-writeFileSync(OUT, `${header}\n${imports}\n${body}`, 'utf8');
+const generated = `${header}\n${imports}\n${body}`;
+
+// `--check` (smoke check): fail instead of writing if the committed registry 
is
+// stale, so CI catches a plugin added/removed without regenerating.
+if (process.argv.includes('--check')) {
+  const current = existsSync(OUT) ? readFileSync(OUT, 'utf8') : '';
+  if (current !== generated) {
+    console.error(
+      `${path.relative(FE, OUT)} is out of date. ` +
+        'Run `npm run gen:backend-querycontext-registry` and commit the 
result.',
+    );
+    process.exit(1);
+  }
+  console.log(`${path.relative(FE, OUT)} is up to date.`);
+  process.exit(0);
+}
+
+writeFileSync(OUT, generated, 'utf8');
 
 console.log(`buildQuery modules: ${buildQueryFiles.length}`);
 console.log(`viz keys mapped: ${entries.length}`);
diff --git a/superset/commands/chart/_bundles/README.md 
b/superset/commands/chart/_bundles/README.md
index d27797fcfa2..3ebff76af53 100644
--- a/superset/commands/chart/_bundles/README.md
+++ b/superset/commands/chart/_bundles/README.md
@@ -23,17 +23,31 @@ This directory holds the bundled frontend `buildQuery` code 
that the backend
 runs in V8 (`py_mini_racer`) to synthesize a faithful `query_context` for
 imported charts (Apache Superset #33615).
 
-**`query_context_bundle.js` is generated, not committed.** Build it with:
+**`query_context_bundle.js` is a generated build artifact, not committed.** It 
is
+produced automatically as part of the standard frontend build:
 
 ```bash
 cd superset-frontend
-npm run build:backend-querycontext
+npm run build            # runs build:backend-querycontext via the postbuild 
hook
 ```
 
+or on its own with `npm run build:backend-querycontext`.
+
+Because the supported build produces it and `MANIFEST.in` ships
+`superset/commands/chart/_bundles/*.js`, packaged Superset distributions carry 
the
+bundle by default (it is `.gitignore`d in the working tree but included at 
build
+time).
+
 Source entry: `superset-frontend/src/backend-querycontext/entry.ts`.
 Consumer: `superset/commands/chart/query_context_generator.py`.
 
-When the bundle is absent the generator degrades gracefully and the importer
-falls back to the pure-Python generic derivation in
+To enable exact parity at runtime, install the V8 runtime extra:
+
+```bash
+pip install "apache-superset[querycontext]"   # pulls py-mini-racer
+```
+
+When the bundle or `py_mini_racer` is absent the generator degrades gracefully 
and
+the importer falls back to the pure-Python generic derivation in
 `superset/commands/chart/query_context_builder.py` — nothing breaks; parity 
just
-isn't available until the bundle is built (a packaging/CI step).
+isn't available until both are present.
diff --git a/superset/commands/chart/query_context_generator.py 
b/superset/commands/chart/query_context_generator.py
index 9635d3409fc..4f31420e5a0 100644
--- a/superset/commands/chart/query_context_generator.py
+++ b/superset/commands/chart/query_context_generator.py
@@ -29,9 +29,12 @@ not been built, or evaluation fails, 
:meth:`QueryContextGenerator.generate`
 returns ``None`` and the caller falls back to the pure-Python generic 
derivation
 
(:func:`superset.commands.chart.query_context_builder.build_query_context_config`).
 
-Build the bundle with ``npm run build:backend-querycontext`` (from
-``superset-frontend/``); the artifact lands at
-``superset/commands/chart/_bundles/query_context_bundle.js``.
+The bundle is produced by the standard frontend build (``npm run build`` runs 
it
+via a ``postbuild`` hook; or ``npm run build:backend-querycontext`` alone) and
+lands at ``superset/commands/chart/_bundles/query_context_bundle.js``, shipped 
in
+packaged distributions via ``MANIFEST.in``. Install the V8 runtime with the
+``querycontext`` extra (``pip install "apache-superset[querycontext]"``) to 
make
+exact parity the default rather than the fallback.
 """
 
 from __future__ import annotations

Reply via email to