Compare commits

...

447 Commits

Author SHA1 Message Date
Maxime Beauchemin
36cf9337a8 chore(list-view): make SelectOption.title an explicit typed field
Follow-up from code review on sc-104554. `SelectOption.title` was
previously accessed via the `[key: string]: unknown` index signature,
making the "plain-text fallback" contract implicit. Make it a typed
optional string so callers can rely on it and TypeScript can enforce
the shape. Simplify the label-resolution expression in `Select.tsx`
accordingly.
2026-04-21 05:09:52 +00:00
Maxime Beauchemin
d952109cbc fix(list-view): preserve user name in filter pill after navigation
In the Chart list (and other CRUD lists), filtering by a user, navigating
into an asset, and returning to the list replaced the user's name in the
filter pill with a numeric user id.

Root cause: Owner filter options supply a React element as `label` (via
`OwnerSelectLabel`, which renders name + email). When a selection was
serialized to URL / filter state, `SelectFilter.onChange` only accepted
string labels and otherwise fell back to `String(selected.value)` (the
numeric id). On return to the list, the rehydrated `{label, value}` held
the numeric id as the label and that is what the pill rendered.

Prefer the option's plain-text `title` (already set to the human-readable
name by `createFetchOwners`) before falling back to the stringified value.
Add a unit test covering both the ReactNode-with-title path and the
no-title fallback.
2026-04-21 04:51:48 +00:00
Maxime Beauchemin
151d7d76da fix(charts): set g.form_data for metric() Jinja macro on GET chart data endpoint (#39347)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 19:36:03 -07:00
Maxime Beauchemin
4f19bc4c5f fix(table): ensure dimensions appear before metrics in column order (#39346)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 17:44:26 -07:00
Beto Dealmeida
11607dde04 feat(sqllab): syntax validation for sqlite-based DB engine specs (#38698)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-04-20 18:29:51 -04:00
dependabot[bot]
e1bdb94efc chore(deps-dev): bump globals from 17.4.0 to 17.5.0 in /docs (#39479)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 15:16:03 -07:00
Beto Dealmeida
6535fdd556 chore: simplify Trino's OAuth detection (#39496) 2026-04-20 18:08:48 -04:00
Beto Dealmeida
5fb89b865d fix(oauth2): silence lock acquisition errors on token refresh (#39463)
Co-authored-by: Beto Dealmeida <beto@preset.io>
2026-04-20 18:08:33 -04:00
Amin Ghadersohi
6948e73ec7 feat(mcp): add get_chart_sql tool and expose chart filters in get_chart_info (#38700) 2026-04-20 17:50:10 -04:00
Maxime Beauchemin
c4cf03f899 fix(import): import tags during CLI native asset import (#39495)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 13:59:51 -07:00
Joe Li
d3de16c5f5 fix(dashboard): restore groupby in buildExistingColumnsSet and guard null customization config (#39416)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Richard Fogaça <richardfogaca@gmail.com>
2026-04-20 13:24:22 -07:00
bdonovan1
78fb09695b fix(chart): word cloud secondary sort prevents Druid TopN optimization when sort_by_metric enabled (#39073)
Co-authored-by: Brian Donovan <briand@netflix.com>
2026-04-20 16:28:31 -03:00
dependabot[bot]
06818008c2 chore(deps-dev): bump eslint from 10.2.0 to 10.2.1 in /superset-websocket (#39473)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 12:07:15 -07:00
dependabot[bot]
52ba4fd0cb chore(deps): bump antd from 6.3.5 to 6.3.6 in /docs (#39480)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 12:01:59 -07:00
Aitema-gmbh
4f2fa41f4e fix(a11y): WCAG 3.1.2 — set HTML lang attribute dynamically from locale (#39243)
Co-authored-by: Fedo Hagge-Kubat <office@aitema.org>
2026-04-20 11:33:10 -07:00
Kamil Gabryjelski
bf7ec853fa fix(big-number): use correct default font size for subtitle/subheader (#39493) 2026-04-20 18:21:18 +02:00
Michael S. Molina
9fe3f634ec perf(sql-lab): debounce schema browser search (#39489)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 12:59:01 -03:00
dependabot[bot]
899e9294b2 chore(deps): bump maplibre-gl from 5.22.0 to 5.23.0 in /superset-frontend (#39475)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 08:40:46 -07:00
dependabot[bot]
dc9b459b27 chore(deps): bump actions/setup-node from 6.3.0 to 6.4.0 (#39481)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 08:34:02 -07:00
wanjoc
7d3881f1da docs: Added instructions on configuring Superset SECRET_KEY (#25646)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 08:33:27 -07:00
Evan Rusackas
e5f9a6bf4b chore(lint): convert superset-ui-core chart-composition to function components (#39455)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 08:33:04 -07:00
Amin Ghadersohi
5cff657812 fix(mcp): default XY chart x-axis to dataset primary datetime column (#39421)
Co-authored-by: codeant-ai-for-open-source[bot] <244253245+codeant-ai-for-open-source[bot]@users.noreply.github.com>
2026-04-20 11:14:54 -04:00
Arunkumar S
16387b0815 fix(sqllab): remove duplicate tooltip on share query link icon (#39289) 2026-04-20 22:01:21 +07:00
Alexandru Soare
0857611a4e fix(mcp): Add defensive validator for ColumnInfo.is_nullable (#39365) 2026-04-20 13:50:31 +03:00
Geidō
51ea2c297d fix(dataset): calculated columns in virtual datasets fail when used as dynamic aggregation filter dimensions (#39004)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 13:44:53 +03:00
dependabot[bot]
fbd062165e chore(deps): bump @swc/core from 1.15.24 to 1.15.26 in /docs (#39374)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-19 21:40:19 +07:00
dependabot[bot]
55625c911f chore(deps-dev): bump timezone-mock from 1.4.0 to 1.4.2 in /superset-frontend (#38049)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-04-19 17:19:08 +07:00
dependabot[bot]
fca64de8e9 chore(deps-dev): bump prettier from 3.8.2 to 3.8.3 in /superset-frontend (#39372)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-19 11:19:22 +07:00
dependabot[bot]
03725d1aaa chore(deps): bump dompurify from 3.3.3 to 3.4.0 in /superset-frontend (#39399)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-04-19 10:58:36 +07:00
dependabot[bot]
a9487cbc84 chore(deps): bump aws-actions/amazon-ecr-login from 2.1.2 to 2.1.3 (#39403)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-18 12:51:07 +07:00
dependabot[bot]
ce5b2aa424 chore(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1 (#39320)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-18 12:49:30 +07:00
dependabot[bot]
e535dce030 chore(deps-dev): bump prettier from 3.8.1 to 3.8.3 in /docs (#39400)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-18 11:58:29 +07:00
dependabot[bot]
a7310b1fce chore(deps): bump @docusaurus/core from 3.9.2 to 3.10.0 in /docs (#39188)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-04-18 11:43:47 +07:00
dependabot[bot]
cd6ce881a5 chore(deps): bump dompurify from 3.3.3 to 3.4.0 in /docs (#39398)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-18 09:54:38 +07:00
dependabot[bot]
f0ef9f5e9c chore(deps-dev): bump webpack from 5.105.4 to 5.106.2 in /docs (#39401)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-04-18 09:52:53 +07:00
dependabot[bot]
4ae16cb140 chore(deps-dev): bump typescript-eslint from 8.58.0 to 8.58.2 in /docs (#39426)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-18 09:27:11 +07:00
David Hotham
3d85e8e23b chore: publish wheels (#36746)
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
2026-04-17 17:21:23 -03:00
Evan Rusackas
690a411cf3 chore(ci): require PMC review for CI-executed scripts (#39462)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-17 12:55:27 -07:00
JUST.in DO IT
be680408c9 fix(sqllab): enhance table explore tree with schema pinning, column sorting, and table schema refresh (#39396)
Co-authored-by: Michael S. Molina <michael.s.molina@gmail.com>
2026-04-17 09:08:46 -07:00
JUST.in DO IT
4bdc8d4c68 fix(sqllab): Relocate schema display on table preview (#39420) 2026-04-17 09:09:52 -03:00
dependabot[bot]
db7a2bd682 chore(deps): bump protocol-buffers-schema from 3.6.0 to 3.6.1 in /superset-frontend (#39418)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-16 20:49:37 -07:00
Gabriel Torres Ruiz
2e0d482ccf fix(mcp): support explicit query_mode in TableChartConfig (#39412) 2026-04-16 18:53:25 -03:00
Gabriel Torres Ruiz
e5b3a9c25d fix(mcp): replace inputSchema with parameters_hint in search_tools results by default (#39411) 2026-04-16 18:53:10 -03:00
Gabriel Torres Ruiz
c289731212 fix(mcp): prevent LLM from creating new dashboard instead of adding chart to existing one (#39353) 2026-04-16 18:52:53 -03:00
Gabriel Torres Ruiz
f850c6b1b1 fix(parallel-coordinates): improve dark mode visibility for labels, axis text, and data lines (#39415) 2026-04-16 18:51:36 -03:00
Evan Rusackas
8ce234371b test(core): restore 100% TS coverage for core-packages-ts (copy utility) (#39384)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-16 12:02:52 -07:00
Michael S. Molina
e5820b6b2b chore: Bump core packages to 0.1.0 RC2 (#39406) 2026-04-16 15:28:37 -03:00
Mehmet Salih Yavuz
69f062b804 feat(mcp): add a preview flow to mcp chart updates (#39383)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 20:31:02 +03:00
dependabot[bot]
735dd5dbae chore(deps): bump @swc/core from 1.15.21 to 1.15.24 in /docs (#39133)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-04-16 10:24:39 -07:00
dependabot[bot]
cd7dddb5a1 chore(deps): bump baseline-browser-mapping from 2.10.16 to 2.10.19 in /docs (#39373)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-16 10:24:26 -07:00
Mehmet Salih Yavuz
7c76fd3d81 fix(SelectFilter): auto clear search input (#39157) 2026-04-16 18:54:34 +03:00
Luiz Otavio
0b419a07f5 fix: add comments to SQL clause validation (#39167) 2026-04-16 09:19:39 -03:00
JUST.in DO IT
0b51e9cd5e fix(sqllab): format_sql to apply db dialect by database_id (#39393) 2026-04-16 08:27:51 -03:00
Amin Ghadersohi
e7b9fb277e fix(mcp): always push fresh app context per tool call to prevent g.user race (#39385) 2026-04-15 20:48:21 -04:00
Amin Ghadersohi
838ee870d0 fix(mcp): update instructions to use correct request wrapper and identifier params (#39392) 2026-04-15 20:17:07 -04:00
dependabot[bot]
84af6c9f29 chore(deps-dev): bump @docusaurus/tsconfig from 3.9.2 to 3.10.0 in /docs (#39189)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 15:28:40 -07:00
dependabot[bot]
05227e8a80 chore(deps): bump caniuse-lite from 1.0.30001786 to 1.0.30001788 in /docs (#39376)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 15:12:46 -07:00
dependabot[bot]
76a209663d chore(deps-dev): bump baseline-browser-mapping from 2.10.13 to 2.10.16 in /superset-frontend (#39150)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 14:56:40 -07:00
dependabot[bot]
61c45e3dd8 chore(deps-dev): bump @docusaurus/module-type-aliases from 3.9.2 to 3.10.0 in /docs (#39194)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 14:53:37 -07:00
dependabot[bot]
e11a50bedf chore(deps): bump @docusaurus/faster from 3.9.2 to 3.10.0 in /docs (#39195)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 14:53:05 -07:00
dependabot[bot]
f4a6ea0fde chore(deps): bump actions/github-script from 8.0.0 to 9.0.0 (#39267)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 14:52:48 -07:00
dependabot[bot]
e542e9f840 chore(deps): bump actions/cache from 5.0.4 to 5.0.5 (#39368)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 14:52:32 -07:00
dependabot[bot]
e0dcb2908d chore(deps): bump swagger-ui-react from 5.32.1 to 5.32.4 in /docs (#39377)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 14:51:42 -07:00
innovark
eaccb2e471 fix(EmptyState): prevent SVG cropping in empty state images (#37287)
Co-authored-by: Joe Li <joe@preset.io>
2026-04-15 14:49:18 -07:00
Laurent Ouattara
c1a1f2e7e7 docs: add Hifadih Business & Technology to In the Wild (#38824) 2026-04-15 14:48:58 -07:00
Robert A
45d5501aa7 fix(documentation): FAQ grammar for SQL query wording (#38923) 2026-04-15 14:48:41 -07:00
dependabot[bot]
388596e4fe chore(deps): bump baseline-browser-mapping from 2.10.13 to 2.10.16 in /docs (#39148)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 14:48:25 -07:00
Grégoire Gailly
b11d4f3ef0 fix(i18n): typo in fr language (#36982)
Co-authored-by: Sam Firke <sfirke@users.noreply.github.com>
2026-04-15 16:20:01 -04:00
Michael S. Molina
998b9e387b fix(ListView): empty state not filling available width (#39387)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 16:32:12 -03:00
Maxime Beauchemin
b3e88db87e fix(table): use column label instead of SQL expression for orderby in downloads (#39332)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 11:20:54 -07:00
Abdul Rehman
8471e82342 fix(css-templates): add missing height to CSS editor in CssTemplateModal (#39221)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:01:27 -03:00
Richard Fogaca Nienkotter
c3a0f2749b fix(dashboard): apply dynamic groupby display controls to scoped charts (#39356) 2026-04-15 14:57:29 -03:00
Maxime Beauchemin
c2d96e0dce fix(table): fix cross-filter not clearing on second click in Interactive Table (#39253)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 10:30:36 -07:00
Abdul Rehman
44e77fdf2b fix(explore): dispatch onChange immediately on NumberControl stepper arrow clicks (#39220)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:15:37 -07:00
Gabriel Torres Ruiz
18d6feb499 feat(mcp): add create_virtual_dataset tool to save SQL queries as datasets (#39279) 2026-04-15 13:04:32 -03:00
dependabot[bot]
0d91f5e982 chore(deps): bump markdown-to-jsx from 9.7.13 to 9.7.15 in /superset-frontend (#39217)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 22:29:01 +07:00
dependabot[bot]
5661fc9128 chore(deps): bump anthropics/claude-code-action from 1.0.93 to 1.0.96 + temporarily stop Dependabot PR for claude-code-action due to high release frequency but low usage(#39360)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-04-15 22:26:44 +07:00
dependabot[bot]
a6156676c8 chore(deps): bump fuse.js from 7.1.0 to 7.3.0 in /superset-frontend (#39146)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 22:25:17 +07:00
dependabot[bot]
b2bd2329bc chore(deps-dev): bump wait-on from 9.0.4 to 9.0.5 in /superset-frontend (#39322)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 22:24:09 +07:00
Amin Ghadersohi
724f1484b9 chore(mcp): update CLAUDE.md to reflect current codebase patterns (#39348)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:11:21 -04:00
Beto Dealmeida
84f7b4a973 fix: do_ping takes a connection, not engine (#39013) 2026-04-15 11:10:24 -04:00
Michael S. Molina
ddcb9be9a7 fix(sqllab): show schema refresh icon only on hover (#39367)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 11:37:33 -03:00
dependabot[bot]
8d9b5bd479 chore(deps): bump follow-redirects from 1.15.11 to 1.16.0 in /docs (#39352)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 21:32:26 +07:00
dependabot[bot]
4b88fc57b4 chore(deps-dev): bump prettier from 3.8.2 to 3.8.3 in /superset-websocket (#39358)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 21:31:56 +07:00
Hugh A. Miles II
b76080e291 feat(security): add granular export controls - Phase 2 + 3 (#38581)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: codeant-ai-for-open-source[bot] <244253245+codeant-ai-for-open-source[bot]@users.noreply.github.com>
Co-authored-by: Beto Dealmeida <roberto@dealmeida.net>
Co-authored-by: Daniel Vaz Gaspar <danielvazgaspar@gmail.com>
2026-04-15 10:24:59 -04:00
Alexandru Soare
411f769896 feat(filters): Adding empty state for filter modal (#38909) 2026-04-15 15:59:11 +03:00
Alexandru Soare
ffcc6e8b63 fix(MCP): fix MCP logs (#39159) 2026-04-15 15:57:04 +03:00
Luiz Otavio
86575e129b fix(native-filters): prevent infinite recursion in filter scope tree traversal (#39355) 2026-04-15 08:16:12 -03:00
Joe Li
3e25f02da9 test(sqllab): migrate Cypress E2E tests to Playwright (#39071) 2026-04-14 10:31:37 -07:00
dependabot[bot]
002d8ad1e4 chore(deps-dev): bump @types/node from 25.5.0 to 25.6.0 in /superset-frontend (#39265)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-14 23:18:15 +07:00
dependabot[bot]
6287a07912 chore(deps): bump anthropics/claude-code-action from 1.0.89 to 1.0.93 (#39318)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-14 23:14:11 +07:00
dependabot[bot]
fa97d0357f chore(deps-dev): bump globals from 17.4.0 to 17.5.0 in /superset-websocket (#39310)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-14 23:02:05 +07:00
dependabot[bot]
f836c3eccd chore(deps-dev): bump typescript-eslint from 8.58.0 to 8.58.2 in /superset-websocket (#39337)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-14 22:59:44 +07:00
JUST.in DO IT
499e27ea54 fix(native-filter): infinite filter loading by deps (#39175) 2026-04-14 09:06:36 -03:00
Alexandru Soare
c2a35e2eea fix(popup): Dropdown popup width doesn't match input width when tags collapse in oneLine mode (#39136) 2026-04-14 11:09:26 +03:00
Alexandru Soare
5138aa2c11 fix(select): select all button cutoff (#39005) 2026-04-14 11:07:10 +03:00
Alexandru Soare
66a9e2e16e fix(explore): Prevent error toast when navigating away from Explore page (#39065) 2026-04-14 11:05:03 +03:00
Richard Fogaca Nienkotter
0f417f0040 fix(dashboard): preserve dynamic group by column order (#39333) 2026-04-13 21:39:04 -03:00
Alexandru Soare
1462ac9282 fix(dashboard): Ensure screenshot downloads always generate fresh images/pdfs (#38880) 2026-04-13 14:17:46 -07:00
Richard Fogaca Nienkotter
da371217ef fix: revert and restore server-side sorting for value axis sorts (#39331) 2026-04-13 18:07:15 -03:00
Richard Fogaca Nienkotter
c971ea3ec6 fix(heatmap): skip orderby for value-based axis sorts (#39290)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 14:29:26 -03:00
Richard Fogaca Nienkotter
de98fdc37b test(heatmap): restore buildQuery coverage on master (#39329) 2026-04-13 13:50:11 -03:00
Maxime Beauchemin
fa1f12a0b5 fix(explore): replace TableView with virtualized GridTable, add row limit controls, restore sample filters (#39212)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 08:19:49 -07:00
Maxime Beauchemin
de40b58e10 fix(tests): fix async teardown leak in FiltersConfigModal.test.tsx (#39281)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 12:48:01 -07:00
Mike Bridge
eea3557f61 fix(dashboard): hide "Filters out of scope" section when empty (#39201)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
2026-04-10 15:42:41 -04:00
Mike Bridge
7a243d329e fix(dashboard): allow filter list to scroll in filter config modal sidebar (#39203)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
2026-04-10 15:42:16 -04:00
Maxime Beauchemin
98146251c4 fix(tests): improve ShareMenuItems test isolation to fix intermittent suite failure (#39280)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 12:30:38 -07:00
Maxime Beauchemin
0aa8cace1b fix(dataset-editor): fix SQL expression editor extra spaces and height expansion (#39248)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 12:12:26 -07:00
Maxime Beauchemin
450701ecec fix(SqlLab): improve SQL diff modal — responsive width, padding, tabs, and copy button (#39246)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 12:11:05 -07:00
Richard Fogaca Nienkotter
e9911fbac4 fix(echarts): prevent tooltip crash during dashboard auto-refresh (#39277)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:36:44 -03:00
Gabriel Torres Ruiz
69c8eef78e fix(ag-grid): jpeg export of ag-grid tables (#38781) 2026-04-10 12:54:59 -03:00
dependabot[bot]
2ff50667e7 chore(deps): bump axios from 1.13.5 to 1.15.0 in /superset-frontend (#39258)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 20:55:13 +07:00
dependabot[bot]
f1cf274751 chore(deps): bump axios from 1.13.5 to 1.15.0 in /docs (#39259)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 20:48:35 +07:00
dependabot[bot]
b65396ccd4 chore(deps-dev): bump @types/node from 25.5.2 to 25.6.0 in /superset-websocket (#39262)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 20:46:57 +07:00
dependabot[bot]
1ad76e847e chore(deps-dev): bump prettier from 3.8.1 to 3.8.2 in /superset-websocket (#39260)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 20:46:34 +07:00
dependabot[bot]
4583ef93a4 chore(deps-dev): bump prettier from 3.8.1 to 3.8.2 in /superset-frontend (#39263)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 20:40:46 +07:00
dependabot[bot]
f632d2474b chore(deps-dev): bump webpack from 5.105.4 to 5.106.0 in /superset-frontend (#39268)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 20:40:03 +07:00
Evan Rusackas
b1d69f5b39 docs(api): add Theme API endpoints to OpenAPI spec (#37943)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-10 00:17:06 -07:00
Enzo Martellucci
aba7e6dae4 fix(table): cross-filtering breaks after renaming column labels via Custom SQL (#38858) 2026-04-10 06:02:18 +02:00
Mike Bridge
8bcc90c766 fix(dashboard): Vertical filter bar gradient is extending past the filter bar area (#39204)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
2026-04-09 18:30:47 -07:00
venkateshwaran shanmugham
e39dd1afce fix: implement native browser fullscreen for dashboard charts (#38819)
Signed-off-by: Venkateshwaran Shanmugham <venkateshwaracholan@gmail.com>
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
Co-authored-by: Richard Fogaça <richardfogaca@gmail.com>
Co-authored-by: Richard Fogaca Nienkotter <63572350+richardfogaca@users.noreply.github.com>
2026-04-09 21:49:36 -03:00
Amin Ghadersohi
680cef0ee0 fix(mcp): strip json_metadata and position_json from get_dashboard_info response (#39101) 2026-04-09 17:30:57 -04:00
Amin Ghadersohi
e17cf3c808 fix(mcp): wire up compact schema serialization for search_tools results (#39229) 2026-04-09 17:25:46 -04:00
Shaitan
f49310b8ff fix(sql-lab): apply access check in SqlExecutionResultsCommand (#38952)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 16:47:15 -04:00
Vitor Avila
c7955a38ef fix: Drill to Detail for Embedded (#39214)
Co-authored-by: Maxime Beauchemin <maximebeauchemin@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 17:01:48 -03:00
Amin Ghadersohi
68067d7f44 fix(mcp): handle OAuth-authenticated databases in execute_sql (#39166) 2026-04-09 15:47:00 -04:00
Daniel Vaz Gaspar
5815665cc6 feat: role/user CRUD events and login/logout tracking in the action log (#39121)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 15:55:25 +01:00
Enzo Martellucci
6649f35a0d fix(reports): escape SQL LIKE wildcards in find_by_extra_metadata (#38738)
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2026-04-09 12:58:06 +03:00
Mehmet Salih Yavuz
5263abdc60 fix(AlertsReports): untie filters from alerts reports tabs flag (#38722)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:11:43 +03:00
Birk Skyum
c49641538d feat: modernize deck.gl and map plugins with MapLibre/Mapbox dual renderer (#38035)
Co-authored-by: Beto Dealmeida <roberto@dealmeida.net>
2026-04-08 20:14:59 -04:00
Maxime Beauchemin
d915e4f3ff fix(tags): fix Bulk tag modal dropdown clipping and stale tag cache (#39210)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 16:28:13 -07:00
Maxime Beauchemin
bad5a35fce fix(explore): constrain Edit Dataset modal height to prevent footer cutoff (#39211)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 16:19:10 -07:00
Amin Ghadersohi
1bde6f3bfd fix(mcp): resolve null fields in list_datasets, list_databases, and save_sql_query (#39206) 2026-04-08 18:39:56 -04:00
Deadman
4e0890ee1f feat(api): Add filter_dashboard_id parameter to apply dashboard filters to chart/data endpoint (#38638)
Co-authored-by: Matthew Deadman <matthewdeadman@Matthews-MacBook-Pro-2.local>
Co-authored-by: Matthew Deadman <matthewdeadman@matthews-mbp-2.lan>
Co-authored-by: codeant-ai-for-open-source[bot] <244253245+codeant-ai-for-open-source[bot]@users.noreply.github.com>
2026-04-08 15:32:46 -07:00
Maxime Beauchemin
d63308ca37 fix(frontend): fix loading spinner positioning in Save modal and filters panel (#39205)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: yousoph <sophieyou12@gmail.com>
2026-04-08 13:23:30 -07:00
Maxime Beauchemin
63cceb6a79 refactor(plugins): replace react-icons with antd icons, remove 83MB dependency (#39184)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 13:21:34 -07:00
Maxime Beauchemin
b8b2bdedf9 fix(ace-editor): style bracket matching to blend with theme (#39182)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 13:09:14 -07:00
Maxime Beauchemin
d5017e60c3 fix(sqllab): fix table navigator schema list, pin/unpin UX, copy actions, icons, and toolbar colors (#39173)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 13:06:29 -07:00
Luiz Otavio
2e80f2a473 fix: add template_processor so Jinja gets rendered before SQLGlot parse (#39207) 2026-04-08 16:58:15 -03:00
JUST.in DO IT
4c2dd63464 fix(sqllab): Update style for code viewer container (#39075) 2026-04-08 12:42:06 -07:00
Maxime Beauchemin
62302ad8c3 perf(webpack): reduce watch mode memory usage and fix docker-compose-light env (#39183)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 12:26:49 -07:00
Maxime Beauchemin
ed659958f3 fix(sqllab): use monospace font for SQL in database error messages (#39181)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 12:26:25 -07:00
Maxime Beauchemin
36de05fe36 fix(plugin-chart-handlebars): improve CSS sanitization tooltip and hide when not needed (#39180)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 12:25:54 -07:00
Maxime Beauchemin
a64609f4f3 fix(explore): add left-indentation to control panel hierarchy (#39177)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 12:25:36 -07:00
Maxime Beauchemin
140f0001f2 fix(sqllab): demote "Save as new" button from primary to secondary (#39179)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 12:03:44 -07:00
Elizabeth Thompson
587fe4af63 fix(reports): propagate PlaywrightTimeout so execution transitions to ERROR state (#39176)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 11:00:03 -07:00
Michael S. Molina
3a3a6536b7 fix(explore): Unnecessary scroll bars appearing on charts in Explore (#39160)
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2026-04-08 08:33:20 -03:00
Alexandru Soare
4f695e1b4d fix(filterReports): _generate_native_filter() crashes on null/empty filterValues (#38954) 2026-04-08 13:53:18 +03:00
Maxime Beauchemin
6ba9096870 fix(explore): handle boolean false values correctly in control rendering (#39172)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 18:23:03 -07:00
dependabot[bot]
5106afb07f chore(deps): bump d3-cloud from 1.2.8 to 1.2.9 in /superset-frontend (#39145)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 15:16:28 -07:00
dependabot[bot]
2bd4131636 chore(deps): bump react-syntax-highlighter from 16.1.0 to 16.1.1 in /superset-frontend (#39134)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 15:15:18 -07:00
dependabot[bot]
7e452df1cc chore(deps): bump anthropics/claude-code-action from 1.0.87 to 1.0.89 (#39132)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 15:14:30 -07:00
dependabot[bot]
a626d06415 chore(deps): bump caniuse-lite from 1.0.30001784 to 1.0.30001786 in /docs (#39128)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 15:11:13 -07:00
dependabot[bot]
d159edc9a6 chore(deps-dev): bump @swc/core from 1.15.21 to 1.15.24 in /superset-frontend (#39127)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 15:10:17 -07:00
dependabot[bot]
96fa2cbd2b chore(deps): update @deck.gl/aggregation-layers requirement from ~9.2.9 to ~9.2.11 in /superset-frontend/plugins/legacy-preset-chart-deckgl (#39126)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 15:09:49 -07:00
dependabot[bot]
9750881193 chore(deps-dev): bump @types/node from 25.5.0 to 25.5.2 in /superset-websocket (#39125)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 15:09:25 -07:00
dependabot[bot]
3db92021c7 chore(deps-dev): bump eslint from 10.1.0 to 10.2.0 in /superset-websocket (#39123)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 15:08:46 -07:00
dependabot[bot]
5ccfc530b2 chore(deps): bump geolib from 3.3.4 to 3.3.14 in /superset-frontend (#39092)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 14:48:08 -07:00
Amin Ghadersohi
5f9fc31ae2 feat(mcp): add get_chart_type_schema tool for on-demand schema discovery (#39142) 2026-04-07 12:07:45 -04:00
dependabot[bot]
8e811de564 chore(deps): bump hot-shots from 14.2.0 to 14.3.1 in /superset-websocket (#39147)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 22:43:50 +07:00
dependabot[bot]
027de6339b chore(deps-dev): bump jsdom from 29.0.1 to 29.0.2 in /superset-frontend (#39155)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 21:39:04 +07:00
Amin Ghadersohi
bf9aff19b5 fix(mcp): compress chart config schemas to reduce search_tools token usage (#39018) 2026-04-06 19:52:03 -04:00
SBIN2010
b05764d070 feat: Add currencies controls in country map (#39016) 2026-04-06 23:20:03 +03:00
Amin Ghadersohi
7be2acb2f3 fix(mcp): add description and certification fields to default list tool columns (#39017) 2026-04-06 13:37:52 -04:00
Amin Ghadersohi
83ad1eca26 fix(mcp): add dynamic response truncation for oversized info tool responses (#39107) 2026-04-06 12:36:03 -04:00
Amin Ghadersohi
92747246fc fix(mcp): remove JWT ValueError g.user fallback in auth layer (#39106) 2026-04-06 12:35:46 -04:00
Amin Ghadersohi
7380a59ab8 fix(mcp): fix form_data null, dataset URL, ASCII preview, and chart rename (#39109) 2026-04-06 12:34:26 -04:00
Ville Brofeldt
e56f8cc4fb fix(security_manager): custom auth_view issue (#39098) 2026-04-06 09:04:59 -07:00
Ville Brofeldt
7c79b9ab61 fix(migrations): check pre-existing foreign keys on create util (#39099) 2026-04-06 09:04:22 -07:00
Maxime Beauchemin
a62be684a0 feat(mcp): add database connection listing and info tools (#39111)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Amin Ghadersohi <amin.ghadersohi@gmail.com>
2026-04-06 11:34:10 -04:00
Michael S. Molina
a3dfbd7bff fix(deps): revert simple-zstd from 2.1.0 back to 1.4.2 (#39139)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 11:28:28 -03:00
Sam Firke
12eb40db01 fix(SQL Lab): handle columns without names (#38986) 2026-04-06 10:09:16 -04:00
dependabot[bot]
d796543f5a chore(deps): update @deck.gl/react requirement from ~9.2.9 to ~9.2.11 in /superset-frontend/plugins/legacy-preset-chart-deckgl (#39033)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 15:07:42 -07:00
dependabot[bot]
e5ae626433 chore(deps): bump dawidd6/action-download-artifact from 19 to 20 (#39081)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 15:06:06 -07:00
dependabot[bot]
8195574345 chore(deps): bump anthropics/claude-code-action from 1.0.85 to 1.0.87 (#39083)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 15:04:43 -07:00
dependabot[bot]
6b029997d9 chore(deps): bump react-syntax-highlighter from 16.1.0 to 16.1.1 in /superset-frontend (#39087)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 15:04:04 -07:00
dependabot[bot]
7a64483e6b chore(deps-dev): bump @swc/plugin-emotion from 14.7.0 to 14.8.0 in /superset-frontend (#39088)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 15:03:44 -07:00
dependabot[bot]
e424b55036 chore(deps-dev): bump babel-loader from 10.1.0 to 10.1.1 in /superset-frontend (#39090)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 15:02:57 -07:00
dependabot[bot]
613e6d6cde chore(deps): bump d3-cloud from 1.2.8 to 1.2.9 in /superset-frontend (#39093)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 15:02:11 -07:00
Amin Ghadersohi
b3a402d936 fix(mcp): handle stale SSL connections, heatmap duplicate labels, and session rollback (#39015) 2026-04-03 16:07:29 -04:00
JUST.in DO IT
c7d175b842 fix(dashboard): remove opacity on filter dropdown (#39074) 2026-04-03 09:31:23 -07:00
Amin Ghadersohi
851bbeea48 fix(mcp): improve execute_sql response-too-large error to suggest limit parameter (#39003) 2026-04-03 10:57:31 -04:00
dependabot[bot]
c5bce756f0 chore(deps): bump yeoman-generator from 7.5.1 to 8.1.2 in /superset-frontend (#38671)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 22:13:20 -07:00
dependabot[bot]
3239f058c8 chore(deps-dev): bump baseline-browser-mapping from 2.10.10 to 2.10.13 in /superset-frontend (#39044)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 22:10:35 -07:00
dependabot[bot]
7e0c634c3a chore(deps-dev): bump typescript-eslint from 8.56.1 to 8.58.0 in /superset-websocket (#38997)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 21:46:19 -07:00
dependabot[bot]
a9ced5c881 chore(deps): bump lodash-es from 4.17.23 to 4.18.1 in /superset-frontend (#39026)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 21:45:55 -07:00
dependabot[bot]
ace5f9d8c2 chore(deps): bump lodash from 4.17.23 to 4.18.1 in /superset-frontend/cypress-base (#39027)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 21:45:28 -07:00
dependabot[bot]
0452d1515a chore(deps-dev): bump @babel/preset-env from 7.29.0 to 7.29.2 in /superset-frontend (#39028)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 21:44:57 -07:00
dependabot[bot]
0330fdeb00 chore(deps-dev): bump ts-jest from 29.4.6 to 29.4.9 in /superset-websocket (#39029)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 21:44:32 -07:00
dependabot[bot]
f2ff24d811 chore(deps): bump @ant-design/icons from 5.6.1 to 6.1.1 in /superset-frontend (#39050)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 21:42:10 -07:00
dependabot[bot]
c51132f824 chore(deps): bump aws-actions/amazon-ecr-login from 2.1.1 to 2.1.2 (#39042)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 09:43:40 +07:00
dependabot[bot]
b4cb815ebf chore(deps): bump anthropics/claude-code-action from 1.0.83 to 1.0.85 (#39037)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 09:43:05 +07:00
dependabot[bot]
08d1ddd9fb chore(deps-dev): bump mini-css-extract-plugin from 2.10.1 to 2.10.2 in /superset-frontend (#39054)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 09:33:50 +07:00
dependabot[bot]
23ac4cb3a4 chore(deps): bump react-syntax-highlighter from 16.1.0 to 16.1.1 in /superset-frontend (#39051)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 09:32:55 +07:00
Joe Li
5662ecab15 chore(tests): promote Playwright experimental tests to stable (#38924)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 12:00:06 -07:00
Joe Li
9e27d682f6 test(alerts/reports): close backend and frontend test coverage gaps (#38591)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 11:55:24 -07:00
Joe Li
f0fcdcc76a chore: package bumps (#39014) 2026-04-02 11:53:07 -07:00
Kamil Gabryjelski
135e0f8099 fix(mcp): Created dashboard should be in draft state by default (#39011) 2026-04-02 19:28:51 +02:00
Geidō
25eea295f6 fix(reports): log exception traceback in _get_csv_data (#39069)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 18:37:57 +02:00
dependabot[bot]
c372f5980c chore(deps): bump lodash from 4.17.23 to 4.18.1 in /superset-frontend (#39043)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-04-02 23:36:36 +07:00
dependabot[bot]
3802acb1e0 chore(deps-dev): bump jest-html-reporter from 4.3.0 to 4.4.0 in /superset-frontend (#39053)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 22:08:48 +07:00
dependabot[bot]
bdb0030cf8 chore(deps-dev): bump @swc/core from 1.15.18 to 1.15.21 in /superset-frontend (#39045)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 22:07:44 +07:00
dependabot[bot]
87f0540acd chore(deps-dev): bump ts-jest from 29.4.6 to 29.4.9 in /superset-frontend (#39049)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 22:06:54 +07:00
dependabot[bot]
985d7b6a79 chore(deps-dev): bump @types/node from 25.3.5 to 25.5.0 in /superset-frontend (#39055)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 22:06:13 +07:00
dependabot[bot]
59f92f979a chore(deps-dev): bump eslint-plugin-testing-library from 7.16.1 to 7.16.2 in /superset-frontend (#39056)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 22:03:50 +07:00
dependabot[bot]
5cc286e383 chore(deps-dev): bump @playwright/test from 1.58.2 to 1.59.1 in /superset-frontend (#39057)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 21:59:29 +07:00
dependabot[bot]
26f4a5acad chore(deps): bump azure/setup-helm from 4.3.1 to 5.0.0 (#38815)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-04-02 01:28:56 -04:00
dependabot[bot]
fdd08d3b70 chore(deps): bump ws from 8.19.0 to 8.20.0 in /superset-websocket (#38994)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 01:28:52 -04:00
dependabot[bot]
1aac6c9474 chore(deps): update @deck.gl/react requirement from ~9.2.5 to ~9.2.9 in /superset-frontend/plugins/legacy-preset-chart-deckgl (#38150)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 14:38:12 -07:00
dependabot[bot]
7acb0c6d05 chore(deps-dev): bump @types/node from 25.3.3 to 25.3.5 in /superset-frontend (#38510)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
Co-authored-by: Joe Li <joe@preset.io>
2026-04-01 14:27:54 -07:00
dependabot[bot]
00eb86d03f chore(deps-dev): bump @swc/plugin-emotion from 14.6.0 to 14.7.0 in /superset-frontend (#38333)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-04-01 14:27:11 -07:00
dependabot[bot]
1d0e836a29 chore(deps): update @deck.gl/extensions requirement from ~9.2.5 to ~9.2.9 in /superset-frontend/plugins/legacy-preset-chart-deckgl (#38149)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-04-01 13:30:26 -07:00
dependabot[bot]
ec6640b188 chore(deps-dev): update fs-extra requirement from ^11.3.3 to ^11.3.4 in /superset-frontend/packages/generator-superset (#38383)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-04-01 13:29:47 -07:00
Rayan Salhab
ff3b8d8398 fix(ace-editor): fix cursor misalignment in markdown editor (#38928) 2026-04-01 12:03:28 -07:00
Michael S. Molina
022342839a fix(echarts): fix stacked horizontal bar chart clipping and duplicate x-axis labels (#39012) 2026-04-01 15:50:08 -03:00
Michael S. Molina
38f0dc74f7 fix(dataset-editor): improve modal layout and fix Settings tab horizontal scroll (#39009)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: codeant-ai-for-open-source[bot] <244253245+codeant-ai-for-open-source[bot]@users.noreply.github.com>
2026-04-01 15:36:17 -03:00
Amin Ghadersohi
0bae05d4a9 fix(mcp): handle table chart raw mode in query builders and sanitize dashboard titles (#38990) 2026-04-01 13:42:59 -04:00
dependabot[bot]
1bb41a6e60 chore(deps): bump anthropics/claude-code-action from 1.0.82 to 1.0.83 (#39001)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 10:20:18 -07:00
dependabot[bot]
4423134739 chore(deps): bump ioredis from 5.10.0 to 5.10.1 in /superset-websocket (#38993)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 10:19:26 -07:00
Amin Ghadersohi
190f1a59c5 fix(mcp): fix dashboard owners Pydantic crash and preserve chart preview filters (#38987) 2026-04-01 13:18:28 -04:00
dependabot[bot]
5f99d613a0 chore(deps): bump markdown-to-jsx from 9.7.6 to 9.7.8 in /superset-frontend (#38507)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 09:34:47 -07:00
dependabot[bot]
6adc816805 chore(deps): bump d3-cloud from 1.2.8 to 1.2.9 in /superset-frontend (#38438)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-04-01 09:34:01 -07:00
dependabot[bot]
aa97679327 chore(deps): update @deck.gl/aggregation-layers requirement from ~9.2.5 to ~9.2.9 in /superset-frontend/plugins/legacy-preset-chart-deckgl (#38148)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-04-01 09:32:38 -07:00
Michael S. Molina
94d8735d4b fix(query): pass datasource table to template processor for schema-aware Jinja rendering (#38984)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 13:08:12 -03:00
dependabot[bot]
64c8d652e1 chore(deps-dev): bump @types/node from 25.3.5 to 25.5.0 in /superset-websocket (#38995)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 22:48:45 +07:00
dependabot[bot]
d30c5b4eee chore(deps): bump caniuse-lite from 1.0.30001782 to 1.0.30001784 in /docs (#38998)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 22:37:29 +07:00
dependabot[bot]
8ed75787cb chore(deps-dev): bump jsdom from 28.1.0 to 29.0.1 in /superset-frontend (#38999)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 17:39:08 +07:00
michaelkremmel
4ee391e0d7 docs(db): Update crate.py with new Homepage URL (#39002) 2026-04-01 17:37:51 +07:00
dependabot[bot]
a67ca052d6 chore(deps-dev): bump babel-loader from 10.0.0 to 10.1.0 in /superset-frontend (#38505)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
Co-authored-by: Joe Li <joe@preset.io>
2026-03-31 21:59:02 -07:00
dependabot[bot]
6b6e3803d1 chore(deps-dev): bump @typescript-eslint/eslint-plugin from 8.56.1 to 8.57.0 in /superset-websocket (#38540)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 21:58:30 -07:00
dependabot[bot]
51ec61c675 chore(deps-dev): bump eslint from 10.0.2 to 10.0.3 in /superset-websocket (#38500)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 21:58:11 -07:00
dependabot[bot]
424f99efdf chore(deps): bump anthropics/claude-code-action from 1.0.80 to 1.0.82 (#38946)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 21:38:37 -07:00
dependabot[bot]
070be3de8b chore(deps-dev): bump webpack-bundle-analyzer from 5.2.0 to 5.3.0 in /superset-frontend (#38940)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 21:38:24 -07:00
dependabot[bot]
bd98269628 chore(deps): bump hot-shots from 14.1.1 to 14.2.0 in /superset-websocket (#38663)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 21:37:24 -07:00
dependabot[bot]
7ce371080c chore(deps-dev): bump @types/node from 25.3.3 to 25.3.5 in /superset-websocket (#38462)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-03-31 21:35:32 -07:00
dependabot[bot]
872632aca0 chore(deps): bump fs-extra from 11.3.2 to 11.3.4 in /superset-frontend (#38437)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 21:35:08 -07:00
dependabot[bot]
64bd03bd70 chore(deps): bump caniuse-lite from 1.0.30001781 to 1.0.30001782 in /docs (#38941) 2026-04-01 07:55:19 +07:00
madhushreeag
1e2d0faa55 fix(dashboard): dashboard filters not inherited in charts in Safari sometimes due to race condition (#38851)
Co-authored-by: madhushree agarwal <madhushree_agarwal@apple.com>
2026-03-31 12:46:05 -07:00
Michael S. Molina
8559786cc2 fix(mixed-timeseries): apply same axis formatting options as timeseries charts (#38979)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 15:00:46 -03:00
Michael S. Molina
d4d22909cb fix(dashboard): live CSS preview in PropertiesModal (#38960)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 15:00:20 -03:00
dependabot[bot]
4fae5758d5 chore(deps): bump baseline-browser-mapping from 2.10.11 to 2.10.12 in /docs (#38942)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 00:42:28 +07:00
dependabot[bot]
f85efe6139 chore(build): remove eslint-plugin-file-progress usage + correct newlines for npm run check:custom-rules (#38938)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-04-01 00:35:02 +07:00
Kamil Gabryjelski
6ea9f2ade9 chore(mcp): clarify saved metrics vs columns in MCP instructions (#38981)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 19:31:02 +02:00
dependabot[bot]
4036b784ed chore(deps): bump serialize-javascript and terser-webpack-plugin in /superset-embedded-sdk (#38920)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 10:30:40 -07:00
dependabot[bot]
08a4ad662a chore(deps): bump brace-expansion from 1.1.11 to 1.1.13 in /superset-frontend/cypress-base (#38919)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 10:30:06 -07:00
dependabot[bot]
e4021fb6e7 fix(sec): resolve 50+ Dependabot alerts + bump core-js (#38939)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-04-01 00:28:42 +07:00
Rui Zhao
53b1d1097c fix(presto): Fix presto timestamp (#26467)
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Rui Zhao <zhaorui@dropbox.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-03-31 10:28:06 -07:00
Mehmet Salih Yavuz
55aa36fef8 docs(developer): add celery to testing section for alerts&reports (#38888) 2026-03-31 10:24:58 -07:00
dependabot[bot]
3abcfb797a chore(deps-dev): bump open-cli from 8.0.0 to 9.0.0 in /superset-frontend (#38875)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 10:23:29 -07:00
dependabot[bot]
a741ddc03c chore(deps-dev): bump picomatch from 2.3.1 to 2.3.2 in /superset-embedded-sdk (#38864)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 10:19:48 -07:00
dependabot[bot]
7d26e33346 chore(deps-dev): bump picomatch from 2.3.1 to 2.3.2 in /superset-websocket (#38861)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 10:19:10 -07:00
Jessica Morris
f6cd8066ab fix(bubble): Fix Bubble chart axis label rotation (#38917) 2026-03-31 10:13:54 -07:00
Amin Ghadersohi
daefedebcd fix(mcp): batch fix for execute_sql crashes, null timestamps, and deck.gl errors (#38977) 2026-03-31 12:50:20 -04:00
Amin Ghadersohi
c37a3ec292 fix(mcp): add TEMPORAL_RANGE filter for temporal x-axis in generate_chart (#38978) 2026-03-31 12:39:08 -04:00
Amin Ghadersohi
4245720851 feat(mcp): add Big Number chart type support to MCP service (#38403)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 11:53:53 -04:00
Enzo Martellucci
f0b20dc445 fix(echarts): adapt y-axis ticks and padding for compact timeseries charts (#38673) 2026-03-31 17:44:42 +02:00
dependabot[bot]
e6f1209318 chore(deps): bump aws-actions/amazon-ecr-login from 2.0.2 to 2.1.1 (#38944)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 22:34:58 +07:00
dependabot[bot]
944944c49e chore(deps): bump antd from 6.3.4 to 6.3.5 in /docs (#38967)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 22:33:18 +07:00
dependabot[bot]
ecbf396d4a chore(deps): bump path-to-regexp from 8.2.0 to 8.4.0 in /superset-websocket/utils/client-ws-app (#38935)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 22:16:26 +07:00
RACZ Andras
b1474aaa60 docs: Fix misleading links in UPDATING.md (#38947) 2026-03-31 22:09:31 +07:00
dependabot[bot]
b49e899974 chore(deps-dev): bump typescript-eslint from 8.57.2 to 8.58.0 in /docs (#38968)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 21:59:46 +07:00
Đỗ Trọng Hải
11f2140c37 fix(AlteredSliceTag): not display undefined filter value for chart change record (#38883)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-03-31 10:38:22 -03:00
Michael S. Molina
f1cd1ae710 fix(pivot-table): safely cast numeric strings to numbers for date formatting (#38953)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 08:19:22 -03:00
Enzo Martellucci
e0a0a22542 fix(charts): add X Axis Number Format control for numeric X-axis columns (#38809)
Co-authored-by: codeant-ai-for-open-source[bot] <244253245+codeant-ai-for-open-source[bot]@users.noreply.github.com>
2026-03-31 13:38:07 +03:00
Amin Ghadersohi
2c9cf0bd55 fix(mcp): enforce MAX_PAGE_SIZE limit on list tools to prevent oversized responses (#38959) 2026-03-30 16:48:03 -04:00
Amin Ghadersohi
38fdfb4ca2 fix(mcp): prevent stale g.user from causing user impersonation across tool calls (#38747) 2026-03-30 14:23:46 -04:00
Kamil Gabryjelski
15bab227bb feat(mcp): support saved metrics from datasets in chart generation (#38955)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 16:38:31 +02:00
Amin Ghadersohi
d331a043a3 fix(mcp): prevent PendingRollbackError from poisoned sessions after SSL drops (#38934)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 10:30:15 -04:00
Enzo Martellucci
41d401a879 fix(select): ensure filter dropdown matches input field width (#38886) 2026-03-30 15:52:37 +02:00
Amin Ghadersohi
89f7e5e7ba fix(mcp): validate dataset exists in generate_explore_link before generating URL (#38951) 2026-03-30 09:29:29 -04:00
Amin Ghadersohi
aa1a69555b fix(mcp): prevent GRID_ID injection into ROOT_ID on tabbed dashboards (#38890)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 11:26:58 +02:00
Amin Ghadersohi
d1903afc69 fix(mcp): remove @parse_request decorator for cleaner tool schemas (#38918) 2026-03-29 16:09:51 -04:00
Đỗ Trọng Hải
dbc25dc555 fix(ci): resolve failed CodeCov upload for backend tests (#38885)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-03-27 18:33:02 -04:00
JUST.in DO IT
a5d2324e21 fix(sqllab): invalid treeview folder expansion (#38897) 2026-03-27 14:54:45 -07:00
dependabot[bot]
38e82e4084 chore(deps): bump yaml from 1.10.2 to 1.10.3 in /superset-frontend/cypress-base (#38856)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 13:58:26 -07:00
dependabot[bot]
6bcc8bf2b2 chore(deps): bump picomatch from 2.3.1 to 2.3.2 in /superset-frontend/cypress-base (#38862)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 13:58:06 -07:00
Mehmet Salih Yavuz
f832f9b0d5 fix(Timeseries): dedup x axis labels (#38733) 2026-03-27 22:13:02 +03:00
Kamil Gabryjelski
fc705d94e3 fix(explore): migrate from window.history to React Router history API (#38887) 2026-03-27 16:49:54 +01:00
JUST.in DO IT
65eae027fa fix(sqllab): long cell content overflooding (#38855) 2026-03-27 09:46:10 -03:00
Krishna Chaitanya
ac96f46c76 fix(dataset): add email field to owners_data for Chart Explore path (#38836) 2026-03-27 09:44:11 -03:00
Alexandru Soare
5c782397bb refactor(passwords): accept passwords via YAML file (#38059)
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2026-03-27 14:37:34 +02:00
Enzo Martellucci
40387d5daa fix(reports): PUT with empty recipients list does not persist the change (#38711) 2026-03-27 12:54:13 +01:00
dependabot[bot]
7f3351011d chore(deps): bump anthropics/claude-code-action from 1.0.78 to 1.0.80 (#38901)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:52:31 +07:00
dependabot[bot]
d6a6b6db14 chore(deps): bump yaml from 1.10.2 to 1.10.3 in /superset-frontend (#38905)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:51:06 +07:00
dependabot[bot]
388a1fd0be chore(deps-dev): bump picomatch from 2.3.1 to 2.3.2 in /superset-frontend (#38906)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:47:12 +07:00
dependabot[bot]
c2c929bf94 chore(deps-dev): bump speed-measure-webpack-plugin from 1.5.0 to 1.6.0 in /superset-frontend (#38871)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:46:12 +07:00
dependabot[bot]
41473a520e chore(deps): bump handlebars from 4.7.8 to 4.7.9 in /superset-frontend (#38894)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:45:21 +07:00
dependabot[bot]
50a5bb0671 chore(deps-dev): bump handlebars from 4.7.8 to 4.7.9 in /superset-websocket (#38895)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:44:48 +07:00
dependabot[bot]
20d0cfd156 chore(deps): bump codecov/codecov-action from 5.5.3 to 6.0.0 (#38903)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:44:26 +07:00
dependabot[bot]
5ad91fbb09 chore(deps): bump baseline-browser-mapping from 2.10.10 to 2.10.11 in /docs (#38902)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:43:58 +07:00
dependabot[bot]
6229c99050 chore(deps): bump @ant-design/icons from 6.1.0 to 6.1.1 in /docs (#38904)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:43:38 +07:00
dependabot[bot]
7e69d5d839 chore(deps): bump node-forge from 1.3.2 to 1.4.0 in /docs (#38907)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 14:42:11 +07:00
dagecko
8700ec4e6d fix: pin 2 unpinned action(s),extract 21 unsafe expression(s) to env vars (#38893) 2026-03-27 14:38:20 +07:00
dependabot[bot]
8cbf5fb8df chore(deps-dev): bump lerna from 8.2.4 to 9.0.4 in /superset-frontend (#37914)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2026-03-27 14:29:19 +07:00
Richard Fogaca Nienkotter
9c288d66b5 fix(dataset): add missing currency_code_column to DatasetPostSchema (#38853) 2026-03-26 16:58:04 -03:00
Beto Dealmeida
8983edea66 fix: type probing (#38889) 2026-03-26 13:06:49 -04:00
Shaitan
95820fb9e6 docs: improve SQL templating guidance and examples (#38777)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Daniel Vaz Gaspar <danielvazgaspar@gmail.com>
2026-03-26 16:47:14 +00:00
Amin Ghadersohi
6dc3d7ad9f fix(mcp): add try/except around DAO re-fetch to handle session errors in multi-tenant (#38859) 2026-03-26 12:43:21 -04:00
JUST.in DO IT
cfa1aba1e0 fix(sqllab): inactive leftbar selector on empty state (#38833) 2026-03-26 08:57:16 -07:00
dependabot[bot]
43816d7528 chore(deps): bump aws-actions/amazon-ecs-deploy-task-definition from 2.6.0 to 2.6.1 (#38874)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 21:59:45 +07:00
dependabot[bot]
6dd82afb0b chore(deps): bump dayjs from 1.11.19 to 1.11.20 in /superset-frontend (#38840)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2026-03-26 21:52:42 +07:00
JUST.in DO IT
e045f49787 fix(echart): multiple time shift line pattern (#38866) 2026-03-26 08:56:05 -03:00
Joe Li
38d3a39c06 test(sqllab): add SQL Lab SDK API contract tests (#38860)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 08:52:14 -03:00
Amin Ghadersohi
23a5e95884 fix(mcp): add permission checks to generate_dashboard and update_chart tools (#38845) 2026-03-25 16:37:48 -04:00
Kamil Gabryjelski
16f5a2a41a fix(mcp): detect unknown chart config fields and suggest correct ones (#38848)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 18:38:23 +01:00
Joe Li
04e07acf98 fix(tests): resolve flakey SouthPane extension test caused by nwsapi (#38832)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 09:54:44 -07:00
Đỗ Trọng Hải
3506773f51 fix(ci): install missing msgcat used for Babel translation update (#38830)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-03-25 23:40:40 +07:00
dependabot[bot]
d32e975eb9 chore(deps): bump anthropics/claude-code-action from 1.0.76 to 1.0.78 (#38842)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-25 23:38:08 +07:00
dependabot[bot]
21fb5a27e9 chore(deps): bump google-auth-library from 10.6.1 to 10.6.2 in /superset-frontend (#38841)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-25 23:35:50 +07:00
Mayank Aggarwal
403f4ad78c fix(dashboard): larger JSON metadata editor for better editing UX (#38728) (#38745) 2026-03-25 23:25:47 +07:00
dependabot[bot]
ba5820b088 chore(deps): bump antd from 6.3.3 to 6.3.4 in /docs (#38843)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-25 23:09:16 +07:00
Shaitan
a93e319716 fix(datasource): align access validation in legacy views (#38647)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Daniel Vaz Gaspar <danielvazgaspar@gmail.com>
2026-03-25 14:56:59 +00:00
Richard Fogaca Nienkotter
12aca72074 fix(echarts): prevent plain legend clipping in dashboards (#38675) 2026-03-25 09:38:31 -03:00
Michael S. Molina
3fb903fdc6 fix(embedded-sdk): wire hideTab to actually hide the dashboard tab (#38846) 2026-03-25 09:19:56 -03:00
Joe Li
4b26f8c712 fix(models): correct TabState.latest_query_id column type to match FK target (#38837)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 04:24:53 -04:00
Alexandru Soare
37c4a36fdb fix(report): raise warning when filter type not recognized (#38676) 2026-03-24 16:06:44 -07:00
Amin Ghadersohi
811dcb3715 feat(api-keys): add API key authentication via FAB SecurityManager (#37973)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Kamil Gabryjelski <kamil.gabryjelski@gmail.com>
2026-03-24 13:37:26 -04:00
Joe Li
ccaac306e5 test(sqllab): add extension slot contract tests for all 7 host components (#38776)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:01:52 -07:00
Amin Ghadersohi
c596df9294 feat(mcp): add Handlebars chart type support to MCP service (#38402)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:25:39 -04:00
Michael S. Molina
6852349d24 fix(extensions-cli): remove publisher prefix from bundle filename (#38823) 2026-03-24 13:09:10 -03:00
JUST.in DO IT
7c9d75b69e fix(sqllab): FilterText does not apply accordingly (#38813) 2026-03-24 09:04:41 -07:00
dependabot[bot]
42201a98a1 chore(deps): bump pug from 3.0.3 to 3.0.4 in /superset-websocket/utils/client-ws-app (#38664) 2026-03-24 22:40:17 +07:00
Amin Ghadersohi
09594b32f9 fix(mcp): fix generate_dashboard cross-session SQLAlchemy error (#38827) 2026-03-24 11:39:37 -04:00
dependabot[bot]
e2bb20121e chore(deps-dev): bump typescript-eslint from 8.57.1 to 8.57.2 in /docs (#38818)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-24 22:07:07 +07:00
Francesco.Castaldi
56ebfb7848 feat(i18n): update Italian messages.po (#38821) 2026-03-24 22:06:11 +07:00
Beto Dealmeida
5d9f53ff0c feat: prevent Postgres connection to Redshift (#38693) 2026-03-24 10:44:38 -04:00
Alexandru Soare
89d1b80ce7 fix(keys): Unsafe dict access in get_native_filters_params() crashes execution (#38272) 2026-03-24 15:43:27 +02:00
Shaitan
962abf6904 fix(sqllab): add authorization check to query cost estimation (#38648)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 12:57:02 +00:00
Amin Ghadersohi
ed3c5280a9 fix(mcp): prevent encoding errors and fix tool bugs on MCP client transports (#38786) 2026-03-24 05:41:24 -04:00
Mehmet Salih Yavuz
7222327992 fix(Matrixify): readd matrixify_enable guard missing (#38759) 2026-03-23 23:29:09 +03:00
Beto Dealmeida
e0b524fff2 chore: docs on Redshift auth with access key (#38810) 2026-03-23 16:07:36 -04:00
Levis Mbote
e67bc5bee5 fix(explore): display actual data type instead of "column" in column tooltip (#38554) 2026-03-23 09:06:54 -07:00
Mehmet Salih Yavuz
86a260e39b feat(theming): Custom label tokens (#38679) 2026-03-23 18:21:47 +03:00
Mehmet Salih Yavuz
fdcb942f3c fix(MainNav): display all menu items on smaller screens (#38732) 2026-03-23 18:21:13 +03:00
dependabot[bot]
7a5c07b99c chore(deps): bump @babel/runtime from 7.28.6 to 7.29.2 in /superset-frontend (#38804)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 22:21:07 +07:00
dependabot[bot]
6d93eeb533 chore(deps): bump baseline-browser-mapping from 2.10.9 to 2.10.10 in /docs (#38799)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 22:20:36 +07:00
Mehmet Salih Yavuz
44179199ba chore(Reports): remove unused and incorrect field (#38724) 2026-03-23 18:20:21 +03:00
Mehmet Salih Yavuz
100ad7d9ee fix(AlertsReports): validate anchor_list is a list (#38723) 2026-03-23 18:19:57 +03:00
dependabot[bot]
c96c817ef5 chore(deps-dev): bump eslint-plugin-testing-library from 7.16.0 to 7.16.1 in /superset-frontend (#38795)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 22:10:30 +07:00
dependabot[bot]
519a64da82 chore(deps): bump @swc/core from 1.15.18 to 1.15.21 in /docs (#38798)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 22:09:00 +07:00
dependabot[bot]
24be9cd515 chore(deps): bump caniuse-lite from 1.0.30001780 to 1.0.30001781 in /docs (#38801)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 21:58:15 +07:00
dependabot[bot]
1987e816a5 chore(deps-dev): bump baseline-browser-mapping from 2.10.7 to 2.10.10 in /superset-frontend (#38805)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 21:57:57 +07:00
dependabot[bot]
0f4aa1ceea chore(deps): bump nanoid from 5.1.6 to 5.1.7 in /superset-frontend (#38803)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 21:56:54 +07:00
dependabot[bot]
601fb45142 chore(deps-dev): bump oxlint from 1.53.0 to 1.56.0 in /superset-frontend (#38802)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 21:52:51 +07:00
dependabot[bot]
c9ebb13fa1 chore(deps-dev): bump @babel/runtime-corejs3 from 7.29.0 to 7.29.2 in /superset-frontend (#38800)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 21:50:52 +07:00
dependabot[bot]
618113079f chore(deps): bump anthropics/claude-code-action from 0.0.63 to 1.0.76 (#38797)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 21:48:46 +07:00
Mehmet Salih Yavuz
cc34d19d24 fix(DropdownContainer): add fresh to avoid stale data (#38702) 2026-03-23 14:32:11 +03:00
João Pedro Alves Barbosa
02ffb52f4a fix(table): improve conditional formatting text contrast (#38705) 2026-03-22 18:59:15 -03:00
dependabot[bot]
361afff798 chore(deps-dev): bump copy-webpack-plugin from 13.0.1 to 14.0.0 in /superset-frontend (#38504) 2026-03-22 23:49:45 +07:00
dependabot[bot]
2a6b0215f0 chore(deps): bump simple-zstd from 1.4.2 to 2.1.0 in /superset-frontend (#38662) 2026-03-22 23:49:00 +07:00
dependabot[bot]
c1c296233f chore(deps-dev): bump terser-webpack-plugin from 5.3.17 to 5.4.0 in /superset-frontend (#38669)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-22 11:23:47 +07:00
dependabot[bot]
e05fdd8acd chore(deps): bump mapbox-gl from 3.19.0 to 3.20.0 in /superset-frontend (#38670)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2026-03-22 10:58:08 +07:00
Đỗ Trọng Hải
83823911b5 feat(sec): harden GHA ref by using its SHA ID to prevent accidental usage of compromised actions (#38782)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-03-21 21:27:30 +07:00
Đỗ Trọng Hải
7004369c68 fix(sec): remove compromised Trivy actions (#38780)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-03-21 12:24:24 +07:00
dependabot[bot]
f5d7ce0f86 chore(deps-dev): bump flatted from 3.4.1 to 3.4.2 in /superset-frontend (#38771)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2026-03-21 11:44:13 +07:00
dependabot[bot]
32eb8c8263 chore(deps): bump flatted from 3.3.3 to 3.4.2 in /docs (#38772)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-21 09:27:03 +07:00
Amin Ghadersohi
44c2c765ae fix(mcp): convert adhoc filters to QueryObject format before query compilation (#38774) 2026-03-20 20:43:09 +01:00
Amin Ghadersohi
0d5721910e fix(mcp): normalize call_tool proxy arguments to prevent encoding TypeError (#38775) 2026-03-20 20:42:40 +01:00
dependabot[bot]
28d67d59cd chore(deps-dev): bump flatted from 3.2.2 to 3.4.2 in /superset-frontend/cypress-base (#38761)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-20 10:32:21 -07:00
Kamil Gabryjelski
1d72480c17 fix(mcp): fix detached Slice instance error in chart/dashboard serialization (#38767)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 18:23:51 +01:00
dependabot[bot]
1af5da6aad chore(deps): bump baseline-browser-mapping from 2.10.7 to 2.10.9 in /docs (#38756)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-20 10:12:39 -07:00
dependabot[bot]
ea1c6ee30f chore(deps): bump geostyler-openlayers-parser from 5.4.0 to 5.4.1 in /superset-frontend (#38755)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-20 10:12:07 -07:00
dependabot[bot]
97ea479cdc chore(deps-dev): bump flatted from 3.3.1 to 3.4.2 in /superset-websocket (#38752)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-20 10:11:41 -07:00
Enzo Martellucci
e088979fbe fix(reports): validate nativeFilters on report create/update and deactivate on dashboard filter deletion (#38715) 2026-03-20 17:20:02 +01:00
Kamil Gabryjelski
5e5c05362c fix(mcp): use correct permission class for save_sql_query tool (#38764)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:15:19 +01:00
Amin Ghadersohi
c2a21915ff fix(mcp): fix dashboard slug null and execute_sql encoding error (#38710) 2026-03-20 14:41:54 +01:00
Enzo Martellucci
cbb2b2f3c2 feat(themes): add JSON formatting to theme modal editor (#38739) 2026-03-20 13:48:00 +01:00
Alexandru Soare
82a74c88aa fix(button): Theming configurations for button elements is not consistent (#38604) 2026-03-20 12:37:04 +02:00
Levis Mbote
6b9dd23e3a fix(timeseries-table): enable proper column sorting in timeseries-table chart (#38579) 2026-03-19 12:01:40 -07:00
Levis Mbote
b754f2d173 fix(theme): persist local theme id so "Local" tag remains after navigation (#38527) 2026-03-19 12:01:24 -07:00
Levis Mbote
ee233d16d6 fix(dashboard): correct tab underline width for newly added dashboard tabs. (#38524) 2026-03-19 12:01:08 -07:00
Levis Mbote
65f13f773e fix(theme): ensure colorLink follows colorPrimary when not explicitly set (#38517) 2026-03-19 12:00:41 -07:00
Shaitan
d4646d43a7 docs(security): update vulnerability reporting policy and admin trust boundary (#38653)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 10:57:57 -07:00
Alexandru Soare
6465450b64 fix(firebolt): Firebolt SQL entered with EXCLUDE is rewritten to EXCEPT (#38742) 2026-03-19 10:21:50 -07:00
dependabot[bot]
01aa4d3281 chore(deps): bump match-sorter from 6.3.4 to 8.2.0 in /superset-frontend (#36470)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-03-19 23:28:20 +07:00
Kamil Gabryjelski
211f29b723 fix(mcp): Chart schema followups - DRY extraction, template fix, alias and test gaps (#38746)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:50:42 +01:00
Đỗ Trọng Hải
d6bfc98a61 feat(ci): use zstd for faster saving and loading superset-node-ci image (#38645)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-03-19 22:43:16 +07:00
dependabot[bot]
5457c2da67 chore(deps): bump dawidd6/action-download-artifact from 17 to 19 (#38735)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-19 22:42:39 +07:00
Kamil Gabryjelski
14b1b456e1 fix: Add aliases and groupby list to chart schemas (#38740) 2026-03-19 16:15:58 +01:00
Luiz Otavio
972e15e601 fix(sql): remove WHERE 1 = 1 when temporal filter has "No filter" selected (#38704) 2026-03-19 08:29:53 -03:00
Joe Li
03de7e1ec6 fix(dashboard): use inline theme data to prevent 403 for non-admin users (#38384)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 16:17:03 -07:00
dependabot[bot]
3edf75123a chore(deps): bump swagger-ui-react from 5.32.0 to 5.32.1 in /docs (#38708)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-18 10:12:47 -07:00
Michael S. Molina
fd1c423826 fix(chart): prevent chart list from failing when a datasource lacks explore_url (#38721) 2026-03-18 10:23:57 -03:00
Kamil Gabryjelski
a314e5b35e fix: Row limit support for chart mcp tools (#38717) 2026-03-18 13:40:47 +01:00
Amin Ghadersohi
e02ca8871d fix(mcp): expose individual tool parameters when MCP_PARSE_REQUEST_ENABLED=False (#38714)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 11:38:22 +01:00
dependabot[bot]
834d2abe70 chore(deps): bump antd from 6.3.2 to 6.3.3 in /docs (#38686)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-17 16:01:02 -07:00
Evan Rusackas
91986fff02 fix(tests): restore 100% TypeScript coverage for core packages (#38682)
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-03-17 15:28:51 -03:00
João Pedro Alves Barbosa
05b9970aa6 fix(map-box): prevent clusters from being smaller than individual points (#38458)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 15:08:05 -03:00
Michael S. Molina
6f301707f9 fix: Simplify extension folder name (#38690) 2026-03-17 14:00:19 -03:00
mcdogg17
5865176f36 fix(dashboard): overload issue in dashboard export to excel (#29418)
Co-authored-by: Evan Rusackas <evan@preset.io>
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:29:32 -07:00
dependabot[bot]
461037f645 chore(deps-dev): bump typescript-eslint from 8.56.1 to 8.57.1 in /docs (#38684)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-17 21:54:27 +07:00
dependabot[bot]
c980f39aab chore(deps): bump caniuse-lite from 1.0.30001778 to 1.0.30001780 in /docs (#38688)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-17 21:51:39 +07:00
Beto Dealmeida
a854fa60a2 feat: apply RLS conservatively (#38683) 2026-03-17 10:20:09 -04:00
Amin Ghadersohi
1c8224f4c6 feat(mcp): Add tool annotations for MCP directory compliance (#38641) 2026-03-16 19:09:25 -07:00
Đỗ Trọng Hải
ca403dc45d fix(ci): allow docs testing to run despite absence of db diagnostics data (#38655)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-03-17 08:01:43 +07:00
João Pedro Alves Barbosa
96705c156a fix(map-box): make opacity, lon, lat, and zoom controls functional (#38374)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: codeant-ai-for-open-source[bot] <244253245+codeant-ai-for-open-source[bot]@users.noreply.github.com>
2026-03-16 21:55:49 -03:00
endimonan
7909095ff3 feat(native-filters): add configurable LIKE/ILIKE operators to Select filter (#38470)
Co-authored-by: Evan Rusackas <evan@preset.io>
Co-authored-by: Richard Fogaca Nienkotter <63572350+richardfogaca@users.noreply.github.com>
2026-03-16 21:11:53 -03:00
Joe Li
aa5adb0fce fix(embedded): default to light theme instead of system preference (#38644)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 09:33:33 -07:00
Ville Brofeldt
dcb414aa06 feat(extensions): add update command to extensions cli (#38651) 2026-03-16 07:02:42 -07:00
Đỗ Trọng Hải
afe093f1ca fix(FilterBar): reduce padded space between filter header and first filter (#38646)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-03-16 10:00:52 -03:00
Mayank Aggarwal
cc066b3576 fix(docs): use absolute API doc links in developer docs (#38649) 2026-03-14 22:50:14 +07:00
dependabot[bot]
39cd1cdd43 chore(deps): bump dawidd6/action-download-artifact from 16 to 17 (#38620)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-14 12:40:25 +07:00
dependabot[bot]
176bf00c16 chore(deps-dev): bump baseline-browser-mapping from 2.10.0 to 2.10.7 + sync lockfile + run npm audit fix in /superset-frontend (#38621)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-03-14 12:28:47 +07:00
dependabot[bot]
68e38c8893 chore(deps): bump undici from 7.22.0 to 7.24.1 in /superset-frontend (#38642)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-14 11:13:50 +07:00
Amin Ghadersohi
48220fb33f feat(mcp): add save_sql_query tool for SQL Lab saved queries (#38414)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:02:04 -07:00
Mehmet Salih Yavuz
ed622e254a feat(matrixify): Revamp control panel (#38519) 2026-03-13 21:51:53 +03:00
amaannawab923
6e7d6a85b4 fix(ag-grid-table): fix failing buildQuery test expectation (#38636) 2026-03-14 00:59:52 +07:00
Luiz Otavio
e8061a9c2b style(metadata-bar): use bold font weight for metadata bar title (#38608) 2026-03-13 14:24:14 -03:00
Amin Ghadersohi
97a66f7a64 feat(mcp): add BM25 tool search transform to reduce initial context size (#38562)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 18:06:11 +01:00
Amin Ghadersohi
b6c3b3ef46 fix(mcp): return all statement results for multi-statement SQL queries (#38388)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:53:52 +01:00
dependabot[bot]
f4a57a13bc chore(deps): bump dompurify from 3.3.2 to 3.3.3 in /superset-frontend (#38592)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2026-03-13 22:07:09 +07:00
dependabot[bot]
242636b36b chore(deps): bump baseline-browser-mapping from 2.10.0 to 2.10.7 in /docs (#38622)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-13 22:06:43 +07:00
dependabot[bot]
ba7d7dcec0 chore(deps): bump react-syntax-highlighter from 16.1.0 to 16.1.1 in /superset-frontend (#38619)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-13 22:06:21 +07:00
Rafael Benitez
ba7271b4d8 fix(world-map): add fallback fill color when colorFn returns null (#38602)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:02:03 -03:00
amaannawab923
ca2d26a1e2 fix(ag-grid-table): fix AND filter conditions not applied (#38369) 2026-03-13 19:42:14 +05:30
Alexandru Soare
f6106cd26f fix(timeshiftcolor): Time shift color to match the original color (#38473) 2026-03-13 15:24:56 +02:00
Michael S. Molina
1867336907 fix(editor): implement missing methods, fix cursor position clearing (#38603) 2026-03-13 09:06:55 -03:00
Ville Brofeldt
f5383263bc fix(extensions): fix gitignore template and bump version (#38614) 2026-03-13 08:50:10 -03:00
Amin Ghadersohi
d5cf77cd60 fix(mcp): fix crashes in list tools, dataset info, chart preview, and add owner/favorite filters (#38277)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:46:52 +01:00
Amin Ghadersohi
f458e2d484 feat(mcp): add extra_form_data param to get_chart_data for dashboard filters (#38531)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:13:47 +01:00
Kamil Gabryjelski
af5e05db2e fix(mcp): Support form_data_key without chart identifier for unsaved charts (#38628) 2026-03-13 11:58:12 +01:00
Enzo Martellucci
32a64d02c7 fix(deckgl): polygon chart not rendering when boundary column contains nested geometry JSON (#38595) 2026-03-13 11:54:05 +01:00
Enzo Martellucci
9516d1a306 fix(explore/dashboard): fix CSV/Excel downloads for legacy chart types (#38513)
Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: codeant-ai-for-open-source[bot] <244253245+codeant-ai-for-open-source[bot]@users.noreply.github.com>
2026-03-13 11:49:34 +01:00
Kamil Gabryjelski
d91b96814e fix(mcp): Improve validation errors and field aliases to reduce failed LLM tool calls (#38625) 2026-03-13 11:16:50 +01:00
Daniel Vaz Gaspar
56d6bb1913 feat(auth): add SAML login support to frontend (#38606) 2026-03-13 09:00:07 +00:00
Amin Ghadersohi
fc156d0014 fix(mcp): replace uuid with url and changed_on_humanized in default list columns (#38566)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:53:30 +01:00
Đỗ Trọng Hải
0b8df8d3f2 build(deps): update geostyler-* deps to latest major versions (#38151)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-03-13 01:18:59 -07:00
Amin Ghadersohi
83955e87ac refactor(mcp): use serialize_user_object in get_instance_info (#38613) 2026-03-13 08:59:21 +01:00
dependabot[bot]
4a9db243a1 chore(deps): bump caniuse-lite from 1.0.30001777 to 1.0.30001778 in /docs (#38593)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-13 09:35:13 +07:00
Amin Ghadersohi
d4f1f8db00 fix(mcp): extract role names as strings in UserInfo serialization (#38612) 2026-03-12 16:20:53 -07:00
Mehmet Salih Yavuz
95f61bd223 fix: add parent_slice_id for multilayer charts to embed (#38243) 2026-03-12 21:21:43 +03:00
Mehmet Salih Yavuz
7f476a79b3 fix: add embedded box sizing rule for layout (#38351)
Co-authored-by: Joe Li <joe@preset.io>
2026-03-12 21:20:14 +03:00
Amin Ghadersohi
65e21cf13c docs: move MCP deployment guide to admin docs, add user-facing AI guide (#38585) 2026-03-12 10:30:51 -07:00
Amin Ghadersohi
7943af359c feat(mcp): implement RBAC permission checking for MCP tools (#38407)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 17:35:07 +01:00
Yuriy Krasilnikov
09e9c6a522 fix(embedded): prevent double RLS application in virtual datasets (#37395) 2026-03-12 14:12:59 +01:00
Ville Brofeldt
a9def2fc15 fix: support nested function calls in cache_key_wrapper (#38569) 2026-03-12 08:08:58 -03:00
Alexandru Soare
27197faba9 fix(matrixify): Matrixify to not override slice id (#38515)
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-03-12 11:39:29 +02:00
dependabot[bot]
ffe60bd960 chore(deps-dev): bump oxlint from 1.51.0 to 1.53.0 in /superset-frontend (#38571)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 23:41:41 +07:00
dependabot[bot]
d752be5f74 chore(deps): bump dompurify from 3.3.1 to 3.3.2 in /superset-frontend (#38455)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-03-11 08:51:40 -07:00
dependabot[bot]
3056c41507 chore(deps): bump caniuse-lite from 1.0.30001775 to 1.0.30001777 in /docs (#38463)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-03-11 08:51:21 -07:00
dependabot[bot]
d42e9c4d1b chore(deps): bump acorn from 8.9.0 to 8.16.0 in /superset-frontend (#38466)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-03-11 08:51:10 -07:00
dependabot[bot]
5912941942 chore(deps-dev): bump @typescript-eslint/parser from 8.56.1 to 8.57.0 in /superset-websocket (#38570)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 22:50:11 +07:00
dependabot[bot]
9b8106b382 chore(deps-dev): bump mini-css-extract-plugin from 2.10.0 to 2.10.1 in /superset-frontend (#38573)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 22:23:08 +07:00
amaannawab923
9215eb5e45 fix(ag-grid): persist AG Grid column filters in explore permalinks (#38393) 2026-03-11 01:56:24 +05:30
Amin Ghadersohi
fe7f220c21 fix(charts): set reasonable default y-axis title margin to prevent label overlap (#38389)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:09:09 +01:00
Amin Ghadersohi
3bb9704cd5 fix(mcp): honor target_tab parameter when adding charts to tabbed dashboards (#38409)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:57:15 -07:00
Amin Ghadersohi
eb77452857 feat(mcp): auto-generate dashboard title from chart names when omitted (#38410)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:56:58 -07:00
976 changed files with 69337 additions and 16500 deletions

5
.github/CODEOWNERS vendored
View File

@@ -22,6 +22,11 @@
/.github/ @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar @sadpandajoe @hainenber
# Notify PMC members of changes to CI-executed scripts (supply-chain risk:
# scripts/ files run directly in CI workflows and can execute arbitrary code)
/scripts/ @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar @sadpandajoe @hainenber
# Notify PMC members of changes to required GitHub Actions
/.asf.yaml @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar @Antonio-RiveroMartnez

37
.github/SECURITY.md vendored
View File

@@ -18,10 +18,32 @@ e-mail address [security@superset.apache.org](mailto:security@superset.apache.or
More details can be found on the ASF website at
[ASF vulnerability reporting process](https://apache.org/security/#reporting-a-vulnerability)
We kindly ask you to include the following information in your report:
- Apache Superset version that you are using
- A sanitized copy of your `superset_config.py` file or any config overrides
- Detailed steps to reproduce the vulnerability
**Submission Standards & AI Policy**
To ensure engineering focus remains on verified risks and to manage high reporting volumes, all reports must meet the following criteria:
- Plain Text Format: In accordance with Apache guidelines, please provide all details in plain text within the email body. Avoid sending PDFs, Word documents, or password-protected archives.
- Mandatory AI Disclosure: If you utilized Large Language Models (LLMs) or AI tools to identify a flaw or assist in writing a report, you must disclose this in your submission so our triage team can contextualize the findings.
- Human-Verified PoC: All submissions must include a manual, step-by-step Proof of Concept (PoC) performed on a supported release. Raw AI outputs, hypothetical chat transcripts, or unverified scanner logs will be closed as Invalid.
We kindly ask you to include the following information in your report to assist our developers in triaging and remediating issues efficiently:
- Version/Commit: The specific version of Apache Superset or the Git commit hash you are using.
- Configuration: A sanitized copy of your `superset_config.py` file or any config overrides.
- Environment: Your deployment method (e.g., Docker Compose, Helm, or source) and relevant OS/Browser details.
- Impacted Component: Identification of the affected area (e.g., Python backend, React frontend, or a specific database connector).
- Expected vs. Actual Behavior: A clear description of the intended system behavior versus the observed vulnerability.
- Detailed Reproduction Steps: Clear, manual steps to reproduce the vulnerability.
**Out of Scope Vulnerabilities**
To prioritize engineering efforts on genuine architectural risks, the following scenarios are explicitly out of scope and will not be issued a CVE:
- Attacks requiring Admin privileges: (e.g., CSS injection, template manipulation, dashboard ownership overrides, or modifying global system settings). Per the CVE vulnerability definition in CNA Operational Rules 4.1, a qualifying vulnerability must allow violation of a security policy. The Admin role is a fully trusted operational boundary defined by Apache Superset's security policy; actions within this boundary do not violate that policy and are therefore considered intended capabilities 'by design,' not vulnerabilities.
- Brute Force and Rate Limiting: Reports targeting a lack of resource exhaustion protections, generic rate-limiting, or volumetric Denial of Service (DoS) attempts.
- Theoretical attack vectors: Issues without a demonstrable, reproducible exploit path.
- Non-Exploitable Findings: Missing security headers, generic banner disclosures, or descriptive error messages that do not lead to a direct, documented exploit.
**Outcome of Reports**
Reports that are deemed out-of-scope for a CVE but represent valid security best practices or hardening opportunities may be converted into public GitHub issues. This allows the community to contribute to the general hardening of the platform even when a specific vulnerability threshold is not met.
Note that Apache Superset is not responsible for any third-party dependencies that may
have security issues. Any vulnerabilities found in third-party dependencies should be
@@ -29,6 +51,13 @@ reported to the maintainers of those projects. Results from security scans of Ap
Superset dependencies found on its official Docker image can be remediated at release time
by extending the image itself.
**Vulnerability Aggregation & CVE Attribution**
In accordance with MITRE CNA Operational Rules (4.1.10, 4.1.11, and 4.2.13), Apache Superset issues CVEs based on the underlying architectural root cause rather than the number of affected endpoints or exploit payloads.
- Aggregation: If multiple exploit vectors stem from the same programmatic failure or shared vulnerable code, they must be aggregated into a single, comprehensive report.
- Independent Fixes: Separate CVEs will only be assigned if the vulnerabilities reside in decoupled architectural modules and can be fixed independently of one another.
Reports that fail to aggregate related findings will be merged during triage to ensure an accurate and defensible CVE record.
**Your responsible disclosure and collaboration are invaluable.**
## Extra Information

View File

@@ -26,16 +26,16 @@ runs:
- name: Set up QEMU
if: ${{ inputs.build == 'true' }}
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
- name: Set up Docker Buildx
if: ${{ inputs.build == 'true' }}
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Try to login to DockerHub
if: ${{ inputs.login-to-dockerhub == 'true' }}
continue-on-error: true
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ inputs.dockerhub-user }}
password: ${{ inputs.dockerhub-token }}

View File

@@ -4,6 +4,10 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
ignore:
# Ignore temporarily as release schedule is too mentally taxing for dep-handling maintainers
# Additionally, very few PRs are reviewed by this action.
- dependency-name: anthropics/claude-code-action
schedule:
interval: "daily"

5
.github/labeler.yml vendored
View File

@@ -17,6 +17,11 @@
- any-glob-to-any-file:
- 'superset/migrations/**'
"risk:ci-script":
- changed-files:
- any-glob-to-any-file:
- 'scripts/**'
############################################
# Dependencies
############################################

View File

@@ -32,7 +32,7 @@ jobs:
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: true
ref: master
@@ -41,7 +41,7 @@ jobs:
uses: ./.github/actions/setup-supersetbot/
- name: Set up Python ${{ inputs.python-version }}
uses: actions/setup-python@v6
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: "3.10"
@@ -51,27 +51,31 @@ jobs:
- name: supersetbot bump-python -p "${{ github.event.inputs.package }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INPUT_PACKAGE: ${{ github.event.inputs.package }}
INPUT_GROUP: ${{ github.event.inputs.group }}
INPUT_EXTRA_FLAGS: ${{ github.event.inputs.extra-flags }}
INPUT_LIMIT: ${{ github.event.inputs.limit }}
run: |
git config --global user.email "action@github.com"
git config --global user.name "GitHub Action"
PACKAGE_OPT=""
if [ -n "${{ github.event.inputs.package }}" ]; then
PACKAGE_OPT="-p ${{ github.event.inputs.package }}"
if [ -n "${INPUT_PACKAGE}" ]; then
PACKAGE_OPT="-p ${INPUT_PACKAGE}"
fi
GROUP_OPT=""
if [ -n "${{ github.event.inputs.group }}" ]; then
GROUP_OPT="-g ${{ github.event.inputs.group }}"
if [ -n "${INPUT_GROUP}" ]; then
GROUP_OPT="-g ${INPUT_GROUP}"
fi
EXTRA_FLAGS="${{ github.event.inputs.extra-flags }}"
EXTRA_FLAGS="${INPUT_EXTRA_FLAGS}"
supersetbot bump-python \
--verbose \
--use-current-repo \
--include-subpackages \
--limit ${{ github.event.inputs.limit }} \
--limit ${INPUT_LIMIT} \
$PACKAGE_OPT \
$GROUP_OPT \
$EXTRA_FLAGS

View File

@@ -31,7 +31,7 @@ jobs:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
if: steps.check_queued.outputs.count >= 20
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Cancel duplicate workflow runs
if: steps.check_queued.outputs.count >= 20

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive

View File

@@ -25,9 +25,9 @@ jobs:
pull-requests: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check and notify
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ github.token }}
script: |

View File

@@ -44,7 +44,7 @@ jobs:
pull-requests: write
steps:
- name: Comment access denied
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const message = `👋 Hi @${{ github.event.comment.user.login || github.event.review.user.login || github.event.issue.user.login }}!
@@ -71,12 +71,12 @@ jobs:
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 1
- name: Run Claude PR Action
uses: anthropics/claude-code-action@beta
uses: anthropics/claude-code-action@5fb899572b81d2bb648d4d187173a2f423a9677c # beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
timeout_minutes: "60"

View File

@@ -31,7 +31,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check for file changes
id: check

View File

@@ -27,9 +27,9 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout Repository"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: "Dependency Review"
uses: actions/dependency-review-action@v4
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
continue-on-error: true
with:
fail-on-severity: critical
@@ -49,7 +49,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: "Checkout Repository"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup Python
uses: ./.github/actions/setup-backend/

View File

@@ -42,7 +42,7 @@ jobs:
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
@@ -101,23 +101,6 @@ jobs:
docker images $IMAGE_TAG
docker history $IMAGE_TAG
# Scan for vulnerabilities in built container image after pushes to mainline branch.
- name: Run Trivy container image vulnerabity scan
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker) && matrix.build_preset == 'lean'
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
with:
image-ref: ${{ env.IMAGE_TAG }}
format: 'sarif'
output: 'trivy-results.sarif'
vuln-type: 'os'
severity: 'CRITICAL,HIGH'
ignore-unfixed: true
- name: Upload Trivy scan results to GitHub Security tab
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker) && matrix.build_preset == 'lean'
uses: github/codeql-action/upload-sarif@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8
with:
sarif_file: 'trivy-results.sarif'
- name: docker-compose sanity check
if: (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker) && matrix.build_preset == 'dev'
shell: bash
@@ -134,7 +117,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Check for file changes

View File

@@ -16,10 +16,12 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${{ (secrets.NPM_TOKEN != '') || '' }}" ]; then
if [ -n "${NPM_TOKEN}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
env:
NPM_TOKEN: ${{ (secrets.NPM_TOKEN != '') || '' }}
build:
needs: config
if: needs.config.outputs.has-secrets
@@ -28,8 +30,8 @@ jobs:
run:
working-directory: superset-embedded-sdk
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './superset-embedded-sdk/.nvmrc'
registry-url: 'https://registry.npmjs.org'

View File

@@ -18,8 +18,8 @@ jobs:
run:
working-directory: superset-embedded-sdk
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './superset-embedded-sdk/.nvmrc'
registry-url: 'https://registry.npmjs.org'

View File

@@ -20,10 +20,12 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${{ (secrets.AWS_ACCESS_KEY_ID != '' && secrets.AWS_SECRET_ACCESS_KEY != '') || '' }}" ]; then
if [ -n "${AWS_ACCESS_KEY_ID}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
env:
AWS_ACCESS_KEY_ID: ${{ (secrets.AWS_ACCESS_KEY_ID != '' && secrets.AWS_SECRET_ACCESS_KEY != '') || '' }}
ephemeral-env-cleanup:
needs: config
if: needs.config.outputs.has-secrets
@@ -33,7 +35,7 @@ jobs:
pull-requests: write
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -56,7 +58,7 @@ jobs:
- name: Login to Amazon ECR
if: steps.describe-services.outputs.active == 'true'
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
uses: aws-actions/amazon-ecr-login@376925c9d111252e87ae59691e5a442dd100ef6a # v2
- name: Delete ECR image tag
if: steps.describe-services.outputs.active == 'true'
@@ -69,7 +71,7 @@ jobs:
- name: Comment (success)
if: steps.describe-services.outputs.active == 'true'
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{github.token}}
script: |

View File

@@ -47,7 +47,7 @@ jobs:
id: eval-label
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
LABEL_NAME="${{ github.event.inputs.label_name }}"
LABEL_NAME="${INPUT_LABEL_NAME}"
else
LABEL_NAME="${{ github.event.label.name }}"
fi
@@ -60,10 +60,12 @@ jobs:
echo "result=noop" >> $GITHUB_OUTPUT
fi
env:
INPUT_LABEL_NAME: ${{ github.event.inputs.label_name }}
- name: Get event SHA
id: get-sha
if: steps.eval-label.outputs.result == 'up'
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
@@ -94,7 +96,7 @@ jobs:
core.setOutput("sha", prSha);
- name: Looking for feature flags in PR description
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
id: eval-feature-flags
if: steps.eval-label.outputs.result == 'up'
with:
@@ -116,7 +118,7 @@ jobs:
return results;
- name: Reply with confirmation comment
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
if: steps.eval-label.outputs.result == 'up'
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -160,7 +162,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ needs.ephemeral-env-label.outputs.sha }} : ${{steps.get-sha.outputs.sha}} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ needs.ephemeral-env-label.outputs.sha }}
persist-credentials: false
@@ -189,7 +191,7 @@ jobs:
--extra-flags "--build-arg INCLUDE_CHROMIUM=false"
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -197,7 +199,7 @@ jobs:
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
uses: aws-actions/amazon-ecr-login@376925c9d111252e87ae59691e5a442dd100ef6a # v2
- name: Load, tag and push image to ECR
id: push-image
@@ -220,12 +222,12 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -233,7 +235,7 @@ jobs:
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
uses: aws-actions/amazon-ecr-login@376925c9d111252e87ae59691e5a442dd100ef6a # v2
- name: Check target image exists in ECR
id: check-image
@@ -248,7 +250,7 @@ jobs:
- name: Fail on missing container image
if: steps.check-image.outcome == 'failure'
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ github.token }}
script: |
@@ -263,7 +265,7 @@ jobs:
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
uses: aws-actions/amazon-ecs-render-task-definition@77954e213ba1f9f9cb016b86a1d4f6fcdea0d57e # v1
with:
task-definition: .github/workflows/ecs-task-definition.json
container-name: superset-ci
@@ -276,7 +278,9 @@ jobs:
- name: Describe ECS service
id: describe-services
run: |
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${INPUT_ISSUE_NUMBER}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
env:
INPUT_ISSUE_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
- name: Create ECS service
id: create-service
if: steps.describe-services.outputs.active != 'true'
@@ -296,7 +300,7 @@ jobs:
--tags key=pr,value=$PR_NUMBER key=github_user,value=${{ github.actor }}
- name: Deploy Amazon ECS task definition
id: deploy-task
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
uses: aws-actions/amazon-ecs-deploy-task-definition@fc8fc60f3a60ffd500fcb13b209c59d221ac8c8c # v2
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service
@@ -307,7 +311,9 @@ jobs:
- name: List tasks
id: list-tasks
run: |
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${INPUT_ISSUE_NUMBER}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
env:
INPUT_ISSUE_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
- name: Get network interface
id: get-eni
run: |
@@ -318,7 +324,7 @@ jobs:
echo "ip=$(aws ec2 describe-network-interfaces --network-interface-ids ${{ steps.get-eni.outputs.eni }} | jq -r '.NetworkInterfaces | first | .Association.PublicIp')" >> $GITHUB_OUTPUT
- name: Comment (success)
if: ${{ success() }}
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{github.token}}
script: |
@@ -331,7 +337,7 @@ jobs:
});
- name: Comment (failure)
if: ${{ failure() }}
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{github.token}}
script: |

View File

@@ -16,10 +16,12 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${{ (secrets.FOSSA_API_KEY != '' ) || '' }}" ]; then
if [ -n "${FOSSA_API_KEY}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
env:
FOSSA_API_KEY: ${{ (secrets.FOSSA_API_KEY != '' ) || '' }}
license_check:
needs: config
if: needs.config.outputs.has-secrets
@@ -27,12 +29,12 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: "temurin"
java-version: "11"

View File

@@ -14,10 +14,10 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: '20'

View File

@@ -17,7 +17,7 @@ jobs:
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

View File

@@ -12,7 +12,7 @@ jobs:
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive

View File

@@ -15,12 +15,12 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Setup Java
uses: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '11'

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Check for 'hold' label
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |

View File

@@ -16,7 +16,7 @@ jobs:
pull-requests: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive

View File

@@ -24,7 +24,7 @@ jobs:
python-version: ["current", "previous", "next"]
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -42,7 +42,7 @@ jobs:
echo "HOMEBREW_REPOSITORY=$HOMEBREW_REPOSITORY" >>"${GITHUB_ENV}"
brew install norwoodj/tap/helm-docs
- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: '20'
@@ -57,7 +57,7 @@ jobs:
yarn install --immutable
- name: Cache pre-commit environments
uses: actions/cache@v5
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: ~/.cache/pre-commit
key: pre-commit-v2-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}

View File

@@ -16,17 +16,19 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${{ (secrets.NPM_TOKEN != '' && secrets.GH_PERSONAL_ACCESS_TOKEN != '') || '' }}" ]; then
if [ -n "${NPM_TOKEN}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
env:
NPM_TOKEN: ${{ (secrets.NPM_TOKEN != '' && secrets.GH_PERSONAL_ACCESS_TOKEN != '') || '' }}
build:
needs: config
if: needs.config.outputs.has-secrets
name: Bump version and publish package(s)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
# pulls all commits (needed for lerna / semantic release to correctly version)
fetch-depth: 0
@@ -42,13 +44,13 @@ jobs:
- name: Install Node.js
if: env.HAS_TAGS
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './superset-frontend/.nvmrc'
- name: Cache npm
if: env.HAS_TAGS
uses: actions/cache@v5
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
@@ -62,7 +64,7 @@ jobs:
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- name: Cache npm
if: env.HAS_TAGS
uses: actions/cache@v5
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
id: npm-cache # use this to check for `cache-hit` (`steps.npm-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.npm-cache-dir-path.outputs.dir }}

View File

@@ -37,7 +37,7 @@ jobs:
steps:
- name: Security Check - Authorize Maintainers Only
id: auth
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
@@ -102,10 +102,12 @@ jobs:
- name: Install Superset Showtime
if: steps.auth.outputs.authorized == 'true'
run: |
echo "::notice::Maintainer ${{ github.actor }} triggered deploy for PR ${{ github.event.pull_request.number || github.event.inputs.pr_number }}"
echo "::notice::Maintainer ${{ github.actor }} triggered deploy for PR ${PULL_REQUEST_NUMBER}"
pip install --upgrade superset-showtime
showtime version
env:
PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
- name: Check what actions are needed
if: steps.auth.outputs.authorized == 'true'
id: check
@@ -113,12 +115,14 @@ jobs:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INPUT_PR_NUMBER: ${{ github.event.inputs.pr_number }}
INPUT_SHA: ${{ github.event.inputs.sha }}
run: |
# Bulletproof PR number extraction
if [[ -n "${{ github.event.pull_request.number }}" ]]; then
PR_NUM="${{ github.event.pull_request.number }}"
elif [[ -n "${{ github.event.inputs.pr_number }}" ]]; then
PR_NUM="${{ github.event.inputs.pr_number }}"
elif [[ -n "${INPUT_PR_NUMBER}" ]]; then
PR_NUM="${INPUT_PR_NUMBER}"
else
echo "❌ No PR number found in event or inputs"
exit 1
@@ -127,8 +131,8 @@ jobs:
echo "Using PR number: $PR_NUM"
# Run sync check-only with optional SHA override
if [[ -n "${{ github.event.inputs.sha }}" ]]; then
OUTPUT=$(python -m showtime sync $PR_NUM --check-only --sha "${{ github.event.inputs.sha }}")
if [[ -n "${INPUT_SHA}" ]]; then
OUTPUT=$(python -m showtime sync $PR_NUM --check-only --sha "${INPUT_SHA}")
else
OUTPUT=$(python -m showtime sync $PR_NUM --check-only)
fi
@@ -147,7 +151,7 @@ jobs:
- name: Checkout PR code (only if build needed)
if: steps.auth.outputs.authorized == 'true' && steps.check.outputs.build_needed == 'true'
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ steps.check.outputs.target_sha }}
persist-credentials: false

View File

@@ -37,7 +37,7 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive

View File

@@ -27,10 +27,12 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${{ (secrets.SUPERSET_SITE_BUILD != '' && secrets.SUPERSET_SITE_BUILD != '') || '' }}" ]; then
if [ -n "${SUPERSET_SITE_BUILD}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
env:
SUPERSET_SITE_BUILD: ${{ (secrets.SUPERSET_SITE_BUILD != '' && secrets.SUPERSET_SITE_BUILD != '') || '' }}
build-deploy:
needs: config
if: needs.config.outputs.has-secrets
@@ -38,18 +40,18 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.event.workflow_run.head_sha || github.sha }}"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
persist-credentials: false
submodules: recursive
- name: Set up Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './docs/.nvmrc'
- name: Setup Python
uses: ./.github/actions/setup-backend/
- uses: actions/setup-java@v5
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'zulu'
java-version: '21'
@@ -68,7 +70,7 @@ jobs:
yarn install --check-cache
- name: Download database diagnostics (if triggered by integration tests)
if: github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success'
uses: dawidd6/action-download-artifact@v16
uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20
continue-on-error: true
with:
workflow: superset-python-integrationtest.yml
@@ -77,7 +79,7 @@ jobs:
path: docs/src/data/
- name: Try to download latest diagnostics (for push/dispatch triggers)
if: github.event_name != 'workflow_run'
uses: dawidd6/action-download-artifact@v16
uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20
continue-on-error: true
with:
workflow: superset-python-integrationtest.yml

View File

@@ -24,7 +24,7 @@ jobs:
name: Link Checking
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
# Do not bump this linkinator-action version without opening
# an ASF Infra ticket to allow the new version first!
- uses: JustinBeckwith/linkinator-action@af984b9f30f63e796ae2ea5be5e07cb587f1bbd9 # v2.3
@@ -67,12 +67,12 @@ jobs:
working-directory: docs
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Set up Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './docs/.nvmrc'
- name: yarn install
@@ -98,25 +98,26 @@ jobs:
working-directory: docs
steps:
- name: "Checkout PR head: ${{ github.event.workflow_run.head_sha }}"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.event.workflow_run.head_sha }}
persist-credentials: false
submodules: recursive
- name: Set up Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './docs/.nvmrc'
- name: yarn install
run: |
yarn install --check-cache
- name: Download database diagnostics from integration tests
uses: dawidd6/action-download-artifact@v16
uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20
with:
workflow: superset-python-integrationtest.yml
run_id: ${{ github.event.workflow_run.id }}
name: database-diagnostics
path: docs/src/data/
if_no_artifact_found: 'warning'
- name: Use fresh diagnostics
run: |
if [ -f "src/data/databases-diagnostics.json" ]; then

View File

@@ -69,21 +69,21 @@ jobs:
# Conditional checkout based on context
- name: Checkout for push or pull_request event
if: github.event_name == 'push' || github.event_name == 'pull_request'
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
- name: Checkout using ref (workflow_dispatch)
if: github.event_name == 'workflow_dispatch' && github.event.inputs.ref != ''
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
ref: ${{ github.event.inputs.ref }}
submodules: recursive
- name: Checkout using PR ID (workflow_dispatch)
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_id != ''
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
@@ -109,7 +109,7 @@ jobs:
run: testdata
- name: Setup Node.js
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './superset-frontend/.nvmrc'
- name: Install npm dependencies
@@ -146,7 +146,7 @@ jobs:
SAFE_APP_ROOT=${APP_ROOT//\//_}
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
- name: Upload Artifacts
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: failure()
with:
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
@@ -186,21 +186,21 @@ jobs:
# Conditional checkout based on context (same as Cypress workflow)
- name: Checkout for push or pull_request event
if: github.event_name == 'push' || github.event_name == 'pull_request'
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
- name: Checkout using ref (workflow_dispatch)
if: github.event_name == 'workflow_dispatch' && github.event.inputs.ref != ''
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
ref: ${{ github.event.inputs.ref }}
submodules: recursive
- name: Checkout using PR ID (workflow_dispatch)
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_id != ''
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
@@ -226,7 +226,7 @@ jobs:
run: playwright_testdata
- name: Setup Node.js
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './superset-frontend/.nvmrc'
- name: Install npm dependencies
@@ -259,7 +259,7 @@ jobs:
SAFE_APP_ROOT=${APP_ROOT//\//_}
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
- name: Upload Playwright Artifacts
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: failure()
with:
path: |

View File

@@ -24,7 +24,7 @@ jobs:
working-directory: superset-extensions-cli
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -49,7 +49,7 @@ jobs:
- name: Upload coverage reports to Codecov
if: steps.check.outputs.superset-extensions-cli
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v5
with:
file: ./coverage.xml
flags: superset-extensions-cli
@@ -58,7 +58,7 @@ jobs:
- name: Upload HTML coverage report
if: steps.check.outputs.superset-extensions-cli
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: superset-extensions-cli-coverage-html
path: htmlcov/

View File

@@ -23,7 +23,7 @@ jobs:
should-run: ${{ steps.check.outputs.frontend }}
steps:
- name: Checkout Code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 0
@@ -54,14 +54,14 @@ jobs:
- name: Save Docker Image as Artifact
if: steps.check.outputs.frontend
run: |
docker save $TAG | gzip > docker-image.tar.gz
docker save $TAG | zstd -3 --threads=0 > docker-image.tar.zst
- name: Upload Docker Image Artifact
if: steps.check.outputs.frontend
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: docker-image
path: docker-image.tar.gz
path: docker-image.tar.zst
sharded-jest-tests:
needs: frontend-build
@@ -73,12 +73,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: docker-image
- name: Load Docker Image
run: docker load < docker-image.tar.gz
run: |
zstd -d < docker-image.tar.zst | docker load
- name: npm run test with coverage
run: |
@@ -90,7 +91,7 @@ jobs:
"npm run test -- --coverage --shard=${{ matrix.shard }}/8 --coverageReporters=json"
- name: Upload Coverage Artifact
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: coverage-artifacts-${{ matrix.shard }}
path: superset-frontend/coverage
@@ -103,14 +104,14 @@ jobs:
id-token: write
steps:
- name: Checkout Code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 0
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
- name: Download Coverage Artifacts
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
pattern: coverage-artifacts-*
path: coverage/
@@ -127,7 +128,7 @@ jobs:
run: npx nyc merge coverage/ merged-output/coverage-summary.json
- name: Upload Code Coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v5
with:
flags: javascript
use_oidc: true
@@ -142,13 +143,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: docker-image
- name: Load Docker Image
run: |
docker load < docker-image.tar.gz
zstd -d < docker-image.tar.zst | docker load
- name: lint
run: |
@@ -166,12 +167,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: docker-image
- name: Load Docker Image
run: docker load < docker-image.tar.gz
run: |
zstd -d < docker-image.tar.zst | docker load
- name: Build Plugins Packages
run: |
@@ -184,12 +186,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: docker-image
- name: Load Docker Image
run: docker load < docker-image.tar.gz
run: |
zstd -d < docker-image.tar.zst | docker load
- name: Build Storybook and Run Tests
run: |

View File

@@ -16,14 +16,14 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
fetch-depth: 0
- name: Set up Helm
uses: azure/setup-helm@v4
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with:
version: v3.16.4

View File

@@ -29,7 +29,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ inputs.ref || github.ref_name }}
persist-credentials: true
@@ -42,7 +42,7 @@ jobs:
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v4
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with:
version: v3.5.4
@@ -101,7 +101,7 @@ jobs:
CR_RELEASE_NAME_TEMPLATE: "superset-helm-chart-{{ .Version }}"
- name: Open Pull Request
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const branchName = '${{ env.branch_name }}';

View File

@@ -60,21 +60,21 @@ jobs:
# Conditional checkout based on context (same as Cypress workflow)
- name: Checkout for push or pull_request event
if: github.event_name == 'push' || github.event_name == 'pull_request'
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
- name: Checkout using ref (workflow_dispatch)
if: github.event_name == 'workflow_dispatch' && github.event.inputs.ref != ''
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
ref: ${{ github.event.inputs.ref }}
submodules: recursive
- name: Checkout using PR ID (workflow_dispatch)
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_id != ''
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
@@ -100,7 +100,7 @@ jobs:
run: playwright_testdata
- name: Setup Node.js
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './superset-frontend/.nvmrc'
- name: Install npm dependencies
@@ -133,7 +133,7 @@ jobs:
SAFE_APP_ROOT=${APP_ROOT//\//_}
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
- name: Upload Playwright Artifacts
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: failure()
with:
path: |

View File

@@ -16,6 +16,8 @@ concurrency:
jobs:
test-mysql:
runs-on: ubuntu-24.04
permissions:
id-token: write
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -41,7 +43,7 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -68,11 +70,12 @@ jobs:
run: |
./scripts/python_tests.sh
- name: Upload code coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v5
with:
flags: python,mysql
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset
- name: Generate database diagnostics for docs
if: steps.check.outputs.python
env:
@@ -98,13 +101,15 @@ jobs:
"
- name: Upload database diagnostics artifact
if: steps.check.outputs.python
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: database-diagnostics
path: databases-diagnostics.json
retention-days: 7
test-postgres:
runs-on: ubuntu-24.04
permissions:
id-token: write
strategy:
matrix:
python-version: ["current", "previous", "next"]
@@ -129,7 +134,7 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -159,14 +164,17 @@ jobs:
run: |
./scripts/python_tests.sh
- name: Upload code coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v5
with:
flags: python,postgres
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset
test-sqlite:
runs-on: ubuntu-24.04
permissions:
id-token: write
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -182,7 +190,7 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -211,8 +219,9 @@ jobs:
run: |
./scripts/python_tests.sh
- name: Upload code coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v5
with:
flags: python,sqlite
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset

View File

@@ -17,6 +17,8 @@ concurrency:
jobs:
test-postgres-presto:
runs-on: ubuntu-24.04
permissions:
id-token: write
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -48,7 +50,7 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -77,14 +79,17 @@ jobs:
run: |
./scripts/python_tests.sh -m 'chart_data_flow or sql_json_flow'
- name: Upload code coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v5
with:
flags: python,presto
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset
test-postgres-hive:
runs-on: ubuntu-24.04
permissions:
id-token: write
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -108,7 +113,7 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -145,8 +150,9 @@ jobs:
pip install -e .[hive]
./scripts/python_tests.sh -m 'chart_data_flow or sql_json_flow'
- name: Upload code coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v5
with:
flags: python,hive
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset

View File

@@ -17,6 +17,8 @@ concurrency:
jobs:
unit-tests:
runs-on: ubuntu-24.04
permissions:
id-token: write
strategy:
matrix:
python-version: ["previous", "current", "next"]
@@ -24,7 +26,7 @@ jobs:
PYTHONPATH: ${{ github.workspace }}
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -53,8 +55,9 @@ jobs:
run: |
pytest --durations-min=0.5 --cov=superset/sql/ ./tests/unit_tests/sql/ --cache-clear --cov-fail-under=100
- name: Upload code coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v5
with:
flags: python,unit
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -31,7 +31,7 @@ jobs:
- name: Setup Node.js
if: steps.check.outputs.frontend
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './superset-frontend/.nvmrc'
- name: Install dependencies
@@ -49,7 +49,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -62,6 +62,10 @@ jobs:
- name: Setup Python
if: steps.check.outputs.python
uses: ./.github/actions/setup-backend/
- name: Install msgcat
run: sudo apt update && sudo apt install gettext
- name: Test babel extraction
if: steps.check.outputs.python
run: ./scripts/translations/babel_update.sh

View File

@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Install dependencies

View File

@@ -26,7 +26,7 @@ jobs:
steps:
- name: Quickly add thumbs up!
if: github.event_name == 'issue_comment' && contains(github.event.comment.body, '@supersetbot')
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
@@ -38,7 +38,7 @@ jobs:
});
- name: "Checkout ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

View File

@@ -31,10 +31,12 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${{ (secrets.DOCKERHUB_USER != '' && secrets.DOCKERHUB_TOKEN != '') || '' }}" ]; then
if [ -n "${DOCKERHUB_USER}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
env:
DOCKERHUB_USER: ${{ (secrets.DOCKERHUB_USER != '' && secrets.DOCKERHUB_TOKEN != '') || '' }}
docker-release:
needs: config
if: needs.config.outputs.has-secrets
@@ -47,7 +49,7 @@ jobs:
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
@@ -60,7 +62,7 @@ jobs:
build: "true"
- name: Use Node.js 20
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 20
@@ -72,17 +74,20 @@ jobs:
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INPUT_RELEASE: ${{ github.event.inputs.release }}
INPUT_FORCE_LATEST: ${{ github.event.inputs.force-latest }}
INPUT_GIT_REF: ${{ github.event.inputs.git-ref }}
run: |
RELEASE="${{ github.event.release.tag_name }}"
FORCE_LATEST=""
EVENT="${{github.event_name}}"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
# in the case of a manually-triggered run, read release from input
RELEASE="${{ github.event.inputs.release }}"
if [ "${{ github.event.inputs.force-latest }}" = "true" ]; then
RELEASE="${INPUT_RELEASE}"
if [ "${INPUT_FORCE_LATEST}" = "true" ]; then
FORCE_LATEST="--force-latest"
fi
git checkout "${{ github.event.inputs.git-ref }}"
git checkout "${INPUT_GIT_REF}"
EVENT="release"
fi
@@ -107,12 +112,12 @@ jobs:
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Use Node.js 20
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 20
@@ -122,6 +127,7 @@ jobs:
- name: Label the PRs with the right release-related labels
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INPUT_RELEASE: ${{ github.event.inputs.release }}
run: |
export GITHUB_ACTOR=""
git fetch --all --tags
@@ -129,6 +135,6 @@ jobs:
RELEASE="${{ github.event.release.tag_name }}"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
# in the case of a manually-triggered run, read release from input
RELEASE="${{ github.event.inputs.release }}"
RELEASE="${INPUT_RELEASE}"
fi
supersetbot release-label $RELEASE

View File

@@ -19,10 +19,12 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${{ (secrets.GSHEET_KEY != '' ) || '' }}" ]; then
if [ -n "${GSHEET_KEY}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
env:
GSHEET_KEY: ${{ (secrets.GSHEET_KEY != '' ) || '' }}
process-and-upload:
needs: config
if: needs.config.outputs.has-secrets
@@ -30,10 +32,10 @@ jobs:
name: Generate Reports
steps:
- name: Checkout Repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: './superset-frontend/.nvmrc'

1
.gitignore vendored
View File

@@ -133,6 +133,7 @@ CLAUDE.local.md
PROJECT.md
.aider*
.claude_rc*
.claude/settings.local.json
.env.local
oxc-custom-build/
*.code-workspace

View File

@@ -458,7 +458,7 @@ cd ../
sed -i '' "s/version_string = .*/version_string = \"$SUPERSET_VERSION\"/" setup.py
# build the python distribution
python setup.py sdist
python -m build
```
Publish to PyPI

View File

@@ -287,6 +287,11 @@ categories:
url: https://www.gfk.com/home
contributors: ["@mherr"]
- name: Hifadih Business & Technology
url: https://hifadih.net/en
logo: hifadih.png
contributors: ["@saintLaurent00"]
# Logo approved by @anmol-hpe on behalf of HPE
- name: HPE
url: https://www.hpe.com/in/en/home.html

View File

@@ -24,6 +24,28 @@ assists people when migrating to a new version.
## Next
### Granular Export Controls
A new feature flag `GRANULAR_EXPORT_CONTROLS` introduces three fine-grained permissions that replace the legacy `can_csv` permission:
| Permission | Controls |
|---|---|
| `can_export_data` | CSV, Excel, JSON exports |
| `can_export_image` | Screenshot/PDF exports |
| `can_copy_clipboard` | Copy-to-clipboard operations |
When the feature flag is enabled, these permissions are enforced on both the frontend (disabled buttons with tooltips) and backend (403 responses from API endpoints). When disabled, legacy `can_csv` behavior is preserved.
**Migration behavior:** All three new permissions are granted to every role that currently has `can_csv`, preserving existing access. Admins can then selectively revoke individual export permissions from specific roles as needed.
### Deck.gl MapBox viewport and opacity controls are functional
The Deck.gl MapBox chart's **Opacity**, **Default longitude**, **Default latitude**, and **Zoom** controls were previously non-functional — changing them had no effect on the rendered map. These controls are now wired up correctly.
**Behavior change for existing charts:** Previously, the viewport controls had hard-coded default values (`-122.405293`, `37.772123`, zoom `11` — San Francisco) that were stored in each chart's `form_data` but never applied. The map always used `fitBounds` to center on the data. With this fix, those stored values are now respected, which means existing MapBox charts may open centered on the old default coordinates instead of fitting to data bounds.
**To restore fit-to-data behavior:** Open the chart in Explore, clear the **Default longitude**, **Default latitude**, and **Zoom** fields in the Viewport section, and re-save the chart.
### ClickHouse minimum driver version bump
The minimum required version of `clickhouse-connect` has been raised to `>=0.13.0`. If you are using the ClickHouse connector, please upgrade your `clickhouse-connect` package. The `_mutate_label` workaround that appended hash suffixes to column aliases has also been removed, as it is no longer needed with modern versions of the driver.
@@ -300,13 +322,13 @@ Note: Pillow is now a required dependency (previously optional) to support image
There's a migration added that can potentially affect a significant number of existing charts.
- [32317](https://github.com/apache/superset/pull/32317) The horizontal filter bar feature is now out of testing/beta development and its feature flag `HORIZONTAL_FILTER_BAR` has been removed.
- [31590](https://github.com/apache/superset/pull/31590) Marks the begining of intricate work around supporting dynamic Theming, and breaks support for [THEME_OVERRIDES](https://github.com/apache/superset/blob/732de4ac7fae88e29b7f123b6cbb2d7cd411b0e4/superset/config.py#L671) in favor of a new theming system based on AntD V5. Likely this will be in disrepair until settling over the 5.x lifecycle.
- [32432](https://github.com/apache/superset/pull/31260) Moves the List Roles FAB view to the frontend and requires `FAB_ADD_SECURITY_API` to be enabled in the configuration and `superset init` to be executed.
- [32432](https://github.com/apache/superset/pull/32432) Moves the List Roles FAB view to the frontend and requires `FAB_ADD_SECURITY_API` to be enabled in the configuration and `superset init` to be executed.
- [34319](https://github.com/apache/superset/pull/34319) Drill to Detail and Drill By is now supported in Embedded mode, and also with the `DASHBOARD_RBAC` FF. If you don't want to expose these features in Embedded / `DASHBOARD_RBAC`, make sure the roles used for Embedded / `DASHBOARD_RBAC`don't have the required permissions to perform D2D actions.
## 5.0.0
- [31976](https://github.com/apache/superset/pull/31976) Removed the `DISABLE_LEGACY_DATASOURCE_EDITOR` feature flag. The previous value of the feature flag was `True` and now the feature is permanently removed.
- [31959](https://github.com/apache/superset/pull/32000) Removes CSV_UPLOAD_MAX_SIZE config, use your web server to control file upload size.
- [32000](https://github.com/apache/superset/pull/32000) Removes CSV_UPLOAD_MAX_SIZE config, use your web server to control file upload size.
- [31959](https://github.com/apache/superset/pull/31959) Removes the following endpoints from data uploads: `/api/v1/database/<id>/<file type>_upload` and `/api/v1/database/<file type>_metadata`, in favour of new one (Details on the PR). And simplifies permissions.
- [31844](https://github.com/apache/superset/pull/31844) The `ALERT_REPORTS_EXECUTE_AS` and `THUMBNAILS_EXECUTE_AS` config parameters have been renamed to `ALERT_REPORTS_EXECUTORS` and `THUMBNAILS_EXECUTORS` respectively. A new config flag `CACHE_WARMUP_EXECUTORS` has also been introduced to be able to control which user is used to execute cache warmup tasks. Finally, the config flag `THUMBNAILS_SELENIUM_USER` has been removed. To use a fixed executor for async tasks, use the new `FixedExecutor` class. See the config and docs for more info on setting up different executor profiles.
- [31894](https://github.com/apache/superset/pull/31894) Domain sharding is deprecated in favor of HTTP2. The `SUPERSET_WEBSERVER_DOMAINS` configuration will be removed in the next major version (6.0)

View File

@@ -115,6 +115,10 @@ services:
DATABASE_HOST: db-light
DATABASE_DB: superset_light
POSTGRES_DB: superset_light
EXAMPLES_HOST: db-light
EXAMPLES_DB: superset_light
EXAMPLES_USER: superset
EXAMPLES_PASSWORD: superset
SUPERSET_CONFIG_PATH: /app/docker/pythonpath_dev/superset_config_docker_light.py
GITHUB_HEAD_REF: ${GITHUB_HEAD_REF:-}
GITHUB_SHA: ${GITHUB_SHA:-}
@@ -137,6 +141,10 @@ services:
DATABASE_HOST: db-light
DATABASE_DB: superset_light
POSTGRES_DB: superset_light
EXAMPLES_HOST: db-light
EXAMPLES_DB: superset_light
EXAMPLES_USER: superset
EXAMPLES_PASSWORD: superset
SUPERSET_CONFIG_PATH: /app/docker/pythonpath_dev/superset_config_docker_light.py
healthcheck:
disable: true
@@ -157,6 +165,7 @@ services:
BUILD_SUPERSET_FRONTEND_IN_DOCKER: true
NPM_RUN_PRUNE: false
SCARF_ANALYTICS: "${SCARF_ANALYTICS:-}"
DISABLE_TS_CHECKER: "${DISABLE_TS_CHECKER:-true}"
# configuring the dev-server to use the host.docker.internal to connect to the backend
superset: "http://superset-light:8088"
# Webpack dev server must bind to 0.0.0.0 to be accessible from outside the container

View File

@@ -80,7 +80,7 @@ case "${1}" in
;;
app)
echo "Starting web app (using development server)..."
flask run -p $PORT --reload --debugger --without-threads --host=0.0.0.0 --exclude-patterns "*/node_modules/*:*/.venv/*:*/build/*:*/__pycache__/*"
flask run -p $PORT --reload --debugger --host=0.0.0.0 --exclude-patterns "*/node_modules/*:*/.venv/*:*/build/*:*/__pycache__/*:*/superset-frontend/*"
;;
app-gunicorn)
echo "Starting web app..."

View File

@@ -109,6 +109,14 @@ SECRET_KEY = 'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY'
You can generate a strong secure key with `openssl rand -base64 42`.
Alternatively, you can set the secret key using `SUPERSET_SECRET_KEY` environment variable:
On a Unix-based system, such as Linux or macOS, you can do so by running the following command in your terminal:
```bash
export SUPERSET_SECRET_KEY=$(openssl rand -base64 42)
```
:::caution Use a strong secret key
This key will be used for securely signing session cookies and encrypting sensitive information stored in Superset's application metadata database.
Your deployment must use a complex, unique key.

View File

@@ -1,7 +1,7 @@
---
title: MCP Server Deployment & Authentication
hide_title: true
sidebar_position: 9
sidebar_position: 14
version: 1
---
@@ -30,6 +30,10 @@ Superset includes a built-in [Model Context Protocol (MCP)](https://modelcontext
This guide covers how to run, secure, and deploy the MCP server.
:::tip Looking for user docs?
See **[Using AI with Superset](/user-docs/using-superset/using-ai-with-superset)** for a guide on what AI can do with Superset and how to connect your AI client.
:::
```mermaid
flowchart LR
A["AI Client<br/>(Claude, ChatGPT, etc.)"] -- "MCP protocol<br/>(HTTP + JSON-RPC)" --> B["MCP Server<br/>(:5008/mcp)"]
@@ -668,12 +672,13 @@ MCP_CSRF_CONFIG = {
- **Secrets management** -- Store `MCP_JWT_SECRET`, database credentials, and API keys in environment variables or a secrets manager, never in config files committed to version control
- **Scoped tokens** -- Use `MCP_REQUIRED_SCOPES` to limit what operations a token can perform
- **Network isolation** -- In Kubernetes, restrict MCP pod network policies to only allow traffic from your AI client endpoints
- Review the **[Security documentation](./security)** for additional extension security guidance
- Review the **[Security documentation](/developer-docs/extensions/security)** for additional extension security guidance
---
## Next Steps
- **[MCP Integration](./mcp)** -- Build custom MCP tools and prompts via Superset extensions
- **[Security](./security)** -- Security best practices for extensions
- **[Deployment](./deployment)** -- Package and deploy Superset extensions
- **[Using AI with Superset](/user-docs/using-superset/using-ai-with-superset)** -- What AI can do with Superset and how to get started
- **[MCP Integration](/developer-docs/extensions/mcp)** -- Build custom MCP tools and prompts via Superset extensions
- **[Security](/developer-docs/extensions/security)** -- Security best practices for extensions
- **[Deployment](/developer-docs/extensions/deployment)** -- Package and deploy Superset extensions

View File

@@ -22,6 +22,15 @@ While powerful, this feature executes template code on the server. Within the Su
If you grant these permissions to untrusted users, this feature can be exploited as a **Server-Side Template Injection (SSTI)** vulnerability. Do not enable `ENABLE_TEMPLATE_PROCESSING` unless you fully understand and accept the associated security risks.
Additionally:
- The `url_param()` macro allows URL parameters to influence the rendered SQL. Always validate or restrict `url_param()` values in your templates rather than interpolating them directly.
- `filter.get('val')` returns raw filter values without escaping. Use the safe helpers described below (`|where_in`, `| replace("'", "''")`) rather than concatenating values directly into SQL strings.
:::
:::tip
`ENABLE_TEMPLATE_PROCESSING` defaults to `False`. Only enable it if your deployment requires Jinja templates and all users with dataset/chart edit access are administrators or fully trusted internal users.
:::
When templating is enabled, python code can be embedded in virtual datasets and
@@ -324,6 +333,16 @@ cache hit in the future and Superset can retrieve cached data.
The `{{ url_param('custom_variable') }}` macro lets you define arbitrary URL
parameters and reference them in your SQL code.
:::warning
Always treat `url_param()` values as untrusted input. Escaping behaviour varies by context and configuration, so do not rely on it. Restrict values to an explicit allowlist before using them in SQL:
```sql
{% set cc = url_param('countrycode') %}
{% if cc not in ('US', 'ES', 'FR') %}{% set cc = 'US' %}{% endif %}
WHERE country_code = '{{ cc }}'
```
:::
Here's a concrete example:
- You write the following query in SQL Lab:
@@ -398,6 +417,16 @@ This is useful if:
- You want to handle generating custom SQL conditions for a filter
- You want to have the ability to filter inside the main query for speed purposes
:::warning
`filter.get('val')` returns the raw filter value without escaping. For multi-value filters, use the `|where_in` Jinja filter, which handles quoting safely. For single-value operators like `LIKE`, escape single quotes before interpolating:
```sql
{%- if filter.get('op') == 'LIKE' -%}
AND full_name LIKE '{{ filter.get('val') | replace("'", "''") }}'
{%- endif -%}
```
:::
Here's a concrete example:
```sql
@@ -424,7 +453,7 @@ Here's a concrete example:
{%- if filter.get('op') == 'LIKE' -%}
AND
full_name LIKE {{ "'" + filter.get('val') + "'" }}
full_name LIKE '{{ filter.get('val') | replace("'", "''") }}'
{%- endif -%}
{%- endfor -%}

View File

@@ -24,6 +24,14 @@ A table with the permissions for these roles can be found at [/RESOURCES/STANDAR
Admins have all possible rights, including granting or revoking rights from other
users and altering other peoples slices and dashboards.
>#### Threat Model and Privilege Boundaries: The Admin Role
>
>Apache Superset is built with a granular permission model where users assigned the Admin role are considered fully trusted. Admins possess complete control over the application's configuration, UI rendering, and access controls.
>
>Consequently, actions performed by an Admin that alter the application's behavior or presentation—such as injecting custom CSS, modifying Jinja templates, or altering security flags—are intended administrative capabilities by design.
>
>In accordance with MITRE CNA Rule 4.1, a vulnerability must represent a violation of an explicit security policy. Because the Admin role is defined as a trusted operational boundary, actions executed with Admin privileges do not cross a security perimeter. Therefore, exploit vectors that strictly require Admin access are not classified as security vulnerabilities and are ineligible for CVE assignment.
### Alpha
Alpha users have access to all data sources, but they cannot grant or revoke access

View File

@@ -47,10 +47,10 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get the CSRF token](./api/get-the-csrf-token) | `/api/v1/security/csrf_token/` |
| `POST` | [Get a guest token](./api/get-a-guest-token) | `/api/v1/security/guest_token/` |
| `POST` | [Create security login](./api/create-security-login) | `/api/v1/security/login` |
| `POST` | [Create security refresh](./api/create-security-refresh) | `/api/v1/security/refresh` |
| `GET` | [Get the CSRF token](/developer-docs/api/get-the-csrf-token) | `/api/v1/security/csrf_token/` |
| `POST` | [Get a guest token](/developer-docs/api/get-a-guest-token) | `/api/v1/security/guest_token/` |
| `POST` | [Create security login](/developer-docs/api/create-security-login) | `/api/v1/security/login` |
| `POST` | [Create security refresh](/developer-docs/api/create-security-refresh) | `/api/v1/security/refresh` |
---
@@ -63,32 +63,32 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `DELETE` | [Bulk delete dashboards](./api/bulk-delete-dashboards) | `/api/v1/dashboard/` |
| `GET` | [Get a list of dashboards](./api/get-a-list-of-dashboards) | `/api/v1/dashboard/` |
| `POST` | [Create a new dashboard](./api/create-a-new-dashboard) | `/api/v1/dashboard/` |
| `GET` | [Get metadata information about this API resource (dashboard--info)](./api/get-metadata-information-about-this-api-resource-dashboard-info) | `/api/v1/dashboard/_info` |
| `GET` | [Get a dashboard detail information](./api/get-a-dashboard-detail-information) | `/api/v1/dashboard/{id_or_slug}` |
| `GET` | [Get a dashboard's chart definitions.](./api/get-a-dashboard-s-chart-definitions) | `/api/v1/dashboard/{id_or_slug}/charts` |
| `POST` | [Create a copy of an existing dashboard](./api/create-a-copy-of-an-existing-dashboard) | `/api/v1/dashboard/{id_or_slug}/copy/` |
| `GET` | [Get dashboard's datasets](./api/get-dashboard-s-datasets) | `/api/v1/dashboard/{id_or_slug}/datasets` |
| `DELETE` | [Delete a dashboard's embedded configuration](./api/delete-a-dashboard-s-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
| `GET` | [Get the dashboard's embedded configuration](./api/get-the-dashboard-s-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
| `POST` | [Set a dashboard's embedded configuration](./api/set-a-dashboard-s-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
| `PUT` | [Update dashboard by id_or_slug embedded](./api/update-dashboard-by-id-or-slug-embedded) | `/api/v1/dashboard/{id_or_slug}/embedded` |
| `GET` | [Get dashboard's tabs](./api/get-dashboard-s-tabs) | `/api/v1/dashboard/{id_or_slug}/tabs` |
| `DELETE` | [Delete a dashboard](./api/delete-a-dashboard) | `/api/v1/dashboard/{pk}` |
| `PUT` | [Update a dashboard](./api/update-a-dashboard) | `/api/v1/dashboard/{pk}` |
| `POST` | [Compute and cache a screenshot (dashboard-pk-cache-dashboard-screenshot)](./api/compute-and-cache-a-screenshot-dashboard-pk-cache-dashboard-screenshot) | `/api/v1/dashboard/{pk}/cache_dashboard_screenshot/` |
| `PUT` | [Update colors configuration for a dashboard.](./api/update-colors-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/colors` |
| `DELETE` | [Remove the dashboard from the user favorite list](./api/remove-the-dashboard-from-the-user-favorite-list) | `/api/v1/dashboard/{pk}/favorites/` |
| `POST` | [Mark the dashboard as favorite for the current user](./api/mark-the-dashboard-as-favorite-for-the-current-user) | `/api/v1/dashboard/{pk}/favorites/` |
| `PUT` | [Update native filters configuration for a dashboard.](./api/update-native-filters-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/filters` |
| `GET` | [Get a computed screenshot from cache (dashboard-pk-screenshot-digest)](./api/get-a-computed-screenshot-from-cache-dashboard-pk-screenshot-digest) | `/api/v1/dashboard/{pk}/screenshot/{digest}/` |
| `GET` | [Get dashboard's thumbnail](./api/get-dashboard-s-thumbnail) | `/api/v1/dashboard/{pk}/thumbnail/{digest}/` |
| `GET` | [Download multiple dashboards as YAML files](./api/download-multiple-dashboards-as-yaml-files) | `/api/v1/dashboard/export/` |
| `GET` | [Check favorited dashboards for current user](./api/check-favorited-dashboards-for-current-user) | `/api/v1/dashboard/favorite_status/` |
| `POST` | [Import dashboard(s) with associated charts/datasets/databases](./api/import-dashboard-s-with-associated-charts-datasets-databases) | `/api/v1/dashboard/import/` |
| `GET` | [Get related fields data (dashboard-related-column-name)](./api/get-related-fields-data-dashboard-related-column-name) | `/api/v1/dashboard/related/{column_name}` |
| `DELETE` | [Bulk delete dashboards](/developer-docs/api/bulk-delete-dashboards) | `/api/v1/dashboard/` |
| `GET` | [Get a list of dashboards](/developer-docs/api/get-a-list-of-dashboards) | `/api/v1/dashboard/` |
| `POST` | [Create a new dashboard](/developer-docs/api/create-a-new-dashboard) | `/api/v1/dashboard/` |
| `GET` | [Get metadata information about this API resource (dashboard--info)](/developer-docs/api/get-metadata-information-about-this-api-resource-dashboard-info) | `/api/v1/dashboard/_info` |
| `GET` | [Get a dashboard detail information](/developer-docs/api/get-a-dashboard-detail-information) | `/api/v1/dashboard/{id_or_slug}` |
| `GET` | [Get a dashboard's chart definitions.](/developer-docs/api/get-a-dashboard-s-chart-definitions) | `/api/v1/dashboard/{id_or_slug}/charts` |
| `POST` | [Create a copy of an existing dashboard](/developer-docs/api/create-a-copy-of-an-existing-dashboard) | `/api/v1/dashboard/{id_or_slug}/copy/` |
| `GET` | [Get dashboard's datasets](/developer-docs/api/get-dashboard-s-datasets) | `/api/v1/dashboard/{id_or_slug}/datasets` |
| `DELETE` | [Delete a dashboard's embedded configuration](/developer-docs/api/delete-a-dashboard-s-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
| `GET` | [Get the dashboard's embedded configuration](/developer-docs/api/get-the-dashboard-s-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
| `POST` | [Set a dashboard's embedded configuration](/developer-docs/api/set-a-dashboard-s-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` |
| `PUT` | [Update dashboard by id_or_slug embedded](/developer-docs/api/update-dashboard-by-id-or-slug-embedded) | `/api/v1/dashboard/{id_or_slug}/embedded` |
| `GET` | [Get dashboard's tabs](/developer-docs/api/get-dashboard-s-tabs) | `/api/v1/dashboard/{id_or_slug}/tabs` |
| `DELETE` | [Delete a dashboard](/developer-docs/api/delete-a-dashboard) | `/api/v1/dashboard/{pk}` |
| `PUT` | [Update a dashboard](/developer-docs/api/update-a-dashboard) | `/api/v1/dashboard/{pk}` |
| `POST` | [Compute and cache a screenshot (dashboard-pk-cache-dashboard-screenshot)](/developer-docs/api/compute-and-cache-a-screenshot-dashboard-pk-cache-dashboard-screenshot) | `/api/v1/dashboard/{pk}/cache_dashboard_screenshot/` |
| `PUT` | [Update colors configuration for a dashboard.](/developer-docs/api/update-colors-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/colors` |
| `DELETE` | [Remove the dashboard from the user favorite list](/developer-docs/api/remove-the-dashboard-from-the-user-favorite-list) | `/api/v1/dashboard/{pk}/favorites/` |
| `POST` | [Mark the dashboard as favorite for the current user](/developer-docs/api/mark-the-dashboard-as-favorite-for-the-current-user) | `/api/v1/dashboard/{pk}/favorites/` |
| `PUT` | [Update native filters configuration for a dashboard.](/developer-docs/api/update-native-filters-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/filters` |
| `GET` | [Get a computed screenshot from cache (dashboard-pk-screenshot-digest)](/developer-docs/api/get-a-computed-screenshot-from-cache-dashboard-pk-screenshot-digest) | `/api/v1/dashboard/{pk}/screenshot/{digest}/` |
| `GET` | [Get dashboard's thumbnail](/developer-docs/api/get-dashboard-s-thumbnail) | `/api/v1/dashboard/{pk}/thumbnail/{digest}/` |
| `GET` | [Download multiple dashboards as YAML files](/developer-docs/api/download-multiple-dashboards-as-yaml-files) | `/api/v1/dashboard/export/` |
| `GET` | [Check favorited dashboards for current user](/developer-docs/api/check-favorited-dashboards-for-current-user) | `/api/v1/dashboard/favorite_status/` |
| `POST` | [Import dashboard(s) with associated charts/datasets/databases](/developer-docs/api/import-dashboard-s-with-associated-charts-datasets-databases) | `/api/v1/dashboard/import/` |
| `GET` | [Get related fields data (dashboard-related-column-name)](/developer-docs/api/get-related-fields-data-dashboard-related-column-name) | `/api/v1/dashboard/related/{column_name}` |
</details>
@@ -97,26 +97,26 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `DELETE` | [Bulk delete charts](./api/bulk-delete-charts) | `/api/v1/chart/` |
| `GET` | [Get a list of charts](./api/get-a-list-of-charts) | `/api/v1/chart/` |
| `POST` | [Create a new chart](./api/create-a-new-chart) | `/api/v1/chart/` |
| `GET` | [Get metadata information about this API resource (chart--info)](./api/get-metadata-information-about-this-api-resource-chart-info) | `/api/v1/chart/_info` |
| `DELETE` | [Delete a chart](./api/delete-a-chart) | `/api/v1/chart/{pk}` |
| `GET` | [Get a chart detail information](./api/get-a-chart-detail-information) | `/api/v1/chart/{pk}` |
| `PUT` | [Update a chart](./api/update-a-chart) | `/api/v1/chart/{pk}` |
| `GET` | [Compute and cache a screenshot (chart-pk-cache-screenshot)](./api/compute-and-cache-a-screenshot-chart-pk-cache-screenshot) | `/api/v1/chart/{pk}/cache_screenshot/` |
| `GET` | [Return payload data response for a chart](./api/return-payload-data-response-for-a-chart) | `/api/v1/chart/{pk}/data/` |
| `DELETE` | [Remove the chart from the user favorite list](./api/remove-the-chart-from-the-user-favorite-list) | `/api/v1/chart/{pk}/favorites/` |
| `POST` | [Mark the chart as favorite for the current user](./api/mark-the-chart-as-favorite-for-the-current-user) | `/api/v1/chart/{pk}/favorites/` |
| `GET` | [Get a computed screenshot from cache (chart-pk-screenshot-digest)](./api/get-a-computed-screenshot-from-cache-chart-pk-screenshot-digest) | `/api/v1/chart/{pk}/screenshot/{digest}/` |
| `GET` | [Get chart thumbnail](./api/get-chart-thumbnail) | `/api/v1/chart/{pk}/thumbnail/{digest}/` |
| `POST` | [Return payload data response for the given query (chart-data)](./api/return-payload-data-response-for-the-given-query-chart-data) | `/api/v1/chart/data` |
| `GET` | [Return payload data response for the given query (chart-data-cache-key)](./api/return-payload-data-response-for-the-given-query-chart-data-cache-key) | `/api/v1/chart/data/{cache_key}` |
| `GET` | [Download multiple charts as YAML files](./api/download-multiple-charts-as-yaml-files) | `/api/v1/chart/export/` |
| `GET` | [Check favorited charts for current user](./api/check-favorited-charts-for-current-user) | `/api/v1/chart/favorite_status/` |
| `POST` | [Import chart(s) with associated datasets and databases](./api/import-chart-s-with-associated-datasets-and-databases) | `/api/v1/chart/import/` |
| `GET` | [Get related fields data (chart-related-column-name)](./api/get-related-fields-data-chart-related-column-name) | `/api/v1/chart/related/{column_name}` |
| `PUT` | [Warm up the cache for the chart](./api/warm-up-the-cache-for-the-chart) | `/api/v1/chart/warm_up_cache` |
| `DELETE` | [Bulk delete charts](/developer-docs/api/bulk-delete-charts) | `/api/v1/chart/` |
| `GET` | [Get a list of charts](/developer-docs/api/get-a-list-of-charts) | `/api/v1/chart/` |
| `POST` | [Create a new chart](/developer-docs/api/create-a-new-chart) | `/api/v1/chart/` |
| `GET` | [Get metadata information about this API resource (chart--info)](/developer-docs/api/get-metadata-information-about-this-api-resource-chart-info) | `/api/v1/chart/_info` |
| `DELETE` | [Delete a chart](/developer-docs/api/delete-a-chart) | `/api/v1/chart/{pk}` |
| `GET` | [Get a chart detail information](/developer-docs/api/get-a-chart-detail-information) | `/api/v1/chart/{pk}` |
| `PUT` | [Update a chart](/developer-docs/api/update-a-chart) | `/api/v1/chart/{pk}` |
| `GET` | [Compute and cache a screenshot (chart-pk-cache-screenshot)](/developer-docs/api/compute-and-cache-a-screenshot-chart-pk-cache-screenshot) | `/api/v1/chart/{pk}/cache_screenshot/` |
| `GET` | [Return payload data response for a chart](/developer-docs/api/return-payload-data-response-for-a-chart) | `/api/v1/chart/{pk}/data/` |
| `DELETE` | [Remove the chart from the user favorite list](/developer-docs/api/remove-the-chart-from-the-user-favorite-list) | `/api/v1/chart/{pk}/favorites/` |
| `POST` | [Mark the chart as favorite for the current user](/developer-docs/api/mark-the-chart-as-favorite-for-the-current-user) | `/api/v1/chart/{pk}/favorites/` |
| `GET` | [Get a computed screenshot from cache (chart-pk-screenshot-digest)](/developer-docs/api/get-a-computed-screenshot-from-cache-chart-pk-screenshot-digest) | `/api/v1/chart/{pk}/screenshot/{digest}/` |
| `GET` | [Get chart thumbnail](/developer-docs/api/get-chart-thumbnail) | `/api/v1/chart/{pk}/thumbnail/{digest}/` |
| `POST` | [Return payload data response for the given query (chart-data)](/developer-docs/api/return-payload-data-response-for-the-given-query-chart-data) | `/api/v1/chart/data` |
| `GET` | [Return payload data response for the given query (chart-data-cache-key)](/developer-docs/api/return-payload-data-response-for-the-given-query-chart-data-cache-key) | `/api/v1/chart/data/{cache_key}` |
| `GET` | [Download multiple charts as YAML files](/developer-docs/api/download-multiple-charts-as-yaml-files) | `/api/v1/chart/export/` |
| `GET` | [Check favorited charts for current user](/developer-docs/api/check-favorited-charts-for-current-user) | `/api/v1/chart/favorite_status/` |
| `POST` | [Import chart(s) with associated datasets and databases](/developer-docs/api/import-chart-s-with-associated-datasets-and-databases) | `/api/v1/chart/import/` |
| `GET` | [Get related fields data (chart-related-column-name)](/developer-docs/api/get-related-fields-data-chart-related-column-name) | `/api/v1/chart/related/{column_name}` |
| `PUT` | [Warm up the cache for the chart](/developer-docs/api/warm-up-the-cache-for-the-chart) | `/api/v1/chart/warm_up_cache` |
</details>
@@ -125,24 +125,24 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `DELETE` | [Bulk delete datasets](./api/bulk-delete-datasets) | `/api/v1/dataset/` |
| `GET` | [Get a list of datasets](./api/get-a-list-of-datasets) | `/api/v1/dataset/` |
| `POST` | [Create a new dataset](./api/create-a-new-dataset) | `/api/v1/dataset/` |
| `GET` | [Get metadata information about this API resource (dataset--info)](./api/get-metadata-information-about-this-api-resource-dataset-info) | `/api/v1/dataset/_info` |
| `DELETE` | [Delete a dataset](./api/delete-a-dataset) | `/api/v1/dataset/{pk}` |
| `GET` | [Get a dataset](./api/get-a-dataset) | `/api/v1/dataset/{pk}` |
| `PUT` | [Update a dataset](./api/update-a-dataset) | `/api/v1/dataset/{pk}` |
| `DELETE` | [Delete a dataset column](./api/delete-a-dataset-column) | `/api/v1/dataset/{pk}/column/{column_id}` |
| `DELETE` | [Delete a dataset metric](./api/delete-a-dataset-metric) | `/api/v1/dataset/{pk}/metric/{metric_id}` |
| `PUT` | [Refresh and update columns of a dataset](./api/refresh-and-update-columns-of-a-dataset) | `/api/v1/dataset/{pk}/refresh` |
| `GET` | [Get charts and dashboards count associated to a dataset](./api/get-charts-and-dashboards-count-associated-to-a-dataset) | `/api/v1/dataset/{pk}/related_objects` |
| `GET` | [Get distinct values from field data (dataset-distinct-column-name)](./api/get-distinct-values-from-field-data-dataset-distinct-column-name) | `/api/v1/dataset/distinct/{column_name}` |
| `POST` | [Duplicate a dataset](./api/duplicate-a-dataset) | `/api/v1/dataset/duplicate` |
| `GET` | [Download multiple datasets as YAML files](./api/download-multiple-datasets-as-yaml-files) | `/api/v1/dataset/export/` |
| `POST` | [Retrieve a table by name, or create it if it does not exist](./api/retrieve-a-table-by-name-or-create-it-if-it-does-not-exist) | `/api/v1/dataset/get_or_create/` |
| `POST` | [Import dataset(s) with associated databases](./api/import-dataset-s-with-associated-databases) | `/api/v1/dataset/import/` |
| `GET` | [Get related fields data (dataset-related-column-name)](./api/get-related-fields-data-dataset-related-column-name) | `/api/v1/dataset/related/{column_name}` |
| `PUT` | [Warm up the cache for each chart powered by the given table](./api/warm-up-the-cache-for-each-chart-powered-by-the-given-table) | `/api/v1/dataset/warm_up_cache` |
| `DELETE` | [Bulk delete datasets](/developer-docs/api/bulk-delete-datasets) | `/api/v1/dataset/` |
| `GET` | [Get a list of datasets](/developer-docs/api/get-a-list-of-datasets) | `/api/v1/dataset/` |
| `POST` | [Create a new dataset](/developer-docs/api/create-a-new-dataset) | `/api/v1/dataset/` |
| `GET` | [Get metadata information about this API resource (dataset--info)](/developer-docs/api/get-metadata-information-about-this-api-resource-dataset-info) | `/api/v1/dataset/_info` |
| `DELETE` | [Delete a dataset](/developer-docs/api/delete-a-dataset) | `/api/v1/dataset/{pk}` |
| `GET` | [Get a dataset](/developer-docs/api/get-a-dataset) | `/api/v1/dataset/{pk}` |
| `PUT` | [Update a dataset](/developer-docs/api/update-a-dataset) | `/api/v1/dataset/{pk}` |
| `DELETE` | [Delete a dataset column](/developer-docs/api/delete-a-dataset-column) | `/api/v1/dataset/{pk}/column/{column_id}` |
| `DELETE` | [Delete a dataset metric](/developer-docs/api/delete-a-dataset-metric) | `/api/v1/dataset/{pk}/metric/{metric_id}` |
| `PUT` | [Refresh and update columns of a dataset](/developer-docs/api/refresh-and-update-columns-of-a-dataset) | `/api/v1/dataset/{pk}/refresh` |
| `GET` | [Get charts and dashboards count associated to a dataset](/developer-docs/api/get-charts-and-dashboards-count-associated-to-a-dataset) | `/api/v1/dataset/{pk}/related_objects` |
| `GET` | [Get distinct values from field data (dataset-distinct-column-name)](/developer-docs/api/get-distinct-values-from-field-data-dataset-distinct-column-name) | `/api/v1/dataset/distinct/{column_name}` |
| `POST` | [Duplicate a dataset](/developer-docs/api/duplicate-a-dataset) | `/api/v1/dataset/duplicate` |
| `GET` | [Download multiple datasets as YAML files](/developer-docs/api/download-multiple-datasets-as-yaml-files) | `/api/v1/dataset/export/` |
| `POST` | [Retrieve a table by name, or create it if it does not exist](/developer-docs/api/retrieve-a-table-by-name-or-create-it-if-it-does-not-exist) | `/api/v1/dataset/get_or_create/` |
| `POST` | [Import dataset(s) with associated databases](/developer-docs/api/import-dataset-s-with-associated-databases) | `/api/v1/dataset/import/` |
| `GET` | [Get related fields data (dataset-related-column-name)](/developer-docs/api/get-related-fields-data-dataset-related-column-name) | `/api/v1/dataset/related/{column_name}` |
| `PUT` | [Warm up the cache for each chart powered by the given table](/developer-docs/api/warm-up-the-cache-for-each-chart-powered-by-the-given-table) | `/api/v1/dataset/warm_up_cache` |
</details>
@@ -151,37 +151,37 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get a list of databases](./api/get-a-list-of-databases) | `/api/v1/database/` |
| `POST` | [Create a new database](./api/create-a-new-database) | `/api/v1/database/` |
| `GET` | [Get metadata information about this API resource (database--info)](./api/get-metadata-information-about-this-api-resource-database-info) | `/api/v1/database/_info` |
| `DELETE` | [Delete a database](./api/delete-a-database) | `/api/v1/database/{pk}` |
| `GET` | [Get a database](./api/get-a-database) | `/api/v1/database/{pk}` |
| `PUT` | [Change a database](./api/change-a-database) | `/api/v1/database/{pk}` |
| `GET` | [Get all catalogs from a database](./api/get-all-catalogs-from-a-database) | `/api/v1/database/{pk}/catalogs/` |
| `GET` | [Get a database connection info](./api/get-a-database-connection-info) | `/api/v1/database/{pk}/connection` |
| `GET` | [Get function names supported by a database](./api/get-function-names-supported-by-a-database) | `/api/v1/database/{pk}/function_names/` |
| `GET` | [Get charts and dashboards count associated to a database](./api/get-charts-and-dashboards-count-associated-to-a-database) | `/api/v1/database/{pk}/related_objects/` |
| `GET` | [The list of the database schemas where to upload information](./api/the-list-of-the-database-schemas-where-to-upload-information) | `/api/v1/database/{pk}/schemas_access_for_file_upload/` |
| `GET` | [Get all schemas from a database](./api/get-all-schemas-from-a-database) | `/api/v1/database/{pk}/schemas/` |
| `GET` | [Get database select star for table (database-pk-select-star-table-name)](./api/get-database-select-star-for-table-database-pk-select-star-table-name) | `/api/v1/database/{pk}/select_star/{table_name}/` |
| `GET` | [Get database select star for table (database-pk-select-star-table-name-schema-name)](./api/get-database-select-star-for-table-database-pk-select-star-table-name-schema-name) | `/api/v1/database/{pk}/select_star/{table_name}/{schema_name}/` |
| `DELETE` | [Delete a SSH tunnel](./api/delete-a-ssh-tunnel) | `/api/v1/database/{pk}/ssh_tunnel/` |
| `POST` | [Re-sync all permissions for a database connection](./api/re-sync-all-permissions-for-a-database-connection) | `/api/v1/database/{pk}/sync_permissions/` |
| `GET` | [Get table extra metadata (database-pk-table-extra-table-name-schema-name)](./api/get-table-extra-metadata-database-pk-table-extra-table-name-schema-name) | `/api/v1/database/{pk}/table_extra/{table_name}/{schema_name}/` |
| `GET` | [Get table metadata](./api/get-table-metadata) | `/api/v1/database/{pk}/table_metadata/` |
| `GET` | [Get table extra metadata (database-pk-table-metadata-extra)](./api/get-table-extra-metadata-database-pk-table-metadata-extra) | `/api/v1/database/{pk}/table_metadata/extra/` |
| `GET` | [Get database table metadata](./api/get-database-table-metadata) | `/api/v1/database/{pk}/table/{table_name}/{schema_name}/` |
| `GET` | [Get a list of tables for given database](./api/get-a-list-of-tables-for-given-database) | `/api/v1/database/{pk}/tables/` |
| `POST` | [Upload a file to a database table](./api/upload-a-file-to-a-database-table) | `/api/v1/database/{pk}/upload/` |
| `POST` | [Validate arbitrary SQL](./api/validate-arbitrary-sql) | `/api/v1/database/{pk}/validate_sql/` |
| `GET` | [Get names of databases currently available](./api/get-names-of-databases-currently-available) | `/api/v1/database/available/` |
| `GET` | [Download database(s) and associated dataset(s) as a zip file](./api/download-database-s-and-associated-dataset-s-as-a-zip-file) | `/api/v1/database/export/` |
| `POST` | [Import database(s) with associated datasets](./api/import-database-s-with-associated-datasets) | `/api/v1/database/import/` |
| `GET` | [Receive personal access tokens from OAuth2](./api/receive-personal-access-tokens-from-oauth2) | `/api/v1/database/oauth2/` |
| `GET` | [Get related fields data (database-related-column-name)](./api/get-related-fields-data-database-related-column-name) | `/api/v1/database/related/{column_name}` |
| `POST` | [Test a database connection](./api/test-a-database-connection) | `/api/v1/database/test_connection/` |
| `POST` | [Upload a file and returns file metadata](./api/upload-a-file-and-returns-file-metadata) | `/api/v1/database/upload_metadata/` |
| `POST` | [Validate database connection parameters](./api/validate-database-connection-parameters) | `/api/v1/database/validate_parameters/` |
| `GET` | [Get a list of databases](/developer-docs/api/get-a-list-of-databases) | `/api/v1/database/` |
| `POST` | [Create a new database](/developer-docs/api/create-a-new-database) | `/api/v1/database/` |
| `GET` | [Get metadata information about this API resource (database--info)](/developer-docs/api/get-metadata-information-about-this-api-resource-database-info) | `/api/v1/database/_info` |
| `DELETE` | [Delete a database](/developer-docs/api/delete-a-database) | `/api/v1/database/{pk}` |
| `GET` | [Get a database](/developer-docs/api/get-a-database) | `/api/v1/database/{pk}` |
| `PUT` | [Change a database](/developer-docs/api/change-a-database) | `/api/v1/database/{pk}` |
| `GET` | [Get all catalogs from a database](/developer-docs/api/get-all-catalogs-from-a-database) | `/api/v1/database/{pk}/catalogs/` |
| `GET` | [Get a database connection info](/developer-docs/api/get-a-database-connection-info) | `/api/v1/database/{pk}/connection` |
| `GET` | [Get function names supported by a database](/developer-docs/api/get-function-names-supported-by-a-database) | `/api/v1/database/{pk}/function_names/` |
| `GET` | [Get charts and dashboards count associated to a database](/developer-docs/api/get-charts-and-dashboards-count-associated-to-a-database) | `/api/v1/database/{pk}/related_objects/` |
| `GET` | [The list of the database schemas where to upload information](/developer-docs/api/the-list-of-the-database-schemas-where-to-upload-information) | `/api/v1/database/{pk}/schemas_access_for_file_upload/` |
| `GET` | [Get all schemas from a database](/developer-docs/api/get-all-schemas-from-a-database) | `/api/v1/database/{pk}/schemas/` |
| `GET` | [Get database select star for table (database-pk-select-star-table-name)](/developer-docs/api/get-database-select-star-for-table-database-pk-select-star-table-name) | `/api/v1/database/{pk}/select_star/{table_name}/` |
| `GET` | [Get database select star for table (database-pk-select-star-table-name-schema-name)](/developer-docs/api/get-database-select-star-for-table-database-pk-select-star-table-name-schema-name) | `/api/v1/database/{pk}/select_star/{table_name}/{schema_name}/` |
| `DELETE` | [Delete a SSH tunnel](/developer-docs/api/delete-a-ssh-tunnel) | `/api/v1/database/{pk}/ssh_tunnel/` |
| `POST` | [Re-sync all permissions for a database connection](/developer-docs/api/re-sync-all-permissions-for-a-database-connection) | `/api/v1/database/{pk}/sync_permissions/` |
| `GET` | [Get table extra metadata (database-pk-table-extra-table-name-schema-name)](/developer-docs/api/get-table-extra-metadata-database-pk-table-extra-table-name-schema-name) | `/api/v1/database/{pk}/table_extra/{table_name}/{schema_name}/` |
| `GET` | [Get table metadata](/developer-docs/api/get-table-metadata) | `/api/v1/database/{pk}/table_metadata/` |
| `GET` | [Get table extra metadata (database-pk-table-metadata-extra)](/developer-docs/api/get-table-extra-metadata-database-pk-table-metadata-extra) | `/api/v1/database/{pk}/table_metadata/extra/` |
| `GET` | [Get database table metadata](/developer-docs/api/get-database-table-metadata) | `/api/v1/database/{pk}/table/{table_name}/{schema_name}/` |
| `GET` | [Get a list of tables for given database](/developer-docs/api/get-a-list-of-tables-for-given-database) | `/api/v1/database/{pk}/tables/` |
| `POST` | [Upload a file to a database table](/developer-docs/api/upload-a-file-to-a-database-table) | `/api/v1/database/{pk}/upload/` |
| `POST` | [Validate arbitrary SQL](/developer-docs/api/validate-arbitrary-sql) | `/api/v1/database/{pk}/validate_sql/` |
| `GET` | [Get names of databases currently available](/developer-docs/api/get-names-of-databases-currently-available) | `/api/v1/database/available/` |
| `GET` | [Download database(s) and associated dataset(s) as a zip file](/developer-docs/api/download-database-s-and-associated-dataset-s-as-a-zip-file) | `/api/v1/database/export/` |
| `POST` | [Import database(s) with associated datasets](/developer-docs/api/import-database-s-with-associated-datasets) | `/api/v1/database/import/` |
| `GET` | [Receive personal access tokens from OAuth2](/developer-docs/api/receive-personal-access-tokens-from-oauth2) | `/api/v1/database/oauth2/` |
| `GET` | [Get related fields data (database-related-column-name)](/developer-docs/api/get-related-fields-data-database-related-column-name) | `/api/v1/database/related/{column_name}` |
| `POST` | [Test a database connection](/developer-docs/api/test-a-database-connection) | `/api/v1/database/test_connection/` |
| `POST` | [Upload a file and returns file metadata](/developer-docs/api/upload-a-file-and-returns-file-metadata) | `/api/v1/database/upload_metadata/` |
| `POST` | [Validate database connection parameters](/developer-docs/api/validate-database-connection-parameters) | `/api/v1/database/validate_parameters/` |
</details>
@@ -192,7 +192,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Assemble Explore related information in a single endpoint](./api/assemble-explore-related-information-in-a-single-endpoint) | `/api/v1/explore/` |
| `GET` | [Assemble Explore related information in a single endpoint](/developer-docs/api/assemble-explore-related-information-in-a-single-endpoint) | `/api/v1/explore/` |
</details>
@@ -201,12 +201,12 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get the bootstrap data for SqlLab page](./api/get-the-bootstrap-data-for-sqllab-page) | `/api/v1/sqllab/` |
| `POST` | [Estimate the SQL query execution cost](./api/estimate-the-sql-query-execution-cost) | `/api/v1/sqllab/estimate/` |
| `POST` | [Execute a SQL query](./api/execute-a-sql-query) | `/api/v1/sqllab/execute/` |
| `GET` | [Export the SQL query results to a CSV](./api/export-the-sql-query-results-to-a-csv) | `/api/v1/sqllab/export/{client_id}/` |
| `POST` | [Format SQL code](./api/format-sql-code) | `/api/v1/sqllab/format_sql/` |
| `GET` | [Get the result of a SQL query execution](./api/get-the-result-of-a-sql-query-execution) | `/api/v1/sqllab/results/` |
| `GET` | [Get the bootstrap data for SqlLab page](/developer-docs/api/get-the-bootstrap-data-for-sqllab-page) | `/api/v1/sqllab/` |
| `POST` | [Estimate the SQL query execution cost](/developer-docs/api/estimate-the-sql-query-execution-cost) | `/api/v1/sqllab/estimate/` |
| `POST` | [Execute a SQL query](/developer-docs/api/execute-a-sql-query) | `/api/v1/sqllab/execute/` |
| `GET` | [Export the SQL query results to a CSV](/developer-docs/api/export-the-sql-query-results-to-a-csv) | `/api/v1/sqllab/export/{client_id}/` |
| `POST` | [Format SQL code](/developer-docs/api/format-sql-code) | `/api/v1/sqllab/format_sql/` |
| `GET` | [Get the result of a SQL query execution](/developer-docs/api/get-the-result-of-a-sql-query-execution) | `/api/v1/sqllab/results/` |
</details>
@@ -215,23 +215,23 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get a list of queries](./api/get-a-list-of-queries) | `/api/v1/query/` |
| `GET` | [Get query detail information](./api/get-query-detail-information) | `/api/v1/query/{pk}` |
| `GET` | [Get distinct values from field data (query-distinct-column-name)](./api/get-distinct-values-from-field-data-query-distinct-column-name) | `/api/v1/query/distinct/{column_name}` |
| `GET` | [Get related fields data (query-related-column-name)](./api/get-related-fields-data-query-related-column-name) | `/api/v1/query/related/{column_name}` |
| `POST` | [Manually stop a query with client_id](./api/manually-stop-a-query-with-client-id) | `/api/v1/query/stop` |
| `GET` | [Get a list of queries that changed after last_updated_ms](./api/get-a-list-of-queries-that-changed-after-last-updated-ms) | `/api/v1/query/updated_since` |
| `DELETE` | [Bulk delete saved queries](./api/bulk-delete-saved-queries) | `/api/v1/saved_query/` |
| `GET` | [Get a list of saved queries](./api/get-a-list-of-saved-queries) | `/api/v1/saved_query/` |
| `POST` | [Create a saved query](./api/create-a-saved-query) | `/api/v1/saved_query/` |
| `GET` | [Get metadata information about this API resource (saved-query--info)](./api/get-metadata-information-about-this-api-resource-saved-query-info) | `/api/v1/saved_query/_info` |
| `DELETE` | [Delete a saved query](./api/delete-a-saved-query) | `/api/v1/saved_query/{pk}` |
| `GET` | [Get a saved query](./api/get-a-saved-query) | `/api/v1/saved_query/{pk}` |
| `PUT` | [Update a saved query](./api/update-a-saved-query) | `/api/v1/saved_query/{pk}` |
| `GET` | [Get distinct values from field data (saved-query-distinct-column-name)](./api/get-distinct-values-from-field-data-saved-query-distinct-column-name) | `/api/v1/saved_query/distinct/{column_name}` |
| `GET` | [Download multiple saved queries as YAML files](./api/download-multiple-saved-queries-as-yaml-files) | `/api/v1/saved_query/export/` |
| `POST` | [Import saved queries with associated databases](./api/import-saved-queries-with-associated-databases) | `/api/v1/saved_query/import/` |
| `GET` | [Get related fields data (saved-query-related-column-name)](./api/get-related-fields-data-saved-query-related-column-name) | `/api/v1/saved_query/related/{column_name}` |
| `GET` | [Get a list of queries](/developer-docs/api/get-a-list-of-queries) | `/api/v1/query/` |
| `GET` | [Get query detail information](/developer-docs/api/get-query-detail-information) | `/api/v1/query/{pk}` |
| `GET` | [Get distinct values from field data (query-distinct-column-name)](/developer-docs/api/get-distinct-values-from-field-data-query-distinct-column-name) | `/api/v1/query/distinct/{column_name}` |
| `GET` | [Get related fields data (query-related-column-name)](/developer-docs/api/get-related-fields-data-query-related-column-name) | `/api/v1/query/related/{column_name}` |
| `POST` | [Manually stop a query with client_id](/developer-docs/api/manually-stop-a-query-with-client-id) | `/api/v1/query/stop` |
| `GET` | [Get a list of queries that changed after last_updated_ms](/developer-docs/api/get-a-list-of-queries-that-changed-after-last-updated-ms) | `/api/v1/query/updated_since` |
| `DELETE` | [Bulk delete saved queries](/developer-docs/api/bulk-delete-saved-queries) | `/api/v1/saved_query/` |
| `GET` | [Get a list of saved queries](/developer-docs/api/get-a-list-of-saved-queries) | `/api/v1/saved_query/` |
| `POST` | [Create a saved query](/developer-docs/api/create-a-saved-query) | `/api/v1/saved_query/` |
| `GET` | [Get metadata information about this API resource (saved-query--info)](/developer-docs/api/get-metadata-information-about-this-api-resource-saved-query-info) | `/api/v1/saved_query/_info` |
| `DELETE` | [Delete a saved query](/developer-docs/api/delete-a-saved-query) | `/api/v1/saved_query/{pk}` |
| `GET` | [Get a saved query](/developer-docs/api/get-a-saved-query) | `/api/v1/saved_query/{pk}` |
| `PUT` | [Update a saved query](/developer-docs/api/update-a-saved-query) | `/api/v1/saved_query/{pk}` |
| `GET` | [Get distinct values from field data (saved-query-distinct-column-name)](/developer-docs/api/get-distinct-values-from-field-data-saved-query-distinct-column-name) | `/api/v1/saved_query/distinct/{column_name}` |
| `GET` | [Download multiple saved queries as YAML files](/developer-docs/api/download-multiple-saved-queries-as-yaml-files) | `/api/v1/saved_query/export/` |
| `POST` | [Import saved queries with associated databases](/developer-docs/api/import-saved-queries-with-associated-databases) | `/api/v1/saved_query/import/` |
| `GET` | [Get related fields data (saved-query-related-column-name)](/developer-docs/api/get-related-fields-data-saved-query-related-column-name) | `/api/v1/saved_query/related/{column_name}` |
</details>
@@ -240,7 +240,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get possible values for a datasource column](./api/get-possible-values-for-a-datasource-column) | `/api/v1/datasource/{datasource_type}/{datasource_id}/column/{column_name}/values/` |
| `GET` | [Get possible values for a datasource column](/developer-docs/api/get-possible-values-for-a-datasource-column) | `/api/v1/datasource/{datasource_type}/{datasource_id}/column/{column_name}/values/` |
</details>
@@ -249,8 +249,8 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Return an AdvancedDataTypeResponse](./api/return-an-advanceddatatyperesponse) | `/api/v1/advanced_data_type/convert` |
| `GET` | [Return a list of available advanced data types](./api/return-a-list-of-available-advanced-data-types) | `/api/v1/advanced_data_type/types` |
| `GET` | [Return an AdvancedDataTypeResponse](/developer-docs/api/return-an-advanceddatatyperesponse) | `/api/v1/advanced_data_type/convert` |
| `GET` | [Return a list of available advanced data types](/developer-docs/api/return-a-list-of-available-advanced-data-types) | `/api/v1/advanced_data_type/types` |
</details>
@@ -261,21 +261,21 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `DELETE` | [Bulk delete tags](./api/bulk-delete-tags) | `/api/v1/tag/` |
| `GET` | [Get a list of tags](./api/get-a-list-of-tags) | `/api/v1/tag/` |
| `POST` | [Create a tag](./api/create-a-tag) | `/api/v1/tag/` |
| `GET` | [Get metadata information about tag API endpoints](./api/get-metadata-information-about-tag-api-endpoints) | `/api/v1/tag/_info` |
| `POST` | [Add tags to an object](./api/add-tags-to-an-object) | `/api/v1/tag/{object_type}/{object_id}/` |
| `DELETE` | [Delete a tagged object](./api/delete-a-tagged-object) | `/api/v1/tag/{object_type}/{object_id}/{tag}/` |
| `DELETE` | [Delete a tag](./api/delete-a-tag) | `/api/v1/tag/{pk}` |
| `GET` | [Get a tag detail information](./api/get-a-tag-detail-information) | `/api/v1/tag/{pk}` |
| `PUT` | [Update a tag](./api/update-a-tag) | `/api/v1/tag/{pk}` |
| `DELETE` | [Delete tag by pk favorites](./api/delete-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
| `POST` | [Create tag by pk favorites](./api/create-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
| `POST` | [Bulk create tags and tagged objects](./api/bulk-create-tags-and-tagged-objects) | `/api/v1/tag/bulk_create` |
| `GET` | [Get tag favorite status](./api/get-tag-favorite-status) | `/api/v1/tag/favorite_status/` |
| `GET` | [Get all objects associated with a tag](./api/get-all-objects-associated-with-a-tag) | `/api/v1/tag/get_objects/` |
| `GET` | [Get related fields data (tag-related-column-name)](./api/get-related-fields-data-tag-related-column-name) | `/api/v1/tag/related/{column_name}` |
| `DELETE` | [Bulk delete tags](/developer-docs/api/bulk-delete-tags) | `/api/v1/tag/` |
| `GET` | [Get a list of tags](/developer-docs/api/get-a-list-of-tags) | `/api/v1/tag/` |
| `POST` | [Create a tag](/developer-docs/api/create-a-tag) | `/api/v1/tag/` |
| `GET` | [Get metadata information about tag API endpoints](/developer-docs/api/get-metadata-information-about-tag-api-endpoints) | `/api/v1/tag/_info` |
| `POST` | [Add tags to an object](/developer-docs/api/add-tags-to-an-object) | `/api/v1/tag/{object_type}/{object_id}/` |
| `DELETE` | [Delete a tagged object](/developer-docs/api/delete-a-tagged-object) | `/api/v1/tag/{object_type}/{object_id}/{tag}/` |
| `DELETE` | [Delete a tag](/developer-docs/api/delete-a-tag) | `/api/v1/tag/{pk}` |
| `GET` | [Get a tag detail information](/developer-docs/api/get-a-tag-detail-information) | `/api/v1/tag/{pk}` |
| `PUT` | [Update a tag](/developer-docs/api/update-a-tag) | `/api/v1/tag/{pk}` |
| `DELETE` | [Delete tag by pk favorites](/developer-docs/api/delete-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
| `POST` | [Create tag by pk favorites](/developer-docs/api/create-tag-by-pk-favorites) | `/api/v1/tag/{pk}/favorites/` |
| `POST` | [Bulk create tags and tagged objects](/developer-docs/api/bulk-create-tags-and-tagged-objects) | `/api/v1/tag/bulk_create` |
| `GET` | [Get tag favorite status](/developer-docs/api/get-tag-favorite-status) | `/api/v1/tag/favorite_status/` |
| `GET` | [Get all objects associated with a tag](/developer-docs/api/get-all-objects-associated-with-a-tag) | `/api/v1/tag/get_objects/` |
| `GET` | [Get related fields data (tag-related-column-name)](/developer-docs/api/get-related-fields-data-tag-related-column-name) | `/api/v1/tag/related/{column_name}` |
</details>
@@ -284,20 +284,20 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `DELETE` | [Delete multiple annotation layers in a bulk operation](./api/delete-multiple-annotation-layers-in-a-bulk-operation) | `/api/v1/annotation_layer/` |
| `GET` | [Get a list of annotation layers (annotation-layer)](./api/get-a-list-of-annotation-layers-annotation-layer) | `/api/v1/annotation_layer/` |
| `POST` | [Create an annotation layer (annotation-layer)](./api/create-an-annotation-layer-annotation-layer) | `/api/v1/annotation_layer/` |
| `GET` | [Get metadata information about this API resource (annotation-layer--info)](./api/get-metadata-information-about-this-api-resource-annotation-layer-info) | `/api/v1/annotation_layer/_info` |
| `DELETE` | [Delete annotation layer (annotation-layer-pk)](./api/delete-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
| `GET` | [Get an annotation layer (annotation-layer-pk)](./api/get-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
| `PUT` | [Update an annotation layer (annotation-layer-pk)](./api/update-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
| `DELETE` | [Bulk delete annotation layers](./api/bulk-delete-annotation-layers) | `/api/v1/annotation_layer/{pk}/annotation/` |
| `GET` | [Get a list of annotation layers (annotation-layer-pk-annotation)](./api/get-a-list-of-annotation-layers-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
| `POST` | [Create an annotation layer (annotation-layer-pk-annotation)](./api/create-an-annotation-layer-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
| `DELETE` | [Delete annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/delete-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
| `GET` | [Get an annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/get-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
| `PUT` | [Update an annotation layer (annotation-layer-pk-annotation-annotation-id)](./api/update-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
| `GET` | [Get related fields data (annotation-layer-related-column-name)](./api/get-related-fields-data-annotation-layer-related-column-name) | `/api/v1/annotation_layer/related/{column_name}` |
| `DELETE` | [Delete multiple annotation layers in a bulk operation](/developer-docs/api/delete-multiple-annotation-layers-in-a-bulk-operation) | `/api/v1/annotation_layer/` |
| `GET` | [Get a list of annotation layers (annotation-layer)](/developer-docs/api/get-a-list-of-annotation-layers-annotation-layer) | `/api/v1/annotation_layer/` |
| `POST` | [Create an annotation layer (annotation-layer)](/developer-docs/api/create-an-annotation-layer-annotation-layer) | `/api/v1/annotation_layer/` |
| `GET` | [Get metadata information about this API resource (annotation-layer--info)](/developer-docs/api/get-metadata-information-about-this-api-resource-annotation-layer-info) | `/api/v1/annotation_layer/_info` |
| `DELETE` | [Delete annotation layer (annotation-layer-pk)](/developer-docs/api/delete-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
| `GET` | [Get an annotation layer (annotation-layer-pk)](/developer-docs/api/get-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
| `PUT` | [Update an annotation layer (annotation-layer-pk)](/developer-docs/api/update-an-annotation-layer-annotation-layer-pk) | `/api/v1/annotation_layer/{pk}` |
| `DELETE` | [Bulk delete annotation layers](/developer-docs/api/bulk-delete-annotation-layers) | `/api/v1/annotation_layer/{pk}/annotation/` |
| `GET` | [Get a list of annotation layers (annotation-layer-pk-annotation)](/developer-docs/api/get-a-list-of-annotation-layers-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
| `POST` | [Create an annotation layer (annotation-layer-pk-annotation)](/developer-docs/api/create-an-annotation-layer-annotation-layer-pk-annotation) | `/api/v1/annotation_layer/{pk}/annotation/` |
| `DELETE` | [Delete annotation layer (annotation-layer-pk-annotation-annotation-id)](/developer-docs/api/delete-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
| `GET` | [Get an annotation layer (annotation-layer-pk-annotation-annotation-id)](/developer-docs/api/get-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
| `PUT` | [Update an annotation layer (annotation-layer-pk-annotation-annotation-id)](/developer-docs/api/update-an-annotation-layer-annotation-layer-pk-annotation-annotation-id) | `/api/v1/annotation_layer/{pk}/annotation/{annotation_id}` |
| `GET` | [Get related fields data (annotation-layer-related-column-name)](/developer-docs/api/get-related-fields-data-annotation-layer-related-column-name) | `/api/v1/annotation_layer/related/{column_name}` |
</details>
@@ -306,14 +306,14 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `DELETE` | [Bulk delete CSS templates](./api/bulk-delete-css-templates) | `/api/v1/css_template/` |
| `GET` | [Get a list of CSS templates](./api/get-a-list-of-css-templates) | `/api/v1/css_template/` |
| `POST` | [Create a CSS template](./api/create-a-css-template) | `/api/v1/css_template/` |
| `GET` | [Get metadata information about this API resource (css-template--info)](./api/get-metadata-information-about-this-api-resource-css-template-info) | `/api/v1/css_template/_info` |
| `DELETE` | [Delete a CSS template](./api/delete-a-css-template) | `/api/v1/css_template/{pk}` |
| `GET` | [Get a CSS template](./api/get-a-css-template) | `/api/v1/css_template/{pk}` |
| `PUT` | [Update a CSS template](./api/update-a-css-template) | `/api/v1/css_template/{pk}` |
| `GET` | [Get related fields data (css-template-related-column-name)](./api/get-related-fields-data-css-template-related-column-name) | `/api/v1/css_template/related/{column_name}` |
| `DELETE` | [Bulk delete CSS templates](/developer-docs/api/bulk-delete-css-templates) | `/api/v1/css_template/` |
| `GET` | [Get a list of CSS templates](/developer-docs/api/get-a-list-of-css-templates) | `/api/v1/css_template/` |
| `POST` | [Create a CSS template](/developer-docs/api/create-a-css-template) | `/api/v1/css_template/` |
| `GET` | [Get metadata information about this API resource (css-template--info)](/developer-docs/api/get-metadata-information-about-this-api-resource-css-template-info) | `/api/v1/css_template/_info` |
| `DELETE` | [Delete a CSS template](/developer-docs/api/delete-a-css-template) | `/api/v1/css_template/{pk}` |
| `GET` | [Get a CSS template](/developer-docs/api/get-a-css-template) | `/api/v1/css_template/{pk}` |
| `PUT` | [Update a CSS template](/developer-docs/api/update-a-css-template) | `/api/v1/css_template/{pk}` |
| `GET` | [Get related fields data (css-template-related-column-name)](/developer-docs/api/get-related-fields-data-css-template-related-column-name) | `/api/v1/css_template/related/{column_name}` |
</details>
@@ -324,8 +324,8 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | [Create a new dashboard's permanent link](./api/create-a-new-dashboard-s-permanent-link) | `/api/v1/dashboard/{pk}/permalink` |
| `GET` | [Get dashboard's permanent link state](./api/get-dashboard-s-permanent-link-state) | `/api/v1/dashboard/permalink/{key}` |
| `POST` | [Create a new dashboard's permanent link](/developer-docs/api/create-a-new-dashboard-s-permanent-link) | `/api/v1/dashboard/{pk}/permalink` |
| `GET` | [Get dashboard's permanent link state](/developer-docs/api/get-dashboard-s-permanent-link-state) | `/api/v1/dashboard/permalink/{key}` |
</details>
@@ -334,8 +334,8 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | [Create a new permanent link (explore-permalink)](./api/create-a-new-permanent-link-explore-permalink) | `/api/v1/explore/permalink` |
| `GET` | [Get chart's permanent link state](./api/get-chart-s-permanent-link-state) | `/api/v1/explore/permalink/{key}` |
| `POST` | [Create a new permanent link (explore-permalink)](/developer-docs/api/create-a-new-permanent-link-explore-permalink) | `/api/v1/explore/permalink` |
| `GET` | [Get chart's permanent link state](/developer-docs/api/get-chart-s-permanent-link-state) | `/api/v1/explore/permalink/{key}` |
</details>
@@ -344,8 +344,8 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | [Create a new permanent link (sqllab-permalink)](./api/create-a-new-permanent-link-sqllab-permalink) | `/api/v1/sqllab/permalink` |
| `GET` | [Get permanent link state for SQLLab editor.](./api/get-permanent-link-state-for-sqllab-editor) | `/api/v1/sqllab/permalink/{key}` |
| `POST` | [Create a new permanent link (sqllab-permalink)](/developer-docs/api/create-a-new-permanent-link-sqllab-permalink) | `/api/v1/sqllab/permalink` |
| `GET` | [Get permanent link state for SQLLab editor.](/developer-docs/api/get-permanent-link-state-for-sqllab-editor) | `/api/v1/sqllab/permalink/{key}` |
</details>
@@ -354,7 +354,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get a report schedule log (embedded-dashboard-uuid)](./api/get-a-report-schedule-log-embedded-dashboard-uuid) | `/api/v1/embedded_dashboard/{uuid}` |
| `GET` | [Get a report schedule log (embedded-dashboard-uuid)](/developer-docs/api/get-a-report-schedule-log-embedded-dashboard-uuid) | `/api/v1/embedded_dashboard/{uuid}` |
</details>
@@ -363,10 +363,10 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | [Create a dashboard's filter state](./api/create-a-dashboard-s-filter-state) | `/api/v1/dashboard/{pk}/filter_state` |
| `DELETE` | [Delete a dashboard's filter state value](./api/delete-a-dashboard-s-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` |
| `GET` | [Get a dashboard's filter state value](./api/get-a-dashboard-s-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` |
| `PUT` | [Update a dashboard's filter state value](./api/update-a-dashboard-s-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` |
| `POST` | [Create a dashboard's filter state](/developer-docs/api/create-a-dashboard-s-filter-state) | `/api/v1/dashboard/{pk}/filter_state` |
| `DELETE` | [Delete a dashboard's filter state value](/developer-docs/api/delete-a-dashboard-s-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` |
| `GET` | [Get a dashboard's filter state value](/developer-docs/api/get-a-dashboard-s-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` |
| `PUT` | [Update a dashboard's filter state value](/developer-docs/api/update-a-dashboard-s-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` |
</details>
@@ -375,10 +375,10 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | [Create a new form_data](./api/create-a-new-form-data) | `/api/v1/explore/form_data` |
| `DELETE` | [Delete a form_data](./api/delete-a-form-data) | `/api/v1/explore/form_data/{key}` |
| `GET` | [Get a form_data](./api/get-a-form-data) | `/api/v1/explore/form_data/{key}` |
| `PUT` | [Update an existing form_data](./api/update-an-existing-form-data) | `/api/v1/explore/form_data/{key}` |
| `POST` | [Create a new form_data](/developer-docs/api/create-a-new-form-data) | `/api/v1/explore/form_data` |
| `DELETE` | [Delete a form_data](/developer-docs/api/delete-a-form-data) | `/api/v1/explore/form_data/{key}` |
| `GET` | [Get a form_data](/developer-docs/api/get-a-form-data) | `/api/v1/explore/form_data/{key}` |
| `PUT` | [Update an existing form_data](/developer-docs/api/update-an-existing-form-data) | `/api/v1/explore/form_data/{key}` |
</details>
@@ -389,17 +389,17 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `DELETE` | [Bulk delete report schedules](./api/bulk-delete-report-schedules) | `/api/v1/report/` |
| `GET` | [Get a list of report schedules](./api/get-a-list-of-report-schedules) | `/api/v1/report/` |
| `POST` | [Create a report schedule](./api/create-a-report-schedule) | `/api/v1/report/` |
| `GET` | [Get metadata information about this API resource (report--info)](./api/get-metadata-information-about-this-api-resource-report-info) | `/api/v1/report/_info` |
| `DELETE` | [Delete a report schedule](./api/delete-a-report-schedule) | `/api/v1/report/{pk}` |
| `GET` | [Get a report schedule](./api/get-a-report-schedule) | `/api/v1/report/{pk}` |
| `PUT` | [Update a report schedule](./api/update-a-report-schedule) | `/api/v1/report/{pk}` |
| `GET` | [Get a list of report schedule logs](./api/get-a-list-of-report-schedule-logs) | `/api/v1/report/{pk}/log/` |
| `GET` | [Get a report schedule log (report-pk-log-log-id)](./api/get-a-report-schedule-log-report-pk-log-log-id) | `/api/v1/report/{pk}/log/{log_id}` |
| `GET` | [Get related fields data (report-related-column-name)](./api/get-related-fields-data-report-related-column-name) | `/api/v1/report/related/{column_name}` |
| `GET` | [Get slack channels](./api/get-slack-channels) | `/api/v1/report/slack_channels/` |
| `DELETE` | [Bulk delete report schedules](/developer-docs/api/bulk-delete-report-schedules) | `/api/v1/report/` |
| `GET` | [Get a list of report schedules](/developer-docs/api/get-a-list-of-report-schedules) | `/api/v1/report/` |
| `POST` | [Create a report schedule](/developer-docs/api/create-a-report-schedule) | `/api/v1/report/` |
| `GET` | [Get metadata information about this API resource (report--info)](/developer-docs/api/get-metadata-information-about-this-api-resource-report-info) | `/api/v1/report/_info` |
| `DELETE` | [Delete a report schedule](/developer-docs/api/delete-a-report-schedule) | `/api/v1/report/{pk}` |
| `GET` | [Get a report schedule](/developer-docs/api/get-a-report-schedule) | `/api/v1/report/{pk}` |
| `PUT` | [Update a report schedule](/developer-docs/api/update-a-report-schedule) | `/api/v1/report/{pk}` |
| `GET` | [Get a list of report schedule logs](/developer-docs/api/get-a-list-of-report-schedule-logs) | `/api/v1/report/{pk}/log/` |
| `GET` | [Get a report schedule log (report-pk-log-log-id)](/developer-docs/api/get-a-report-schedule-log-report-pk-log-log-id) | `/api/v1/report/{pk}/log/{log_id}` |
| `GET` | [Get related fields data (report-related-column-name)](/developer-docs/api/get-related-fields-data-report-related-column-name) | `/api/v1/report/related/{column_name}` |
| `GET` | [Get slack channels](/developer-docs/api/get-slack-channels) | `/api/v1/report/slack_channels/` |
</details>
@@ -410,16 +410,16 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get security roles](./api/get-security-roles) | `/api/v1/security/roles/` |
| `POST` | [Create security roles](./api/create-security-roles) | `/api/v1/security/roles/` |
| `GET` | [Get security roles info](./api/get-security-roles-info) | `/api/v1/security/roles/_info` |
| `DELETE` | [Delete security roles by pk](./api/delete-security-roles-by-pk) | `/api/v1/security/roles/{pk}` |
| `GET` | [Get security roles by pk](./api/get-security-roles-by-pk) | `/api/v1/security/roles/{pk}` |
| `PUT` | [Update security roles by pk](./api/update-security-roles-by-pk) | `/api/v1/security/roles/{pk}` |
| `POST` | [Create security roles by role_id permissions](./api/create-security-roles-by-role-id-permissions) | `/api/v1/security/roles/{role_id}/permissions` |
| `GET` | [Get security roles by role_id permissions](./api/get-security-roles-by-role-id-permissions) | `/api/v1/security/roles/{role_id}/permissions/` |
| `PUT` | [Update security roles by role_id users](./api/update-security-roles-by-role-id-users) | `/api/v1/security/roles/{role_id}/users` |
| `GET` | [List roles](./api/list-roles) | `/api/v1/security/roles/search/` |
| `GET` | [Get security roles](/developer-docs/api/get-security-roles) | `/api/v1/security/roles/` |
| `POST` | [Create security roles](/developer-docs/api/create-security-roles) | `/api/v1/security/roles/` |
| `GET` | [Get security roles info](/developer-docs/api/get-security-roles-info) | `/api/v1/security/roles/_info` |
| `DELETE` | [Delete security roles by pk](/developer-docs/api/delete-security-roles-by-pk) | `/api/v1/security/roles/{pk}` |
| `GET` | [Get security roles by pk](/developer-docs/api/get-security-roles-by-pk) | `/api/v1/security/roles/{pk}` |
| `PUT` | [Update security roles by pk](/developer-docs/api/update-security-roles-by-pk) | `/api/v1/security/roles/{pk}` |
| `POST` | [Create security roles by role_id permissions](/developer-docs/api/create-security-roles-by-role-id-permissions) | `/api/v1/security/roles/{role_id}/permissions` |
| `GET` | [Get security roles by role_id permissions](/developer-docs/api/get-security-roles-by-role-id-permissions) | `/api/v1/security/roles/{role_id}/permissions/` |
| `PUT` | [Update security roles by role_id users](/developer-docs/api/update-security-roles-by-role-id-users) | `/api/v1/security/roles/{role_id}/users` |
| `GET` | [List roles](/developer-docs/api/list-roles) | `/api/v1/security/roles/search/` |
</details>
@@ -428,12 +428,12 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get security users](./api/get-security-users) | `/api/v1/security/users/` |
| `POST` | [Create security users](./api/create-security-users) | `/api/v1/security/users/` |
| `GET` | [Get security users info](./api/get-security-users-info) | `/api/v1/security/users/_info` |
| `DELETE` | [Delete security users by pk](./api/delete-security-users-by-pk) | `/api/v1/security/users/{pk}` |
| `GET` | [Get security users by pk](./api/get-security-users-by-pk) | `/api/v1/security/users/{pk}` |
| `PUT` | [Update security users by pk](./api/update-security-users-by-pk) | `/api/v1/security/users/{pk}` |
| `GET` | [Get security users](/developer-docs/api/get-security-users) | `/api/v1/security/users/` |
| `POST` | [Create security users](/developer-docs/api/create-security-users) | `/api/v1/security/users/` |
| `GET` | [Get security users info](/developer-docs/api/get-security-users-info) | `/api/v1/security/users/_info` |
| `DELETE` | [Delete security users by pk](/developer-docs/api/delete-security-users-by-pk) | `/api/v1/security/users/{pk}` |
| `GET` | [Get security users by pk](/developer-docs/api/get-security-users-by-pk) | `/api/v1/security/users/{pk}` |
| `PUT` | [Update security users by pk](/developer-docs/api/update-security-users-by-pk) | `/api/v1/security/users/{pk}` |
</details>
@@ -442,9 +442,9 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get security permissions](./api/get-security-permissions) | `/api/v1/security/permissions/` |
| `GET` | [Get security permissions info](./api/get-security-permissions-info) | `/api/v1/security/permissions/_info` |
| `GET` | [Get security permissions by pk](./api/get-security-permissions-by-pk) | `/api/v1/security/permissions/{pk}` |
| `GET` | [Get security permissions](/developer-docs/api/get-security-permissions) | `/api/v1/security/permissions/` |
| `GET` | [Get security permissions info](/developer-docs/api/get-security-permissions-info) | `/api/v1/security/permissions/_info` |
| `GET` | [Get security permissions by pk](/developer-docs/api/get-security-permissions-by-pk) | `/api/v1/security/permissions/{pk}` |
</details>
@@ -453,12 +453,12 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get security resources](./api/get-security-resources) | `/api/v1/security/resources/` |
| `POST` | [Create security resources](./api/create-security-resources) | `/api/v1/security/resources/` |
| `GET` | [Get security resources info](./api/get-security-resources-info) | `/api/v1/security/resources/_info` |
| `DELETE` | [Delete security resources by pk](./api/delete-security-resources-by-pk) | `/api/v1/security/resources/{pk}` |
| `GET` | [Get security resources by pk](./api/get-security-resources-by-pk) | `/api/v1/security/resources/{pk}` |
| `PUT` | [Update security resources by pk](./api/update-security-resources-by-pk) | `/api/v1/security/resources/{pk}` |
| `GET` | [Get security resources](/developer-docs/api/get-security-resources) | `/api/v1/security/resources/` |
| `POST` | [Create security resources](/developer-docs/api/create-security-resources) | `/api/v1/security/resources/` |
| `GET` | [Get security resources info](/developer-docs/api/get-security-resources-info) | `/api/v1/security/resources/_info` |
| `DELETE` | [Delete security resources by pk](/developer-docs/api/delete-security-resources-by-pk) | `/api/v1/security/resources/{pk}` |
| `GET` | [Get security resources by pk](/developer-docs/api/get-security-resources-by-pk) | `/api/v1/security/resources/{pk}` |
| `PUT` | [Update security resources by pk](/developer-docs/api/update-security-resources-by-pk) | `/api/v1/security/resources/{pk}` |
</details>
@@ -467,12 +467,12 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get security permissions resources](./api/get-security-permissions-resources) | `/api/v1/security/permissions-resources/` |
| `POST` | [Create security permissions resources](./api/create-security-permissions-resources) | `/api/v1/security/permissions-resources/` |
| `GET` | [Get security permissions resources info](./api/get-security-permissions-resources-info) | `/api/v1/security/permissions-resources/_info` |
| `DELETE` | [Delete security permissions resources by pk](./api/delete-security-permissions-resources-by-pk) | `/api/v1/security/permissions-resources/{pk}` |
| `GET` | [Get security permissions resources by pk](./api/get-security-permissions-resources-by-pk) | `/api/v1/security/permissions-resources/{pk}` |
| `PUT` | [Update security permissions resources by pk](./api/update-security-permissions-resources-by-pk) | `/api/v1/security/permissions-resources/{pk}` |
| `GET` | [Get security permissions resources](/developer-docs/api/get-security-permissions-resources) | `/api/v1/security/permissions-resources/` |
| `POST` | [Create security permissions resources](/developer-docs/api/create-security-permissions-resources) | `/api/v1/security/permissions-resources/` |
| `GET` | [Get security permissions resources info](/developer-docs/api/get-security-permissions-resources-info) | `/api/v1/security/permissions-resources/_info` |
| `DELETE` | [Delete security permissions resources by pk](/developer-docs/api/delete-security-permissions-resources-by-pk) | `/api/v1/security/permissions-resources/{pk}` |
| `GET` | [Get security permissions resources by pk](/developer-docs/api/get-security-permissions-resources-by-pk) | `/api/v1/security/permissions-resources/{pk}` |
| `PUT` | [Update security permissions resources by pk](/developer-docs/api/update-security-permissions-resources-by-pk) | `/api/v1/security/permissions-resources/{pk}` |
</details>
@@ -481,14 +481,14 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `DELETE` | [Bulk delete RLS rules](./api/bulk-delete-rls-rules) | `/api/v1/rowlevelsecurity/` |
| `GET` | [Get a list of RLS](./api/get-a-list-of-rls) | `/api/v1/rowlevelsecurity/` |
| `POST` | [Create a new RLS rule](./api/create-a-new-rls-rule) | `/api/v1/rowlevelsecurity/` |
| `GET` | [Get metadata information about this API resource (rowlevelsecurity--info)](./api/get-metadata-information-about-this-api-resource-rowlevelsecurity-info) | `/api/v1/rowlevelsecurity/_info` |
| `DELETE` | [Delete an RLS](./api/delete-an-rls) | `/api/v1/rowlevelsecurity/{pk}` |
| `GET` | [Get an RLS](./api/get-an-rls) | `/api/v1/rowlevelsecurity/{pk}` |
| `PUT` | [Update an RLS rule](./api/update-an-rls-rule) | `/api/v1/rowlevelsecurity/{pk}` |
| `GET` | [Get related fields data (rowlevelsecurity-related-column-name)](./api/get-related-fields-data-rowlevelsecurity-related-column-name) | `/api/v1/rowlevelsecurity/related/{column_name}` |
| `DELETE` | [Bulk delete RLS rules](/developer-docs/api/bulk-delete-rls-rules) | `/api/v1/rowlevelsecurity/` |
| `GET` | [Get a list of RLS](/developer-docs/api/get-a-list-of-rls) | `/api/v1/rowlevelsecurity/` |
| `POST` | [Create a new RLS rule](/developer-docs/api/create-a-new-rls-rule) | `/api/v1/rowlevelsecurity/` |
| `GET` | [Get metadata information about this API resource (rowlevelsecurity--info)](/developer-docs/api/get-metadata-information-about-this-api-resource-rowlevelsecurity-info) | `/api/v1/rowlevelsecurity/_info` |
| `DELETE` | [Delete an RLS](/developer-docs/api/delete-an-rls) | `/api/v1/rowlevelsecurity/{pk}` |
| `GET` | [Get an RLS](/developer-docs/api/get-an-rls) | `/api/v1/rowlevelsecurity/{pk}` |
| `PUT` | [Update an RLS rule](/developer-docs/api/update-an-rls-rule) | `/api/v1/rowlevelsecurity/{pk}` |
| `GET` | [Get related fields data (rowlevelsecurity-related-column-name)](/developer-docs/api/get-related-fields-data-rowlevelsecurity-related-column-name) | `/api/v1/rowlevelsecurity/related/{column_name}` |
</details>
@@ -499,8 +499,8 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Export all assets](./api/export-all-assets) | `/api/v1/assets/export/` |
| `POST` | [Import multiple assets](./api/import-multiple-assets) | `/api/v1/assets/import/` |
| `GET` | [Export all assets](/developer-docs/api/export-all-assets) | `/api/v1/assets/export/` |
| `POST` | [Import multiple assets](/developer-docs/api/import-multiple-assets) | `/api/v1/assets/import/` |
</details>
@@ -509,7 +509,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | [Invalidate cache records and remove the database records](./api/invalidate-cache-records-and-remove-the-database-records) | `/api/v1/cachekey/invalidate` |
| `POST` | [Invalidate cache records and remove the database records](/developer-docs/api/invalidate-cache-records-and-remove-the-database-records) | `/api/v1/cachekey/invalidate` |
</details>
@@ -518,10 +518,10 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get a list of logs](./api/get-a-list-of-logs) | `/api/v1/log/` |
| `POST` | [Create log](./api/create-log) | `/api/v1/log/` |
| `GET` | [Get a log detail information](./api/get-a-log-detail-information) | `/api/v1/log/{pk}` |
| `GET` | [Get recent activity data for a user](./api/get-recent-activity-data-for-a-user) | `/api/v1/log/recent_activity/` |
| `GET` | [Get a list of logs](/developer-docs/api/get-a-list-of-logs) | `/api/v1/log/` |
| `POST` | [Create log](/developer-docs/api/create-log) | `/api/v1/log/` |
| `GET` | [Get a log detail information](/developer-docs/api/get-a-log-detail-information) | `/api/v1/log/{pk}` |
| `GET` | [Get recent activity data for a user](/developer-docs/api/get-recent-activity-data-for-a-user) | `/api/v1/log/recent_activity/` |
</details>
@@ -532,8 +532,8 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get the user object](./api/get-the-user-object) | `/api/v1/me/` |
| `GET` | [Get the user roles](./api/get-the-user-roles) | `/api/v1/me/roles/` |
| `GET` | [Get the user object](/developer-docs/api/get-the-user-object) | `/api/v1/me/` |
| `GET` | [Get the user roles](/developer-docs/api/get-the-user-roles) | `/api/v1/me/roles/` |
</details>
@@ -542,7 +542,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get the user avatar](./api/get-the-user-avatar) | `/api/v1/user/{user_id}/avatar.png` |
| `GET` | [Get the user avatar](/developer-docs/api/get-the-user-avatar) | `/api/v1/user/{user_id}/avatar.png` |
</details>
@@ -551,7 +551,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get menu](./api/get-menu) | `/api/v1/menu/` |
| `GET` | [Get menu](/developer-docs/api/get-menu) | `/api/v1/menu/` |
</details>
@@ -560,7 +560,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get all available domains](./api/get-all-available-domains) | `/api/v1/available_domains/` |
| `GET` | [Get all available domains](/developer-docs/api/get-all-available-domains) | `/api/v1/available_domains/` |
</details>
@@ -569,7 +569,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Read off of the Redis events stream](./api/read-off-of-the-redis-events-stream) | `/api/v1/async_event/` |
| `GET` | [Read off of the Redis events stream](/developer-docs/api/read-off-of-the-redis-events-stream) | `/api/v1/async_event/` |
</details>
@@ -578,7 +578,29 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [Get api by version openapi](./api/get-api-by-version-openapi) | `/api/{version}/_openapi` |
| `GET` | [Get api by version openapi](/developer-docs/api/get-api-by-version-openapi) | `/api/{version}/_openapi` |
</details>
<details>
<summary><strong>Themes</strong> (14 endpoints) — Manage UI themes for customizing Superset's appearance.</summary>
| Method | Endpoint | Description |
|--------|----------|-------------|
| `DELETE` | [Bulk delete themes](/developer-docs/api/bulk-delete-themes) | `/api/v1/theme/` |
| `GET` | [Get a list of themes](/developer-docs/api/get-a-list-of-themes) | `/api/v1/theme/` |
| `POST` | [Create a theme](/developer-docs/api/create-a-theme) | `/api/v1/theme/` |
| `GET` | [Get metadata information about this API resource (theme-info)](/developer-docs/api/get-metadata-information-about-this-api-resource-theme-info) | `/api/v1/theme/_info` |
| `DELETE` | [Delete a theme](/developer-docs/api/delete-a-theme) | `/api/v1/theme/{pk}` |
| `GET` | [Get a theme](/developer-docs/api/get-a-theme) | `/api/v1/theme/{pk}` |
| `PUT` | [Update a theme](/developer-docs/api/update-a-theme) | `/api/v1/theme/{pk}` |
| `PUT` | [Set a theme as the system dark theme](/developer-docs/api/set-a-theme-as-the-system-dark-theme) | `/api/v1/theme/{pk}/set_system_dark` |
| `PUT` | [Set a theme as the system default theme](/developer-docs/api/set-a-theme-as-the-system-default-theme) | `/api/v1/theme/{pk}/set_system_default` |
| `GET` | [Download multiple themes as YAML files](/developer-docs/api/download-multiple-themes-as-yaml-files) | `/api/v1/theme/export/` |
| `POST` | [Import themes from a ZIP file](/developer-docs/api/import-themes-from-a-zip-file) | `/api/v1/theme/import/` |
| `GET` | [Get related fields data (theme-related-column-name)](/developer-docs/api/get-related-fields-data-theme-related-column-name) | `/api/v1/theme/related/{column_name}` |
| `DELETE` | [Clear the system dark theme](/developer-docs/api/clear-the-system-dark-theme) | `/api/v1/theme/unset_system_dark` |
| `DELETE` | [Clear the system default theme](/developer-docs/api/clear-the-system-default-theme) | `/api/v1/theme/unset_system_default` |
</details>

View File

@@ -39,13 +39,17 @@ superset-extensions bundle: Packages the extension into a .supx file.
superset-extensions dev: Automatically rebuilds the extension as files change.
superset-extensions validate: Validates the extension structure and metadata.
superset-extensions validate: Validates the extension structure and metadata consistency.
superset-extensions update: Updates derived and generated files in the extension project.
Use --version [<version>] to update the version (prompts if no value given).
Use --license [<license>] to update the license (prompts if no value given).
```
When creating a new extension with `superset-extensions init`, the CLI generates a standardized folder structure:
```
my-org.dataset-references/
dataset-references/
├── extension.json
├── frontend/
│ ├── src/
@@ -76,7 +80,7 @@ my-org.dataset-references/
```
**Note**: With publisher `my-org` and name `dataset-references`, the technical names are:
- Directory name: `my-org.dataset-references` (kebab-case)
- Directory name: `dataset-references` (kebab-case)
- Backend Python namespace: `my_org.dataset_references`
- Backend distribution package: `my_org-dataset_references`
- Frontend package name: `@my-org/dataset-references` (scoped)

View File

@@ -75,7 +75,7 @@ This approach ensures that extensions from different organizations cannot confli
This creates a complete project structure:
```
my-org.hello-world/
hello-world/
├── extension.json # Extension metadata and configuration
├── backend/ # Backend Python code
│ ├── src/

View File

@@ -52,7 +52,6 @@ module.exports = {
'extensions/development',
'extensions/deployment',
'extensions/mcp',
'extensions/mcp-server',
'extensions/security',
'extensions/tasks',
'extensions/registry',

View File

@@ -63,6 +63,109 @@ pytest tests/unit_tests/
pytest tests/integration_tests/
```
## Testing Alerts & Reports with Celery and MailHog
The Alerts & Reports feature relies on Celery for task scheduling and execution. To test it locally, you need Redis (message broker), Celery Beat (scheduler), a Celery Worker (executor), and an SMTP server to receive email notifications.
### Prerequisites
- Redis running on `localhost:6379`
- [MailHog](https://github.com/mailhog/MailHog) installed (a local SMTP server with a web UI for viewing caught emails)
### superset_config.py
Your `CeleryConfig` **must** include `beat_schedule`. When you define a custom `CeleryConfig` class in `superset_config.py`, it replaces the default entirely. If you omit `beat_schedule`, Celery Beat will start but never schedule any report tasks.
```python
from celery.schedules import crontab
from superset.tasks.types import ExecutorType
REDIS_HOST = "localhost"
REDIS_PORT = "6379"
class CeleryConfig:
broker_url = f"redis://{REDIS_HOST}:{REDIS_PORT}/0"
result_backend = f"redis://{REDIS_HOST}:{REDIS_PORT}/0"
broker_connection_retry_on_startup = True
imports = (
"superset.sql_lab",
"superset.tasks.scheduler",
"superset.tasks.thumbnails",
"superset.tasks.cache",
)
worker_prefetch_multiplier = 10
task_acks_late = True
beat_schedule = {
"reports.scheduler": {
"task": "reports.scheduler",
"schedule": crontab(minute="*", hour="*"),
},
"reports.prune_log": {
"task": "reports.prune_log",
"schedule": crontab(minute=0, hour=0),
},
}
CELERY_CONFIG = CeleryConfig
# SMTP settings pointing to MailHog
SMTP_HOST = "localhost"
SMTP_PORT = 1025
SMTP_STARTTLS = False
SMTP_SSL = False
SMTP_USER = ""
SMTP_PASSWORD = ""
SMTP_MAIL_FROM = "superset@localhost"
# Must match where your frontend is running
WEBDRIVER_BASEURL = "http://localhost:9000/"
ALERT_REPORTS_EXECUTE_AS = [ExecutorType.OWNER]
FEATURE_FLAGS = {
"ALERT_REPORTS": True,
# Recommended for better screenshot support (WebGL/DeckGL charts)
"PLAYWRIGHT_REPORTS_AND_THUMBNAILS": True,
}
```
:::note
Do not include `"superset.tasks.async_queries"` in `CeleryConfig.imports` unless you need Global Async Queries. That module accesses `current_app.config` at import time and will crash the worker with a "Working outside of application context" error.
:::
### Starting the Services
Start MailHog, then Celery Beat and Worker in separate terminals:
```bash
# Terminal 1 - MailHog (SMTP on :1025, Web UI on :8025)
MailHog
# Terminal 2 - Celery Beat (scheduler)
celery --app=superset.tasks.celery_app:app beat --loglevel=info
# Terminal 3 - Celery Worker (executor)
celery --app=superset.tasks.celery_app:app worker --concurrency=1 --loglevel=info
```
Use `--concurrency=1` to limit resource usage on your dev machine.
### Verifying the Setup
1. **Beat** should log `Scheduler: Sending due task reports.scheduler (reports.scheduler)` once per minute
2. **Worker** should log `Scheduling alert <name> eta: <timestamp>` for each active report
3. Create a test report in **Settings > Alerts & Reports** with a `* * * * *` cron schedule
4. Check **http://localhost:8025** (MailHog web UI) for the email within 1-2 minutes
### Troubleshooting
| Problem | Solution |
|---|---|
| Beat shows no output | Ensure `beat_schedule` is defined in your `CeleryConfig` and `--loglevel=info` is set |
| "Report Schedule is still working, refusing to re-compute" | Previous executions are stuck. Reset with: `UPDATE report_schedule SET last_state = 'Not triggered' WHERE id = <id>;` |
| Task backlog overwhelming the worker | Flush Redis: `redis-cli FLUSHDB`, then restart Beat and Worker |
| Screenshot timeout | Ensure your frontend dev server is running and `WEBDRIVER_BASEURL` matches its URL |
---
*This documentation is under active development. Check back soon for updates!*

View File

@@ -91,7 +91,7 @@ or a view.
When working with tables, the solution would be to create a table that contains all the fields
needed for your analysis, most likely through some scheduled batch process.
A view is a simple logical layer that abstracts an arbitrary SQL queries as a virtual table. This can
A view is a simple logical layer that abstracts an arbitrary SQL query as a virtual table. This can
allow you to join and union multiple tables and to apply some transformation using arbitrary SQL
expressions. The limitation there is your database performance, as Superset effectively will run a
query on top of your query (view). A good practice may be to limit yourself to joining your main

View File

@@ -0,0 +1,78 @@
---
title: Granular Export Controls
sidebar_position: 4
---
# Granular Export Controls
Superset provides granular, permission-based controls for data export, image export, and clipboard operations. These replace the legacy `can_csv` permission with three fine-grained permissions that can be assigned independently to roles.
## Feature Flag
Granular export controls are gated behind the `GRANULAR_EXPORT_CONTROLS` feature flag. When the flag is disabled, the legacy `can_csv` permission behavior is preserved.
```python
FEATURE_FLAGS = {
"GRANULAR_EXPORT_CONTROLS": True,
}
```
## Permissions
| Permission | Resource | Controls |
| -------------------- | ---------- | ---------------------------------------------------------------------- |
| `can_export_data` | `Superset` | CSV, Excel, and JSON data exports from charts, dashboards, and SQL Lab |
| `can_export_image` | `Superset` | Screenshot (JPEG/PNG) and PDF exports from charts and dashboards |
| `can_copy_clipboard` | `Superset` | Copy-to-clipboard operations in SQL Lab and the Explore data pane |
## Default Role Assignments
The migration grants all three new permissions (`can_export_data`, `can_export_image`, `can_copy_clipboard`) to every role that currently has `can_csv`. This preserves existing behavior — no role loses access during the upgrade.
After the migration, admins can selectively revoke individual export permissions from any role to restrict access. For example, to prevent Gamma users from exporting data or images while still allowing clipboard operations, revoke `can_export_data` and `can_export_image` from the Gamma role.
## Configuration Steps
1. **Enable the feature flag** in `superset_config.py`:
```python
FEATURE_FLAGS = {
"GRANULAR_EXPORT_CONTROLS": True,
}
```
2. **Run the database migration** to register the new permissions:
```bash
superset db upgrade
```
3. **Initialize permissions** so roles are populated:
```bash
superset init
```
4. **Verify role assignments** in **Settings > List Roles**. Confirm that each role has the expected permissions from the table above.
5. **Customize as needed**: Grant or revoke individual export permissions on any role through the role editor.
## User Experience
When a user lacks a required export permission:
- **Menu items** (CSV, Excel, JSON, screenshot) appear **disabled** with an info tooltip icon explaining the restriction
- **Buttons** (SQL Lab download, clipboard copy) appear **disabled** with a tooltip on hover
- **API endpoints** return **403 Forbidden** when the corresponding permission is missing
## API Enforcement
The following API endpoints enforce granular export permissions when the feature flag is enabled:
| Endpoint | Required Permission |
| --------------------------------------------------------- | ------------------- |
| `GET /api/v1/chart/{id}/data/` (CSV/Excel format) | `can_export_data` |
| `GET /api/v1/chart/{id}/cache_screenshot/` | `can_export_image` |
| `POST /api/v1/dashboard/{id}/cache_dashboard_screenshot/` | `can_export_image` |
| `GET /api/v1/sqllab/export/{client_id}/` | `can_export_data` |
| `POST /api/v1/sqllab/export_streaming/` | `can_export_data` |

View File

@@ -0,0 +1,245 @@
---
title: Using AI with Superset
hide_title: true
sidebar_position: 5
version: 1
---
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Using AI with Superset
Superset supports AI assistants through the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/). Connect Claude, ChatGPT, or other MCP-compatible clients to explore your data, build charts, create dashboards, and run SQL -- all through natural language.
:::info
Requires Superset 5.0+. Your admin must enable and deploy the MCP server before you can connect.
See the **[MCP Server admin guide](/admin-docs/configuration/mcp-server)** for setup instructions.
:::
---
## What Can AI Do with Superset?
### Explore Your Data
Ask your AI assistant to browse what's available in your Superset instance:
- **List datasets** -- see all datasets you have access to, with filtering and search
- **Get dataset details** -- column names, types, available metrics, and filters
- **List charts and dashboards** -- find existing visualizations by name or keyword
- **Get chart and dashboard details** -- understand what a chart shows, its query, and configuration
**Example prompts:**
> "What datasets are available?"
> "Show me the columns in the sales_orders dataset"
> "Find dashboards related to revenue"
### Build Charts
Describe the visualization you want and AI creates it for you:
- **Create charts from natural language** -- describe what you want to see and AI picks the right chart type, metrics, and dimensions
- **Preview before saving** -- AI generates a preview so you can review before committing
- **Modify existing charts** -- update filters, change chart types, add metrics
- **Get Explore links** -- open any chart in Superset's Explore view for further refinement
**Example prompts:**
> "Create a bar chart showing monthly revenue by region from the sales dataset"
> "Update chart 42 to use a line chart instead"
> "Give me a link to explore this chart further"
### Create Dashboards
Build dashboards from a collection of charts:
- **Generate dashboards** -- create a new dashboard with a set of charts, automatically laid out
- **Add charts to existing dashboards** -- place a chart on an existing dashboard with automatic positioning
**Example prompts:**
> "Create a dashboard called 'Q4 Sales Overview' with charts 10, 15, and 22"
> "Add the revenue trend chart to the executive dashboard"
### Run SQL Queries
Execute SQL directly through your AI assistant:
- **Run queries** -- execute SQL with full Superset RBAC enforcement (you can only query data your roles allow)
- **Open SQL Lab** -- get a link to SQL Lab pre-populated with a query, ready to run and explore
**Example prompts:**
> "Run this query: SELECT region, SUM(revenue) FROM sales GROUP BY region"
> "Open SQL Lab with a query to show the top 10 customers by order count"
### Analyze Chart Data
Pull the raw data behind any chart:
- **Get chart data** -- retrieve the data a chart displays, with support for JSON, CSV, and Excel export formats
- **Inspect results** -- useful for verifying what a visualization shows or feeding data into other tools
**Example prompts:**
> "Get the data behind chart 42"
> "Export chart 15 data as CSV"
### Check Instance Status
- **Health check** -- verify your Superset instance is up and the MCP connection is working
- **Instance info** -- get high-level statistics about your Superset instance (number of datasets, charts, dashboards)
**Example prompts:**
> "Is Superset healthy?"
> "How many dashboards are in this instance?"
---
## Connecting Your AI Client
Once your admin has deployed the MCP server, connect your AI client using the instructions below.
### Claude Desktop
Edit your Claude Desktop config file:
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux**: `~/.config/Claude/claude_desktop_config.json`
```json
{
"mcpServers": {
"superset": {
"url": "http://localhost:5008/mcp"
}
}
}
```
Restart Claude Desktop. The hammer icon in the chat bar confirms the connection.
If your admin has enabled JWT authentication, you may need to include a token:
```json
{
"mcpServers": {
"superset": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"http://your-superset-host:5008/mcp",
"--header",
"Authorization: Bearer YOUR_TOKEN"
]
}
}
}
```
### Claude Code (CLI)
Add to your project's `.mcp.json`:
```json
{
"mcpServers": {
"superset": {
"type": "url",
"url": "http://localhost:5008/mcp"
}
}
}
```
### ChatGPT
1. Click your profile icon > **Settings** > **Apps and Connectors**
2. Enable **Developer Mode** in Advanced Settings
3. In the chat composer, press **+** > **Add sources** > **App** > **Connect more** > **Create app**
4. Enter a name and your MCP server URL
5. Click **I understand and continue**
:::info
ChatGPT MCP connectors require a Pro, Team, Enterprise, or Edu plan.
:::
Ask your admin for the MCP server URL and any authentication tokens you need.
---
## Tips for Best Results
- **Be specific** -- "Create a bar chart of monthly revenue by region from the sales dataset" works better than "Make me a chart"
- **Start with exploration** -- ask what datasets and charts exist before creating new ones
- **Review AI-generated content** -- always check chart configurations and SQL before saving or sharing
- **Use Explore for refinement** -- ask AI for an Explore link, then fine-tune interactively in the Superset UI
- **Check permissions if you get errors** -- AI respects Superset's RBAC, so you can only access data your roles allow
---
## Available Tools Reference
| Tool | Description |
|------|-------------|
| `health_check` | Verify the MCP server is running and connected |
| `get_instance_info` | Get instance statistics (dataset, chart, dashboard counts) |
| `get_schema` | Discover available charts, datasets, and dashboards with schema info |
| `list_datasets` | List datasets with filtering and search |
| `get_dataset_info` | Get dataset metadata (columns, metrics, filters) |
| `list_charts` | List charts with filtering and search |
| `get_chart_info` | Get chart metadata and configuration |
| `get_chart_data` | Retrieve chart data (JSON, CSV, or Excel) |
| `get_chart_preview` | Generate a chart preview (URL, ASCII, table, or Vega-Lite) |
| `generate_chart` | Create a new chart from a specification |
| `update_chart` | Modify an existing chart's configuration |
| `update_chart_preview` | Update a cached chart preview without saving |
| `list_dashboards` | List dashboards with filtering and search |
| `get_dashboard_info` | Get dashboard metadata and layout |
| `generate_dashboard` | Create a new dashboard with specified charts |
| `add_chart_to_existing_dashboard` | Add a chart to an existing dashboard |
| `execute_sql` | Run a SQL query with RBAC enforcement |
| `open_sql_lab_with_context` | Open SQL Lab with a pre-populated query |
| `generate_explore_link` | Generate an Explore URL for interactive visualization |
---
## Troubleshooting
### "Connection refused" or "Cannot connect"
- Confirm the MCP server URL with your admin
- For Claude Desktop: fully quit the app (not just close the window) and restart after config changes
- Check that the URL path ends with `/mcp` (e.g., `http://localhost:5008/mcp`)
### "Permission denied" or missing data
- Superset's RBAC controls what you can access through AI, just like in the Superset UI
- Ask your admin to verify your roles and permissions
- Try accessing the same data through the Superset web UI to confirm your access
### "Response too large"
- Ask for smaller result sets: use filters, reduce `page_size`, or request specific columns
- Example: "Show me the top 10 rows from the sales dataset" instead of "Show me all sales data"
### AI doesn't see Superset tools
- Verify the connection in your AI client (e.g., the hammer icon in Claude Desktop)
- Ask the AI "What Superset tools are available?" to confirm the connection
- Restart your AI client if you recently changed the configuration

View File

@@ -40,13 +40,13 @@
"version:remove:components": "node scripts/manage-versions.mjs remove components"
},
"dependencies": {
"@ant-design/icons": "^6.1.0",
"@docusaurus/core": "3.9.2",
"@docusaurus/faster": "^3.9.2",
"@docusaurus/plugin-client-redirects": "3.9.2",
"@docusaurus/preset-classic": "3.9.2",
"@docusaurus/theme-live-codeblock": "^3.9.2",
"@docusaurus/theme-mermaid": "^3.9.2",
"@ant-design/icons": "^6.1.1",
"@docusaurus/core": "^3.10.0",
"@docusaurus/faster": "^3.10.0",
"@docusaurus/plugin-client-redirects": "^3.10.0",
"@docusaurus/preset-classic": "3.10.0",
"@docusaurus/theme-live-codeblock": "^3.10.0",
"@docusaurus/theme-mermaid": "^3.10.0",
"@emotion/core": "^11.0.0",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.14.1",
@@ -67,12 +67,12 @@
"@storybook/preview-api": "^8.6.18",
"@storybook/theming": "^8.6.15",
"@superset-ui/core": "^0.20.4",
"@swc/core": "^1.15.17",
"antd": "^6.3.2",
"baseline-browser-mapping": "^2.10.0",
"caniuse-lite": "^1.0.30001775",
"docusaurus-plugin-openapi-docs": "^4.6.0",
"docusaurus-theme-openapi-docs": "^4.6.0",
"@swc/core": "^1.15.26",
"antd": "^6.3.6",
"baseline-browser-mapping": "^2.10.19",
"caniuse-lite": "^1.0.30001788",
"docusaurus-plugin-openapi-docs": "^5.0.1",
"docusaurus-theme-openapi-docs": "^5.0.1",
"js-yaml": "^4.1.1",
"js-yaml-loader": "^1.2.2",
"json-bigint": "^1.0.0",
@@ -86,14 +86,14 @@
"remark-import-partial": "^0.0.2",
"reselect": "^5.1.1",
"storybook": "^8.6.18",
"swagger-ui-react": "^5.32.0",
"swagger-ui-react": "^5.32.4",
"swc-loader": "^0.2.7",
"tinycolor2": "^1.4.2",
"unist-util-visit": "^5.1.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.9.1",
"@docusaurus/tsconfig": "^3.9.2",
"@docusaurus/module-type-aliases": "^3.10.0",
"@docusaurus/tsconfig": "^3.10.0",
"@eslint/js": "^9.39.2",
"@types/js-yaml": "^4.0.9",
"@types/react": "^19.1.8",
@@ -103,11 +103,11 @@
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-react": "^7.37.5",
"globals": "^17.4.0",
"prettier": "^3.8.1",
"globals": "^17.5.0",
"prettier": "^3.8.3",
"typescript": "~5.9.3",
"typescript-eslint": "^8.56.1",
"webpack": "^5.105.4"
"typescript-eslint": "^8.58.2",
"webpack": "^5.106.2"
},
"browserslist": {
"production": [
@@ -124,7 +124,8 @@
"resolutions": {
"react-redux": "^9.2.0",
"@reduxjs/toolkit": "^2.5.0",
"baseline-browser-mapping": "^2.9.19"
"baseline-browser-mapping": "^2.9.19",
"webpackbar": "^7.0.0"
},
"packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610"
}

View File

@@ -129,6 +129,30 @@ def add_missing_schemas(spec: dict[str, Any]) -> tuple[dict[str, Any], list[str]
}
fixed.append("DashboardColorsConfigUpdateSchema")
# DashboardChartCustomizationsConfigUpdateSchema (dashboards/schemas.py)
if "DashboardChartCustomizationsConfigUpdateSchema" not in schemas:
schemas["DashboardChartCustomizationsConfigUpdateSchema"] = {
"type": "object",
"properties": {
"deleted": {
"type": "array",
"items": {"type": "string"},
"description": "List of deleted chart customization IDs.",
},
"modified": {
"type": "array",
"items": {"type": "object"},
"description": "List of modified chart customizations.",
},
"reordered": {
"type": "array",
"items": {"type": "string"},
"description": "List of chart customization IDs in new order.",
},
},
}
fixed.append("DashboardChartCustomizationsConfigUpdateSchema")
# FormatQueryPayloadSchema - based on superset/sqllab/schemas.py
if "FormatQueryPayloadSchema" not in schemas:
schemas["FormatQueryPayloadSchema"] = {
@@ -295,6 +319,7 @@ TAG_DESCRIPTIONS = {
"Security Roles": "Manage security roles and their permissions.",
"Security Users": "Manage user accounts.",
"Tags": "Organize assets with tags.",
"Themes": "Manage UI themes for customizing Superset's appearance.",
"User": "User profile and preferences.",
}

View File

@@ -202,7 +202,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
mdx += `| Method | Endpoint | Description |\n`;
mdx += `|--------|----------|-------------|\n`;
for (const ep of tagEndpoints['Security']) {
mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;
mdx += `| \`${ep.method}\` | [${ep.summary}](/developer-docs/api/${ep.slug}) | \`${ep.path}\` |\n`;
}
mdx += '\n';
renderedTags.add('Security');
@@ -229,7 +229,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
mdx += `|--------|----------|-------------|\n`;
for (const ep of endpoints) {
mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;
mdx += `| \`${ep.method}\` | [${ep.summary}](/developer-docs/api/${ep.slug}) | \`${ep.path}\` |\n`;
}
mdx += `\n</details>\n\n`;
@@ -252,7 +252,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \\
mdx += `|--------|----------|-------------|\n`;
for (const ep of endpoints) {
mdx += `| \`${ep.method}\` | [${ep.summary}](./api/${ep.slug}) | \`${ep.path}\` |\n`;
mdx += `| \`${ep.method}\` | [${ep.summary}](/developer-docs/api/${ep.slug}) | \`${ep.path}\` |\n`;
}
mdx += `\n</details>\n\n`;

View File

@@ -51,6 +51,12 @@
"lifecycle": "development",
"description": "Enable Superset extensions for custom functionality without modifying core"
},
{
"name": "FAB_API_KEY_ENABLED",
"default": false,
"lifecycle": "development",
"description": "Enable API key authentication via FAB SecurityManager When enabled, users can create/manage API keys in the User Info page"
},
{
"name": "GRANULAR_EXPORT_CONTROLS",
"default": false,

BIN
docs/static/img/logos/hifadih.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -109,6 +109,14 @@ SECRET_KEY = 'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY'
You can generate a strong secure key with `openssl rand -base64 42`.
Alternatively, you can set the secret key using `SUPERSET_SECRET_KEY` environment variable:
On a Unix-based system, such as Linux or macOS, you can do so by running the following command in your terminal:
```bash
export SUPERSET_SECRET_KEY=$(openssl rand -base64 42)
```
:::caution Use a strong secret key
This key will be used for securely signing session cookies and encrypting sensitive information stored in Superset's application metadata database.
Your deployment must use a complex, unique key.

View File

@@ -35,7 +35,7 @@ or a view.
When working with tables, the solution would be to create a table that contains all the fields
needed for your analysis, most likely through some scheduled batch process.
A view is a simple logical layer that abstracts an arbitrary SQL queries as a virtual table. This can
A view is a simple logical layer that abstracts an arbitrary SQL query as a virtual table. This can
allow you to join and union multiple tables and to apply some transformation using arbitrary SQL
expressions. The limitation there is your database performance, as Superset effectively will run a
query on top of your query (view). A good practice may be to limit yourself to joining your main

File diff suppressed because it is too large Load Diff

View File

@@ -48,7 +48,7 @@ dependencies = [
"cryptography>=42.0.4, <47.0.0",
"deprecation>=2.1.0, <2.2.0",
"flask>=2.2.5, <4.0.0",
"flask-appbuilder>=5.0.2,<6",
"flask-appbuilder>=5.2.1, <6.0.0",
"flask-caching>=2.1.0, <3",
"flask-compress>=1.13, <2.0",
"flask-talisman>=1.0.0, <2.0",
@@ -144,7 +144,7 @@ solr = ["sqlalchemy-solr >= 0.2.0"]
elasticsearch = ["elasticsearch-dbapi>=0.2.12, <0.3.0"]
exasol = ["sqlalchemy-exasol >= 2.4.0, <3.0"]
excel = ["xlrd>=1.2.0, <1.3"]
fastmcp = ["fastmcp==2.14.3"]
fastmcp = ["fastmcp>=3.1.0,<4.0"]
firebird = ["sqlalchemy-firebird>=0.7.0, <0.8"]
firebolt = ["firebolt-sqlalchemy>=1.0.0, <2"]
gevent = ["gevent>=23.9.1"]
@@ -183,6 +183,7 @@ risingwave = ["sqlalchemy-risingwave"]
shillelagh = ["shillelagh[all]>=1.4.3, <2"]
singlestore = ["sqlalchemy-singlestoredb>=1.1.1, <2"]
snowflake = ["snowflake-sqlalchemy>=1.2.4, <2"]
sqlite = ["syntaqlite>=0.1.0"]
spark = [
"pyhive[hive]>=0.6.5;python_version<'3.11'",
"pyhive[hive_pure_sasl]>=0.7",
@@ -226,6 +227,7 @@ development = [
"ruff",
"sqloxide",
"statsd",
"syntaqlite>=0.1.0",
]
[project.urls]
@@ -238,7 +240,7 @@ combine_as_imports = true
include_trailing_comma = true
line_length = 88
known_first_party = "superset, apache-superset-core, apache-superset-extensions-cli"
known_third_party = "alembic, apispec, backoff, celery, click, colorama, cron_descriptor, croniter, cryptography, dateutil, deprecation, flask, flask_appbuilder, flask_babel, flask_caching, flask_compress, flask_jwt_extended, flask_login, flask_migrate, flask_sqlalchemy, flask_talisman, flask_testing, flask_wtf, freezegun, geohash, geopy, holidays, humanize, isodate, jinja2, jwt, markdown, markupsafe, marshmallow, marshmallow-union, msgpack, nh3, numpy, pandas, parameterized, parsedatetime, pgsanity, polyline, prison, progress, pyarrow, sqlalchemy_bigquery, pyhive, pyparsing, pytest, pytest_mock, pytz, redis, requests, selenium, setuptools, shillelagh, simplejson, slack, sqlalchemy, sqlalchemy_utils, typing_extensions, urllib3, werkzeug, wtforms, wtforms_json, yaml"
known_third_party = "alembic, apispec, backoff, celery, click, colorama, cron_descriptor, croniter, cryptography, dateutil, deprecation, flask, flask_appbuilder, flask_babel, flask_caching, flask_compress, flask_jwt_extended, flask_login, flask_migrate, flask_sqlalchemy, flask_talisman, flask_testing, flask_wtf, freezegun, geohash, geopy, holidays, humanize, isodate, jinja2, jwt, markdown, markupsafe, marshmallow, marshmallow-union, msgpack, nh3, numpy, pandas, parameterized, parsedatetime, pgsanity, polyline, prison, progress, pyarrow, sqlalchemy_bigquery, pyhive, pyparsing, pytest, pytest_mock, pytz, redis, requests, selenium, setuptools, shillelagh, simplejson, slack, sqlalchemy, sqlalchemy_utils, syntaqlite, typing_extensions, urllib3, werkzeug, wtforms, wtforms_json, yaml"
multi_line_output = 3
order_by_type = false
@@ -372,6 +374,7 @@ unfixable = []
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
[tool.ruff.lint.per-file-ignores]
"superset/mcp_service/app.py" = ["S608", "E501"] # LLM instruction text: SQL examples (S608) and long lines in multiline string (E501)
"scripts/*" = ["TID251"]
"setup.py" = ["TID251"]
"superset/config.py" = ["TID251"]

View File

@@ -86,7 +86,7 @@ cron-descriptor==1.4.5
# via apache-superset (pyproject.toml)
croniter==6.0.0
# via apache-superset (pyproject.toml)
cryptography==46.0.5
cryptography==46.0.6
# via
# apache-superset (pyproject.toml)
# paramiko
@@ -120,7 +120,7 @@ flask==2.3.3
# flask-session
# flask-sqlalchemy
# flask-wtf
flask-appbuilder==5.0.2
flask-appbuilder==5.2.1
# via
# apache-superset (pyproject.toml)
# apache-superset-core
@@ -209,7 +209,7 @@ mako==1.3.10
# via
# apache-superset (pyproject.toml)
# alembic
markdown==3.8
markdown==3.8.1
# via apache-superset (pyproject.toml)
markdown-it-py==3.0.0
# via rich
@@ -279,7 +279,7 @@ parsedatetime==2.6
# via apache-superset (pyproject.toml)
pgsanity==0.2.9
# via apache-superset (pyproject.toml)
pillow==11.3.0
pillow==12.1.1
# via apache-superset (pyproject.toml)
platformdirs==4.3.8
# via requests-cache
@@ -293,7 +293,7 @@ prompt-toolkit==3.0.51
# via click-repl
pyarrow==16.1.0
# via apache-superset (pyproject.toml)
pyasn1==0.6.2
pyasn1==0.6.3
# via
# pyasn1-modules
# rsa
@@ -309,9 +309,9 @@ pydantic-core==2.33.2
# via pydantic
pygeohash==3.2.2
# via apache-superset (pyproject.toml)
pygments==2.19.1
pygments==2.20.0
# via rich
pyjwt==2.10.1
pyjwt==2.12.0
# via
# apache-superset (pyproject.toml)
# flask-appbuilder

View File

@@ -10,6 +10,8 @@
# via
# -r requirements/development.in
# apache-superset
aiofile==3.9.0
# via py-key-value-aio
alembic==1.15.2
# via
# -c requirements/base-constraint.txt
@@ -26,8 +28,10 @@ anyio==4.11.0
# via
# httpx
# mcp
# py-key-value-aio
# sse-starlette
# starlette
# watchfiles
apispec==6.6.1
# via
# -c requirements/base-constraint.txt
@@ -65,9 +69,7 @@ bcrypt==4.3.0
# -c requirements/base-constraint.txt
# paramiko
beartype==0.22.5
# via
# py-key-value-aio
# py-key-value-shared
# via py-key-value-aio
billiard==4.2.1
# via
# -c requirements/base-constraint.txt
@@ -100,6 +102,8 @@ cachetools==6.2.1
# -c requirements/base-constraint.txt
# google-auth
# py-key-value-aio
caio==0.9.25
# via aiofile
cattrs==25.1.1
# via
# -c requirements/base-constraint.txt
@@ -138,7 +142,6 @@ click==8.2.1
# click-repl
# flask
# flask-appbuilder
# typer
# uvicorn
click-didyoumean==0.3.1
# via
@@ -156,8 +159,6 @@ click-repl==0.3.0
# via
# -c requirements/base-constraint.txt
# celery
cloudpickle==3.1.2
# via pydocket
cmdstanpy==1.1.0
# via prophet
colorama==0.4.6
@@ -177,7 +178,7 @@ croniter==6.0.0
# via
# -c requirements/base-constraint.txt
# apache-superset
cryptography==46.0.5
cryptography==46.0.6
# via
# -c requirements/base-constraint.txt
# apache-superset
@@ -206,8 +207,6 @@ deprecation==2.1.0
# apache-superset
dill==0.4.0
# via pylint
diskcache==5.6.3
# via py-key-value-aio
distlib==0.3.8
# via virtualenv
dnspython==2.7.0
@@ -237,9 +236,7 @@ et-xmlfile==2.0.0
# openpyxl
exceptiongroup==1.3.0
# via fastmcp
fakeredis==2.32.1
# via pydocket
fastmcp==2.14.3
fastmcp==3.1.0
# via apache-superset
filelock==3.20.3
# via
@@ -262,7 +259,7 @@ flask==2.3.3
# flask-sqlalchemy
# flask-testing
# flask-wtf
flask-appbuilder==5.0.2
flask-appbuilder==5.2.1
# via
# -c requirements/base-constraint.txt
# apache-superset
@@ -474,6 +471,8 @@ jsonpath-ng==1.7.0
# via
# -c requirements/base-constraint.txt
# apache-superset
jsonref==1.1.0
# via fastmcp
jsonschema==4.23.0
# via
# -c requirements/base-constraint.txt
@@ -504,14 +503,12 @@ limits==5.1.0
# via
# -c requirements/base-constraint.txt
# flask-limiter
lupa==2.6
# via fakeredis
mako==1.3.10
# via
# -c requirements/base-constraint.txt
# alembic
# apache-superset
markdown==3.8
markdown==3.8.1
# via
# -c requirements/base-constraint.txt
# apache-superset
@@ -603,7 +600,7 @@ openpyxl==3.1.5
# -c requirements/base-constraint.txt
# pandas
opentelemetry-api==1.39.1
# via pydocket
# via fastmcp
ordered-set==4.1.0
# via
# -c requirements/base-constraint.txt
@@ -622,6 +619,7 @@ packaging==25.0
# deprecation
# docker
# duckdb-engine
# fastmcp
# google-cloud-bigquery
# gunicorn
# limits
@@ -653,13 +651,11 @@ parsedatetime==2.6
# apache-superset
pathable==0.4.3
# via jsonschema-path
pathvalidate==3.3.1
# via py-key-value-aio
pgsanity==0.2.9
# via
# -c requirements/base-constraint.txt
# apache-superset
pillow==11.3.0
pillow==12.1.1
# via
# -c requirements/base-constraint.txt
# apache-superset
@@ -691,8 +687,6 @@ prison==0.2.1
# flask-appbuilder
progress==1.6
# via apache-superset
prometheus-client==0.23.1
# via pydocket
prompt-toolkit==3.0.51
# via
# -c requirements/base-constraint.txt
@@ -714,19 +708,15 @@ psutil==6.1.0
# via apache-superset
psycopg2-binary==2.9.9
# via apache-superset
py-key-value-aio==0.3.0
# via
# fastmcp
# pydocket
py-key-value-shared==0.3.0
# via py-key-value-aio
py-key-value-aio==0.4.4
# via fastmcp
pyarrow==16.1.0
# via
# -c requirements/base-constraint.txt
# apache-superset
# db-dtypes
# pandas-gbq
pyasn1==0.6.2
pyasn1==0.6.3
# via
# -c requirements/base-constraint.txt
# pyasn1-modules
@@ -758,8 +748,6 @@ pydantic-settings==2.10.1
# via mcp
pydata-google-auth==1.9.0
# via pandas-gbq
pydocket==0.17.1
# via fastmcp
pydruid==0.6.9
# via apache-superset
pyfakefs==5.3.5
@@ -768,7 +756,7 @@ pygeohash==3.2.2
# via
# -c requirements/base-constraint.txt
# apache-superset
pygments==2.19.1
pygments==2.20.0
# via
# -c requirements/base-constraint.txt
# rich
@@ -776,7 +764,7 @@ pyhive==0.7.0
# via apache-superset
pyinstrument==4.4.0
# via apache-superset
pyjwt==2.10.1
pyjwt==2.12.0
# via
# -c requirements/base-constraint.txt
# apache-superset
@@ -844,8 +832,6 @@ python-dotenv==1.1.0
# apache-superset
# fastmcp
# pydantic-settings
python-json-logger==4.0.0
# via pydocket
python-ldap==3.4.4
# via apache-superset
python-multipart==0.0.20
@@ -866,15 +852,13 @@ pyyaml==6.0.2
# -c requirements/base-constraint.txt
# apache-superset
# apispec
# fastmcp
# jsonschema-path
# pre-commit
redis==5.3.1
# via
# -c requirements/base-constraint.txt
# apache-superset
# fakeredis
# py-key-value-aio
# pydocket
referencing==0.36.2
# via
# -c requirements/base-constraint.txt
@@ -910,9 +894,7 @@ rich==13.9.4
# cyclopts
# fastmcp
# flask-limiter
# pydocket
# rich-rst
# typer
rich-rst==1.3.1
# via cyclopts
rpds-py==0.25.0
@@ -944,8 +926,6 @@ setuptools==80.9.0
# pydata-google-auth
# zope-event
# zope-interface
shellingham==1.5.4
# via typer
shillelagh==1.4.3
# via
# -c requirements/base-constraint.txt
@@ -973,7 +953,6 @@ sniffio==1.3.1
sortedcontainers==2.4.0
# via
# -c requirements/base-constraint.txt
# fakeredis
# trio
sqlalchemy==1.4.54
# via
@@ -1013,10 +992,14 @@ starlette==0.49.1
# via mcp
statsd==4.0.1
# via apache-superset
syntaqlite==0.1.0
# via apache-superset
tabulate==0.9.0
# via
# -c requirements/base-constraint.txt
# apache-superset
tomli-w==1.2.0
# via apache-superset-extensions-cli
tomlkit==0.13.3
# via pylint
tqdm==4.67.1
@@ -1034,8 +1017,6 @@ trio-websocket==0.12.2
# via
# -c requirements/base-constraint.txt
# selenium
typer==0.20.0
# via pydocket
typing-extensions==4.15.0
# via
# -c requirements/base-constraint.txt
@@ -1048,16 +1029,14 @@ typing-extensions==4.15.0
# limits
# mcp
# opentelemetry-api
# py-key-value-shared
# py-key-value-aio
# pydantic
# pydantic-core
# pydocket
# pyopenssl
# referencing
# selenium
# shillelagh
# starlette
# typer
# typing-inspection
typing-inspection==0.4.1
# via
@@ -1072,6 +1051,8 @@ tzdata==2025.2
# pandas
tzlocal==5.2
# via trino
uncalled-for==0.2.0
# via fastmcp
url-normalize==2.2.1
# via
# -c requirements/base-constraint.txt
@@ -1101,6 +1082,8 @@ watchdog==6.0.0
# -c requirements/base-constraint.txt
# apache-superset
# apache-superset-extensions-cli
watchfiles==1.1.1
# via fastmcp
wcwidth==0.2.13
# via
# -c requirements/base-constraint.txt

View File

@@ -18,20 +18,20 @@
[project]
name = "apache-superset-core"
version = "0.1.0rc1"
version = "0.1.0rc2"
description = "Core Python package for building Apache Superset backend extensions and integrations"
readme = "README.md"
authors = [
{ name = "Apache Software Foundation", email = "dev@superset.apache.org" },
]
license = { file="LICENSE.txt" }
license = "Apache-2.0"
license-files = ["LICENSE.txt"]
requires-python = ">=3.10"
keywords = ["superset", "apache", "analytics", "business-intelligence", "extensions", "visualization"]
classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",

View File

@@ -37,6 +37,13 @@ Usage:
from typing import Any, Callable, TypeVar
try:
from mcp.types import ToolAnnotations
except (
ImportError
): # MCP extras may not be installed in superset-core-only environments
ToolAnnotations = dict
# Type variable for decorated functions
F = TypeVar("F", bound=Callable[..., Any])
@@ -48,11 +55,15 @@ def tool(
description: str | None = None,
tags: list[str] | None = None,
protect: bool = True,
class_permission_name: str | None = None,
method_permission_name: str | None = None,
annotations: ToolAnnotations | None = None,
) -> Any: # Use Any to avoid mypy issues with dependency injection
"""
Decorator to register an MCP tool with optional authentication.
This decorator combines FastMCP tool registration with optional authentication.
This decorator combines FastMCP tool registration with optional authentication
and RBAC permission checking.
Can be used as:
@tool
@@ -69,6 +80,13 @@ def tool(
description: Tool description (defaults to function docstring)
tags: List of tags for categorizing the tool (defaults to empty list)
protect: Whether to require Superset authentication (defaults to True)
class_permission_name: FAB view/resource name for RBAC checking
(e.g., "Chart", "Dashboard", "SQLLab"). When set, enables
permission checking via security_manager.can_access().
method_permission_name: FAB action name (e.g., "read", "write").
Defaults to "write" if tags includes "mutate", else "read".
annotations: MCP tool annotations (title, readOnlyHint, destructiveHint, etc.)
These hints help MCP clients understand tool behavior and safety.
Returns:
Decorator function that registers and wraps the tool, or the wrapped function
@@ -90,6 +108,18 @@ def tool(
def public_tool() -> str:
'''Public tool accessible without auth'''
return "Hello world"
@tool(class_permission_name="Chart") # RBAC: requires can_read on Chart
def list_charts() -> list:
'''List charts the user can access'''
return []
@tool( # RBAC: can_write on Chart
tags=["mutate"], class_permission_name="Chart",
)
def create_chart(name: str) -> dict:
'''Create a new chart'''
return {"name": name}
"""
raise NotImplementedError(
"MCP tool decorator not initialized. "
@@ -158,4 +188,5 @@ def prompt(
__all__ = [
"tool",
"prompt",
"ToolAnnotations",
]

View File

@@ -7025,9 +7025,9 @@
"dev": true
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"engines": {
"node": ">=8.6"
@@ -7121,15 +7121,6 @@
}
]
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"dependencies": {
"safe-buffer": "^5.1.0"
}
},
"node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
@@ -7306,26 +7297,6 @@
"node": ">=10"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/schema-utils": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
@@ -7355,15 +7326,6 @@
"semver": "bin/semver.js"
}
},
"node_modules/serialize-javascript": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"dependencies": {
"randombytes": "^2.1.0"
}
},
"node_modules/shallow-clone": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
@@ -7590,15 +7552,14 @@
}
},
"node_modules/terser-webpack-plugin": {
"version": "5.3.16",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz",
"integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==",
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz",
"integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.25",
"jest-worker": "^27.4.5",
"schema-utils": "^4.3.0",
"serialize-javascript": "^6.0.2",
"terser": "^5.31.1"
},
"engines": {
@@ -13159,9 +13120,9 @@
"dev": true
},
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true
},
"pify": {
@@ -13220,15 +13181,6 @@
"integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
"dev": true
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"requires": {
"safe-buffer": "^5.1.0"
}
},
"react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
@@ -13359,12 +13311,6 @@
"integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==",
"dev": true
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true
},
"schema-utils": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
@@ -13383,15 +13329,6 @@
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
},
"serialize-javascript": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
}
},
"shallow-clone": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
@@ -13563,15 +13500,14 @@
}
},
"terser-webpack-plugin": {
"version": "5.3.16",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz",
"integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==",
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz",
"integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==",
"dev": true,
"requires": {
"@jridgewell/trace-mapping": "^0.3.25",
"jest-worker": "^27.4.5",
"schema-utils": "^4.3.0",
"serialize-javascript": "^6.0.2",
"terser": "^5.31.1"
}
},

View File

@@ -17,20 +17,20 @@
[project]
name = "apache-superset-extensions-cli"
version = "0.1.0rc1"
version = "0.1.0rc2"
description = "Official command-line interface for building, bundling, and managing Apache Superset extensions"
readme = "README.md"
authors = [
{ name = "Apache Software Foundation", email = "dev@superset.apache.org" },
]
license = { file="LICENSE.txt" }
license = "Apache-2.0"
license-files = ["LICENSE.txt"]
requires-python = ">=3.10"
keywords = ["superset", "apache", "cli", "extensions", "analytics", "business-intelligence", "development-tools"]
classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Console",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
@@ -49,6 +49,7 @@ dependencies = [
"jinja2>=3.1.6",
"semver>=3.0.4",
"tomli>=2.2.1; python_version < '3.11'",
"tomli-w>=1.2.0",
"watchdog>=6.0.0",
]

View File

@@ -50,6 +50,8 @@ from superset_extensions_cli.utils import (
validate_display_name,
validate_publisher,
validate_technical_name,
write_json,
write_toml,
)
REMOTE_ENTRY_REGEX = re.compile(r"^remoteEntry\..+\.js$")
@@ -292,6 +294,7 @@ def app() -> None:
@app.command()
def validate() -> None:
"""Validate the extension structure and metadata consistency."""
validate_npm()
cwd = Path.cwd()
@@ -372,12 +375,167 @@ def validate() -> None:
click.secho(" Convention requires: frontend/src/index.tsx", fg="yellow")
sys.exit(1)
# Validate version and license consistency across extension.json, frontend, and backend
mismatches: list[str] = []
frontend_pkg_path = cwd / "frontend" / "package.json"
frontend_pkg = None
if frontend_pkg_path.is_file():
frontend_pkg = read_json(frontend_pkg_path)
if frontend_pkg:
if frontend_pkg.get("version") != extension.version:
mismatches.append(
f" frontend/package.json version: {frontend_pkg.get('version')} "
f"(expected {extension.version})"
)
if extension.license and frontend_pkg.get("license") != extension.license:
mismatches.append(
f" frontend/package.json license: {frontend_pkg.get('license')} "
f"(expected {extension.license})"
)
backend_pyproject_path = cwd / "backend" / "pyproject.toml"
if backend_pyproject_path.is_file():
backend_pyproject = read_toml(backend_pyproject_path)
if backend_pyproject:
project = backend_pyproject.get("project", {})
if project.get("version") != extension.version:
mismatches.append(
f" backend/pyproject.toml version: {project.get('version')} "
f"(expected {extension.version})"
)
if extension.license and project.get("license") != extension.license:
mismatches.append(
f" backend/pyproject.toml license: {project.get('license')} "
f"(expected {extension.license})"
)
if mismatches:
click.secho("❌ Metadata mismatch detected:", err=True, fg="red")
for mismatch in mismatches:
click.secho(mismatch, err=True, fg="red")
click.secho(
"Run `superset-extensions update` to sync from extension.json.",
fg="yellow",
)
sys.exit(1)
click.secho("✅ Validation successful", fg="green")
@app.command()
@click.option(
"--version",
"version_opt",
is_flag=False,
flag_value="__prompt__",
default=None,
help="Set a new version. Prompts for value if none given.",
)
@click.option(
"--license",
"license_opt",
is_flag=False,
flag_value="__prompt__",
default=None,
help="Set a new license. Prompts for value if none given.",
)
def update(version_opt: str | None, license_opt: str | None) -> None:
"""Update derived and generated files in the extension project."""
cwd = Path.cwd()
extension_json_path = cwd / "extension.json"
extension_data = read_json(extension_json_path)
if not extension_data:
click.secho("❌ extension.json not found.", err=True, fg="red")
sys.exit(1)
try:
extension = ExtensionConfig.model_validate(extension_data)
except Exception as e:
click.secho(f"❌ Invalid extension.json: {e}", err=True, fg="red")
sys.exit(1)
# Resolve version: prompt if flag used without value
if version_opt == "__prompt__":
version_opt = click.prompt("Version", default=extension.version)
target_version = (
version_opt
if version_opt and version_opt != extension.version
else extension.version
)
# Resolve license: prompt if flag used without value
if license_opt == "__prompt__":
license_opt = click.prompt("License", default=extension.license or "")
target_license = (
license_opt
if license_opt and license_opt != extension.license
else extension.license
)
updated: list[str] = []
# Update extension.json if version or license changed
ext_changed = False
if version_opt and version_opt != extension.version:
extension_data["version"] = target_version
ext_changed = True
if license_opt and license_opt != extension.license:
extension_data["license"] = target_license
ext_changed = True
if ext_changed:
try:
ExtensionConfig.model_validate(extension_data)
except Exception as e:
click.secho(f"❌ Invalid value: {e}", err=True, fg="red")
sys.exit(1)
write_json(extension_json_path, extension_data)
updated.append("extension.json")
# Update frontend/package.json
frontend_pkg_path = cwd / "frontend" / "package.json"
if frontend_pkg_path.is_file():
frontend_pkg = read_json(frontend_pkg_path)
if frontend_pkg:
pkg_changed = False
if frontend_pkg.get("version") != target_version:
frontend_pkg["version"] = target_version
pkg_changed = True
if target_license and frontend_pkg.get("license") != target_license:
frontend_pkg["license"] = target_license
pkg_changed = True
if pkg_changed:
write_json(frontend_pkg_path, frontend_pkg)
updated.append("frontend/package.json")
# Update backend/pyproject.toml
backend_pyproject_path = cwd / "backend" / "pyproject.toml"
if backend_pyproject_path.is_file():
backend_pyproject = read_toml(backend_pyproject_path)
if backend_pyproject:
project = backend_pyproject.setdefault("project", {})
toml_changed = False
if project.get("version") != target_version:
project["version"] = target_version
toml_changed = True
if target_license and project.get("license") != target_license:
project["license"] = target_license
toml_changed = True
if toml_changed:
write_toml(backend_pyproject_path, backend_pyproject)
updated.append("backend/pyproject.toml")
if updated:
for path in updated:
click.secho(f"✅ Updated {path}", fg="green")
else:
click.secho("✅ All files already up to date.", fg="green")
@app.command()
@click.pass_context
def build(ctx: click.Context) -> None:
"""Build extension assets."""
ctx.invoke(validate)
cwd = Path.cwd()
frontend_dir = cwd / "frontend"
@@ -413,6 +571,7 @@ def build(ctx: click.Context) -> None:
)
@click.pass_context
def bundle(ctx: click.Context, output: Path | None) -> None:
"""Package the extension into a .supx file."""
ctx.invoke(build)
cwd = Path.cwd()
@@ -426,9 +585,9 @@ def bundle(ctx: click.Context, output: Path | None) -> None:
sys.exit(1)
manifest = json.loads(manifest_path.read_text())
id_ = manifest["id"]
name = manifest["name"]
version = manifest["version"]
default_filename = f"{id_}-{version}.supx"
default_filename = f"{name}-{version}.supx"
if output is None:
zip_path = Path(default_filename)
@@ -453,6 +612,7 @@ def bundle(ctx: click.Context, output: Path | None) -> None:
@app.command()
@click.pass_context
def dev(ctx: click.Context) -> None:
"""Automatically rebuild the extension as files change."""
cwd = Path.cwd()
frontend_dir = cwd / "frontend"
backend_dir = cwd / "backend"
@@ -647,6 +807,7 @@ def init(
frontend_opt: bool | None,
backend_opt: bool | None,
) -> None:
"""Scaffold a new extension project."""
# Get extension names with graceful validation
names = prompt_for_extension_info(display_name_opt, publisher_opt, name_opt)
@@ -663,7 +824,7 @@ def init(
else click.confirm("Include backend?", default=True)
)
target_dir = Path.cwd() / names["id"]
target_dir = Path.cwd() / names["name"]
if target_dir.exists():
click.secho(f"❌ Directory {target_dir} already exists.", fg="red")
sys.exit(1)
@@ -686,7 +847,7 @@ def init(
click.secho("✅ Created extension.json", fg="green")
# Create .gitignore
gitignore = env.get_template(".gitignore.j2").render(ctx)
gitignore = env.get_template("gitignore.j2").render(ctx)
(target_dir / ".gitignore").write_text(gitignore)
click.secho("✅ Created .gitignore", fg="green")

View File

@@ -21,6 +21,8 @@ import sys
from pathlib import Path
from typing import Any
import tomli_w
from superset_core.extensions.constants import (
DISPLAY_NAME_PATTERN,
PUBLISHER_PATTERN,
@@ -109,6 +111,14 @@ def read_json(path: Path) -> dict[str, Any] | None:
return json.loads(path.read_text())
def write_json(path: Path, data: dict[str, Any]) -> None:
path.write_text(json.dumps(data, indent=2) + "\n")
def write_toml(path: Path, data: dict[str, Any]) -> None:
path.write_text(tomli_w.dumps(data))
def _normalize_for_identifiers(name: str) -> str:
"""
Normalize display name to clean lowercase words.

View File

@@ -17,10 +17,12 @@
from __future__ import annotations
import json
import os
from pathlib import Path
import pytest
import tomli_w
from click.testing import CliRunner
@@ -138,3 +140,69 @@ def extension_setup_for_bundling():
(backend_dir / "__init__.py").write_text("# init")
return _setup
@pytest.fixture
def extension_with_versions():
"""Create an extension directory structure with configurable versions and licenses."""
def _create(
base_path: Path,
ext_version: str = "1.0.0",
frontend_version: str | None = None,
backend_version: str | None = None,
ext_license: str | None = "Apache-2.0",
frontend_license: str | None = None,
backend_license: str | None = None,
) -> None:
extension_json = {
"publisher": "test-org",
"name": "test-extension",
"displayName": "Test Extension",
"version": ext_version,
"permissions": [],
}
if ext_license is not None:
extension_json["license"] = ext_license
(base_path / "extension.json").write_text(json.dumps(extension_json))
if frontend_version is not None:
frontend_dir = base_path / "frontend"
frontend_dir.mkdir(exist_ok=True)
(frontend_dir / "src").mkdir(exist_ok=True)
(frontend_dir / "src" / "index.tsx").write_text("// entry")
pkg = {
"name": "@test-org/test-extension",
"version": frontend_version,
}
if frontend_license is not None:
pkg["license"] = frontend_license
elif ext_license is not None:
pkg["license"] = ext_license
(frontend_dir / "package.json").write_text(json.dumps(pkg, indent=2))
if backend_version is not None:
backend_dir = base_path / "backend"
backend_dir.mkdir(exist_ok=True)
src_dir = backend_dir / "src" / "test_org" / "test_extension"
src_dir.mkdir(parents=True, exist_ok=True)
(src_dir / "entrypoint.py").write_text("# entry")
project = {
"name": "test-org-test-extension",
"version": backend_version,
}
if backend_license is not None:
project["license"] = backend_license
elif ext_license is not None:
project["license"] = ext_license
pyproject = {
"project": project,
"tool": {
"apache_superset_extensions": {
"build": {"include": ["src/**/*.py"]}
}
},
}
(backend_dir / "pyproject.toml").write_text(tomli_w.dumps(pyproject))
return _create

View File

@@ -121,7 +121,7 @@ def test_build_command_success_flow(
# Setup mocks
mock_rebuild_frontend.return_value = "remoteEntry.abc123.js"
mock_read_toml.return_value = {
"project": {"name": "test"},
"project": {"name": "test", "version": "1.0.0"},
"tool": {
"apache_superset_extensions": {
"build": {"include": ["src/test_org/test_extension/**/*.py"]}
@@ -162,7 +162,7 @@ def test_build_command_handles_frontend_build_failure(
# Setup mocks
mock_rebuild_frontend.return_value = None # Indicates failure
mock_read_toml.return_value = {
"project": {"name": "test"},
"project": {"name": "test", "version": "1.0.0"},
"tool": {
"apache_superset_extensions": {
"build": {"include": ["src/test_org/test_extension/**/*.py"]}

View File

@@ -43,10 +43,10 @@ def test_bundle_command_creates_zip_with_default_name(
result = cli_runner.invoke(app, ["bundle"])
assert result.exit_code == 0
assert "✅ Bundle created: test-org.test-extension-1.0.0.supx" in result.output
assert "✅ Bundle created: test-extension-1.0.0.supx" in result.output
# Verify zip file was created
zip_path = isolated_filesystem / "test-org.test-extension-1.0.0.supx"
zip_path = isolated_filesystem / "test-extension-1.0.0.supx"
assert_file_exists(zip_path)
# Verify zip contents
@@ -100,7 +100,7 @@ def test_bundle_command_with_output_directory(
assert result.exit_code == 0
# Verify zip file was created in output directory
expected_path = output_dir / "test-org.test-extension-1.0.0.supx"
expected_path = output_dir / "test-extension-1.0.0.supx"
assert_file_exists(expected_path)
assert f"✅ Bundle created: {expected_path}" in result.output
@@ -193,7 +193,7 @@ def test_bundle_includes_all_files_recursively(
assert result.exit_code == 0
# Verify zip file and contents
zip_path = isolated_filesystem / "complex-org.complex-extension-2.1.0.supx"
zip_path = isolated_filesystem / "complex-extension-2.1.0.supx"
assert_file_exists(zip_path)
with zipfile.ZipFile(zip_path, "r") as zipf:

View File

@@ -48,12 +48,12 @@ def test_init_creates_extension_with_both_frontend_and_backend(
)
# Verify directory structure
extension_path = isolated_filesystem / "test-org.test-extension"
extension_path = isolated_filesystem / "test-extension"
assert_directory_exists(extension_path, "main extension directory")
expected_structure = create_test_extension_structure(
isolated_filesystem,
"test-org.test-extension",
"test-extension",
include_frontend=True,
include_backend=True,
)
@@ -74,7 +74,7 @@ def test_init_creates_extension_with_frontend_only(
assert result.exit_code == 0, f"Command failed with output: {result.output}"
extension_path = isolated_filesystem / "test-org.test-extension"
extension_path = isolated_filesystem / "test-extension"
assert_directory_exists(extension_path)
# Should have frontend directory and package.json
@@ -97,7 +97,7 @@ def test_init_creates_extension_with_backend_only(
assert result.exit_code == 0, f"Command failed with output: {result.output}"
extension_path = isolated_filesystem / "test-org.test-extension"
extension_path = isolated_filesystem / "test-extension"
assert_directory_exists(extension_path)
# Should have backend directory and pyproject.toml
@@ -120,7 +120,7 @@ def test_init_creates_extension_with_neither_frontend_nor_backend(
assert result.exit_code == 0, f"Command failed with output: {result.output}"
extension_path = isolated_filesystem / "test-org.test-extension"
extension_path = isolated_filesystem / "test-extension"
assert_directory_exists(extension_path)
# Should only have extension.json
@@ -138,8 +138,8 @@ def test_init_accepts_valid_display_name(cli_runner, isolated_filesystem):
result = cli_runner.invoke(app, ["init"], input=cli_input)
assert result.exit_code == 0, f"Should accept display name: {result.output}"
assert Path("test-org.my-awesome-extension").exists(), (
"Directory for generated composite ID should be created"
assert Path("my-awesome-extension").exists(), (
"Directory with extension name should be created"
)
@@ -152,23 +152,21 @@ def test_init_accepts_mixed_alphanumeric_name(cli_runner, isolated_filesystem):
assert result.exit_code == 0, (
f"Mixed alphanumeric display name should be valid: {result.output}"
)
assert Path("test-org.tool-123").exists(), (
"Directory for 'test-org.tool-123' should be created"
)
assert Path("tool-123").exists(), "Directory for 'tool-123' should be created"
@pytest.mark.cli
@pytest.mark.parametrize(
"display_name,expected_id",
"display_name,expected_dir",
[
("Test Extension", "test-org.test-extension"),
("My Tool v2", "test-org.my-tool-v2"),
("Dashboard Helper", "test-org.dashboard-helper"),
("Chart Builder Pro", "test-org.chart-builder-pro"),
("Test Extension", "test-extension"),
("My Tool v2", "my-tool-v2"),
("Dashboard Helper", "dashboard-helper"),
("Chart Builder Pro", "chart-builder-pro"),
],
)
def test_init_with_various_display_names(cli_runner, display_name, expected_id):
"""Test that init accepts various display names and generates proper IDs."""
def test_init_with_various_display_names(cli_runner, display_name, expected_dir):
"""Test that init accepts various display names and creates directory named after extension."""
with cli_runner.isolated_filesystem():
cli_input = f"{display_name}\n\ntest-org\n0.1.0\nApache-2.0\ny\ny\n"
result = cli_runner.invoke(app, ["init"], input=cli_input)
@@ -176,8 +174,8 @@ def test_init_with_various_display_names(cli_runner, display_name, expected_id):
assert result.exit_code == 0, (
f"Valid display name '{display_name}' was rejected: {result.output}"
)
assert Path(expected_id).exists(), (
f"Directory for '{expected_id}' was not created"
assert Path(expected_dir).exists(), (
f"Directory '{expected_dir}' was not created"
)
@@ -187,7 +185,7 @@ def test_init_fails_when_directory_already_exists(
):
"""Test that init fails gracefully when target directory already exists."""
# Create the directory first
existing_dir = isolated_filesystem / "test-org.test-extension"
existing_dir = isolated_filesystem / "test-extension"
existing_dir.mkdir()
result = cli_runner.invoke(app, ["init"], input=cli_input_both)
@@ -204,7 +202,7 @@ def test_extension_json_content_is_correct(
result = cli_runner.invoke(app, ["init"], input=cli_input_both)
assert result.exit_code == 0
extension_path = isolated_filesystem / "test-org.test-extension"
extension_path = isolated_filesystem / "test-extension"
extension_json_path = extension_path / "extension.json"
# Verify the JSON structure and values
@@ -238,7 +236,7 @@ def test_frontend_package_json_content_is_correct(
result = cli_runner.invoke(app, ["init"], input=cli_input_both)
assert result.exit_code == 0
extension_path = isolated_filesystem / "test-org.test-extension"
extension_path = isolated_filesystem / "test-extension"
package_json_path = extension_path / "frontend" / "package.json"
# Verify the package.json structure and values
@@ -267,7 +265,7 @@ def test_backend_pyproject_toml_is_created(
result = cli_runner.invoke(app, ["init"], input=cli_input_both)
assert result.exit_code == 0
extension_path = isolated_filesystem / "test-org.test-extension"
extension_path = isolated_filesystem / "test-extension"
pyproject_path = extension_path / "backend" / "pyproject.toml"
assert_file_exists(pyproject_path, "backend pyproject.toml")
@@ -305,7 +303,7 @@ def test_gitignore_content_is_correct(cli_runner, isolated_filesystem, cli_input
result = cli_runner.invoke(app, ["init"], input=cli_input_both)
assert result.exit_code == 0
extension_path = isolated_filesystem / "test-org.test-extension"
extension_path = isolated_filesystem / "test-extension"
gitignore_path = extension_path / ".gitignore"
assert_file_exists(gitignore_path, ".gitignore")
@@ -330,7 +328,7 @@ def test_init_with_custom_version_and_license(cli_runner, isolated_filesystem):
assert result.exit_code == 0
extension_path = isolated_filesystem / "test-org.my-extension"
extension_path = isolated_filesystem / "my-extension"
extension_json_path = extension_path / "extension.json"
assert_json_content(
@@ -357,10 +355,10 @@ def test_full_init_workflow_integration(cli_runner, isolated_filesystem):
assert result.exit_code == 0
# Verify complete directory structure
extension_path = isolated_filesystem / "awesome-org.awesome-charts"
extension_path = isolated_filesystem / "awesome-charts"
expected_structure = create_test_extension_structure(
isolated_filesystem,
"awesome-org.awesome-charts",
"awesome-charts",
include_frontend=True,
include_backend=True,
)
@@ -412,7 +410,7 @@ def test_init_non_interactive_with_all_options(cli_runner, isolated_filesystem):
assert result.exit_code == 0, f"Command failed with output: {result.output}"
assert "🎉 Extension My Extension (ID: my-org.my-ext) initialized" in result.output
extension_path = isolated_filesystem / "my-org.my-ext"
extension_path = isolated_filesystem / "my-ext"
assert_directory_exists(extension_path)
assert_directory_exists(extension_path / "frontend")
assert_directory_exists(extension_path / "backend")
@@ -449,7 +447,7 @@ def test_init_frontend_only_with_cli_options(cli_runner, isolated_filesystem):
assert result.exit_code == 0, f"Command failed with output: {result.output}"
extension_path = isolated_filesystem / "frontend-org.frontend-ext"
extension_path = isolated_filesystem / "frontend-ext"
assert_directory_exists(extension_path / "frontend")
assert not (extension_path / "backend").exists()
@@ -478,7 +476,7 @@ def test_init_backend_only_with_cli_options(cli_runner, isolated_filesystem):
assert result.exit_code == 0, f"Command failed with output: {result.output}"
extension_path = isolated_filesystem / "backend-org.backend-ext"
extension_path = isolated_filesystem / "backend-ext"
assert not (extension_path / "frontend").exists()
assert_directory_exists(extension_path / "backend")
@@ -505,7 +503,7 @@ def test_init_prompts_for_missing_options(cli_runner, isolated_filesystem):
assert result.exit_code == 0, f"Command failed with output: {result.output}"
extension_path = isolated_filesystem / "default-org.default-ext"
extension_path = isolated_filesystem / "default-ext"
extension_json = load_json_file(extension_path / "extension.json")
assert extension_json["version"] == "0.1.0"
assert extension_json["license"] == "Apache-2.0"

View File

@@ -0,0 +1,172 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from __future__ import annotations
import pytest
from superset_extensions_cli.cli import app
from superset_extensions_cli.utils import read_json, read_toml
@pytest.mark.cli
def test_update_syncs_versions(
cli_runner, isolated_filesystem, extension_with_versions
):
"""Test update syncs frontend and backend versions from extension.json."""
extension_with_versions(
isolated_filesystem,
ext_version="2.0.0",
frontend_version="1.0.0",
backend_version="1.0.0",
)
result = cli_runner.invoke(app, ["update"])
assert result.exit_code == 0
assert "Updated frontend/package.json" in result.output
assert "Updated backend/pyproject.toml" in result.output
frontend_pkg = read_json(isolated_filesystem / "frontend" / "package.json")
assert frontend_pkg["version"] == "2.0.0"
backend_pyproject = read_toml(isolated_filesystem / "backend" / "pyproject.toml")
assert backend_pyproject["project"]["version"] == "2.0.0"
@pytest.mark.cli
def test_update_noop_when_all_match(
cli_runner, isolated_filesystem, extension_with_versions
):
"""Test update reports no changes when everything already matches."""
extension_with_versions(
isolated_filesystem,
ext_version="1.0.0",
frontend_version="1.0.0",
backend_version="1.0.0",
)
result = cli_runner.invoke(app, ["update"])
assert result.exit_code == 0
assert "All files already up to date" in result.output
@pytest.mark.cli
def test_update_fails_without_extension_json(cli_runner, isolated_filesystem):
"""Test update fails when extension.json is missing."""
result = cli_runner.invoke(app, ["update"])
assert result.exit_code != 0
assert "extension.json not found" in result.output
@pytest.mark.cli
def test_update_with_version_flag(
cli_runner, isolated_filesystem, extension_with_versions
):
"""Test --version updates extension.json first, then syncs all files."""
extension_with_versions(
isolated_filesystem,
ext_version="1.0.0",
frontend_version="1.0.0",
backend_version="1.0.0",
)
result = cli_runner.invoke(app, ["update", "--version", "3.0.0"])
assert result.exit_code == 0
assert "Updated extension.json" in result.output
assert "Updated frontend/package.json" in result.output
assert "Updated backend/pyproject.toml" in result.output
ext = read_json(isolated_filesystem / "extension.json")
assert ext["version"] == "3.0.0"
frontend_pkg = read_json(isolated_filesystem / "frontend" / "package.json")
assert frontend_pkg["version"] == "3.0.0"
backend_pyproject = read_toml(isolated_filesystem / "backend" / "pyproject.toml")
assert backend_pyproject["project"]["version"] == "3.0.0"
@pytest.mark.cli
def test_update_with_license_flag(
cli_runner, isolated_filesystem, extension_with_versions
):
"""Test --license updates license across all files."""
extension_with_versions(
isolated_filesystem,
ext_version="1.0.0",
frontend_version="1.0.0",
backend_version="1.0.0",
ext_license="Apache-2.0",
)
result = cli_runner.invoke(app, ["update", "--license", "MIT"])
assert result.exit_code == 0
assert "Updated extension.json" in result.output
assert "Updated frontend/package.json" in result.output
assert "Updated backend/pyproject.toml" in result.output
ext = read_json(isolated_filesystem / "extension.json")
assert ext["license"] == "MIT"
frontend_pkg = read_json(isolated_filesystem / "frontend" / "package.json")
assert frontend_pkg["license"] == "MIT"
backend_pyproject = read_toml(isolated_filesystem / "backend" / "pyproject.toml")
assert backend_pyproject["project"]["license"] == "MIT"
@pytest.mark.cli
def test_update_version_prompt_default(
cli_runner, isolated_filesystem, extension_with_versions
):
"""Test --version without value prompts with current version as default."""
extension_with_versions(
isolated_filesystem,
ext_version="1.0.0",
frontend_version="1.0.0",
backend_version="1.0.0",
)
# Hit enter to accept default — nothing should change
result = cli_runner.invoke(app, ["update", "--version"], input="\n")
assert result.exit_code == 0
assert "All files already up to date" in result.output
@pytest.mark.cli
def test_update_rejects_invalid_version(
cli_runner, isolated_filesystem, extension_with_versions
):
"""Test --version with an invalid semver string exits with error."""
extension_with_versions(
isolated_filesystem,
ext_version="1.0.0",
)
result = cli_runner.invoke(app, ["update", "--version", "not-a-version"])
assert result.exit_code != 0
assert "Invalid value" in result.output
# Verify extension.json was not modified
ext = read_json(isolated_filesystem / "extension.json")
assert ext["version"] == "1.0.0"

View File

@@ -207,3 +207,66 @@ def test_validate_npm_with_empty_version_output_raises_error(mock_run, mock_whic
# semver.compare will raise ValueError for empty version
with pytest.raises(ValueError):
validate_npm()
# Version Consistency Tests
@pytest.mark.cli
def test_validate_fails_on_version_mismatch(
cli_runner, isolated_filesystem, extension_with_versions
):
"""Test validate fails when frontend/backend versions differ from extension.json."""
extension_with_versions(
isolated_filesystem,
ext_version="2.0.0",
frontend_version="1.0.0",
backend_version="1.0.0",
)
with patch("superset_extensions_cli.cli.validate_npm"):
result = cli_runner.invoke(app, ["validate"])
assert result.exit_code != 0
assert "Metadata mismatch" in result.output
assert "superset-extensions update" in result.output
@pytest.mark.cli
def test_validate_passes_with_matching_versions(
cli_runner, isolated_filesystem, extension_with_versions
):
"""Test validate passes when all versions match extension.json."""
extension_with_versions(
isolated_filesystem,
ext_version="1.0.0",
frontend_version="1.0.0",
backend_version="1.0.0",
)
with patch("superset_extensions_cli.cli.validate_npm"):
result = cli_runner.invoke(app, ["validate"])
assert result.exit_code == 0
assert "Validation successful" in result.output
@pytest.mark.cli
def test_validate_fails_on_license_mismatch(
cli_runner, isolated_filesystem, extension_with_versions
):
"""Test validate fails when frontend/backend licenses differ from extension.json."""
extension_with_versions(
isolated_filesystem,
ext_version="1.0.0",
frontend_version="1.0.0",
backend_version="1.0.0",
ext_license="Apache-2.0",
frontend_license="MIT",
backend_license="MIT",
)
with patch("superset_extensions_cli.cli.validate_npm"):
result = cli_runner.invoke(app, ["validate"])
assert result.exit_code != 0
assert "Metadata mismatch" in result.output
assert "license" in result.output

View File

@@ -20,7 +20,7 @@ from __future__ import annotations
import json
import pytest
from superset_extensions_cli.utils import read_json, read_toml
from superset_extensions_cli.utils import read_json, read_toml, write_json, write_toml
# Read JSON Tests
@@ -269,3 +269,32 @@ def test_read_toml_with_permission_denied(isolated_filesystem):
toml_file.chmod(0o644)
except (OSError, PermissionError):
pass
# Write JSON Tests
@pytest.mark.unit
def test_write_json_round_trip(isolated_filesystem):
"""Test write_json then read_json round-trip preserves content."""
data = {"name": "test-extension", "version": "2.0.0", "nested": {"key": "value"}}
json_file = isolated_filesystem / "output.json"
write_json(json_file, data)
result = read_json(json_file)
assert result == data
# Write TOML Tests
@pytest.mark.unit
def test_write_toml_round_trip(isolated_filesystem):
"""Test write_toml then read_toml round-trip preserves content."""
data = {
"project": {"name": "test-package", "version": "1.0.0"},
"tool": {"apache_superset_extensions": {"build": {"include": ["src/**/*.py"]}}},
}
toml_file = isolated_filesystem / "output.toml"
write_toml(toml_file, data)
result = read_toml(toml_file)
assert result == data

View File

@@ -127,7 +127,6 @@ module.exports = {
},
plugins: [
'import',
'file-progress',
'lodash',
'theme-colors',
'icons',

View File

@@ -1,171 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { CHART_LIST } from 'cypress/utils/urls';
import { setGridMode, toggleBulkSelect } from 'cypress/utils';
import {
setFilter,
interceptBulkDelete,
interceptUpdate,
interceptDelete,
interceptFiltering,
interceptFavoriteStatus,
} from '../explore/utils';
function orderAlphabetical() {
setFilter('Sort', 'Alphabetical');
}
function openProperties() {
cy.get('[aria-label="more"]').eq(0).click();
cy.getBySel('chart-list-edit-option').click();
}
function openMenu() {
cy.get('[aria-label="more"]').eq(0).click();
}
function confirmDelete() {
cy.getBySel('delete-modal-input').type('DELETE');
cy.getBySel('modal-confirm-button').click();
}
function visitChartList() {
interceptFiltering();
interceptFavoriteStatus();
cy.visit(CHART_LIST);
cy.wait('@filtering');
cy.wait('@favoriteStatus');
}
describe('Charts list', () => {
describe('common actions', () => {
beforeEach(() => {
visitChartList();
});
it('should bulk delete correctly', () => {
cy.createSampleCharts([0, 1, 2, 3]);
interceptBulkDelete();
toggleBulkSelect();
// bulk deletes in card-view
setGridMode('card');
orderAlphabetical();
cy.getBySel('skeleton-card').should('not.exist');
cy.getBySel('styled-card').contains('1 - Sample chart').click();
cy.getBySel('styled-card').contains('2 - Sample chart').click();
cy.getBySel('bulk-select-action').contains('Delete').click();
confirmDelete();
cy.wait('@bulkDelete');
cy.getBySel('styled-card')
.eq(1)
.should('not.contain', '1 - Sample chart');
cy.getBySel('styled-card')
.eq(2)
.should('not.contain', '2 - Sample chart');
// bulk deletes in list-view
setGridMode('list');
cy.get('.loading').should('not.exist');
cy.getBySel('table-row').contains('3 - Sample chart').should('exist');
cy.getBySel('table-row').contains('4 - Sample chart').should('exist');
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(0).click();
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(1).click();
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
confirmDelete();
cy.wait('@bulkDelete');
cy.get('.loading').should('exist');
cy.get('.loading').should('not.exist');
cy.getBySel('table-row').eq(0).should('not.contain', '3 - Sample chart');
cy.getBySel('table-row').eq(1).should('not.contain', '4 - Sample chart');
});
it('should delete correctly in card mode', () => {
cy.createSampleCharts([0, 1]);
interceptDelete();
// deletes in card-view
setGridMode('card');
orderAlphabetical();
cy.getBySel('styled-card').contains('1 - Sample chart');
openMenu();
cy.getBySel('chart-list-delete-option').click();
confirmDelete();
cy.wait('@delete');
cy.getBySel('styled-card')
.contains('1 - Sample chart')
.should('not.exist');
});
it('should delete correctly in list mode', () => {
cy.createSampleCharts([2, 3]);
interceptDelete();
cy.getBySel('sort-header').contains('Name').click();
// Modal closes immediately without this
cy.wait(2000);
cy.getBySel('table-row').eq(0).contains('3 - Sample chart');
cy.getBySel('delete').eq(0).click();
confirmDelete();
cy.wait('@delete');
cy.get('.loading').should('exist');
cy.get('.loading').should('not.exist');
cy.getBySel('table-row').eq(0).should('not.contain', '3 - Sample chart');
});
it('should edit correctly', () => {
cy.createSampleCharts([0]);
interceptUpdate();
// edits in card-view
setGridMode('card');
orderAlphabetical();
cy.getBySel('skeleton-card').should('not.exist');
cy.getBySel('styled-card').eq(0).contains('1 - Sample chart');
// change title
openProperties();
cy.getBySel('properties-modal-name-input').type(' | EDITED');
cy.get('button:contains("Save")').click();
cy.wait('@update');
cy.getBySel('styled-card').eq(0).contains('1 - Sample chart | EDITED');
// edits in list-view
setGridMode('list');
// Wait for list view to fully render after mode change
cy.get('.loading').should('not.exist');
cy.getBySel('table-row').should('be.visible');
// Target the specific row by chart title to avoid flakiness from row ordering
cy.getBySel('table-row')
.contains('1 - Sample chart | EDITED')
.parents('[data-test="table-row"]')
.find('[data-test="edit-alt"]')
.click();
cy.getBySel('properties-modal-name-input').clear();
cy.getBySel('properties-modal-name-input').type('1 - Sample chart');
cy.get('button:contains("Save")').click();
cy.wait('@update');
cy.getBySel('table-row').contains('1 - Sample chart').should('exist');
});
});
});

View File

@@ -1,42 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { DATASET_LIST_PATH } from 'cypress/utils/urls';
describe('Dataset list', () => {
before(() => {
cy.visit(DATASET_LIST_PATH);
});
xit('should open Explore on dataset name click', () => {
cy.intercept('**/api/v1/explore/**').as('explore');
cy.get('[data-test="listview-table"] [data-test="internal-link"]')
.contains('birth_names')
.click();
cy.wait('@explore');
cy.get('[data-test="datasource-control"] .title-select').contains(
'birth_names',
);
cy.get('.metric-option-label').first().contains('COUNT(*)');
cy.get('.column-option-label').first().contains('ds');
cy.get('[data-test="fast-viz-switcher"] > div:not([role="button"]')
.contains('Table')
.should('be.visible');
});
});

View File

@@ -23,18 +23,6 @@ export function interceptFiltering() {
cy.intercept('GET', `**/api/v1/chart/?q=*`).as('filtering');
}
export function interceptBulkDelete() {
cy.intercept('DELETE', `**/api/v1/chart/?q=*`).as('bulkDelete');
}
export function interceptDelete() {
cy.intercept('DELETE', `**/api/v1/chart/*`).as('delete');
}
export function interceptFavoriteStatus() {
cy.intercept('GET', '**/api/v1/chart/favorite_status/*').as('favoriteStatus');
}
export function interceptUpdate() {
cy.intercept('PUT', `**/api/v1/chart/*`).as('update');
}
@@ -43,32 +31,13 @@ export const interceptV1ChartData = (alias = 'v1Data') => {
cy.intercept('**/api/v1/chart/data*').as(alias);
};
export function interceptExploreJson(alias = 'getJson') {
cy.intercept('POST', `**/superset/explore_json/**`).as(alias);
}
export const interceptFormDataKey = () => {
cy.intercept('POST', '**/api/v1/explore/form_data').as('formDataKey');
};
export function interceptExploreGet() {
function interceptExploreGet() {
cy.intercept({
method: 'GET',
url: /.*\/api\/v1\/explore\/\?(form_data_key|dashboard_page_id|slice_id)=.*/,
}).as('getExplore');
}
export function setFilter(filter: string, option: string) {
interceptFiltering();
cy.get(`[aria-label^="${filter}"]`).first().click();
cy.get(`.ant-select-item-option[title="${option}"]`).first().click({
force: true,
});
cy.wait('@filtering');
}
export function saveChartToDashboard(chartName: string, dashboardName: string) {
interceptDashboardGet();
interceptUpdate();

View File

@@ -1,73 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { selectResultsTab } from './sqllab.helper';
describe.skip('SqlLab datasource panel', () => {
beforeEach(() => {
cy.visit('/sqllab');
});
// TODO the test below is flaky, and has been disabled for the time being
// (notice the `it.skip`)
it('creates a table preview when a database, schema, and table are selected', () => {
cy.intercept('**/superset/table/**').as('tableMetadata');
// it should have dropdowns to select database, schema, and table
cy.get('.sql-toolbar .Select').should('have.length', 3);
cy.get('.sql-toolbar .table-schema').should('not.exist');
cy.get('[data-test="filterable-table-container"]').should('not.exist');
cy.get('.sql-toolbar .Select')
.eq(0) // database select
.within(() => {
// note: we have to set force: true because the input is invisible / cypress throws
cy.get('input').type('main{enter}', { force: true });
});
cy.get('.sql-toolbar .Select')
.eq(1) // schema select
.within(() => {
cy.get('input').type('main{enter}', { force: true });
});
cy.get('.sql-toolbar .Select')
.eq(2) // table select
.within(() => {
cy.get('input').type('birth_names{enter}', { force: true });
});
cy.wait('@tableMetadata');
cy.get('.sql-toolbar .table-schema').should('have.length', 1);
selectResultsTab().should('have.length', 1);
// add another table and check for added schema + preview
cy.get('.sql-toolbar .Select')
.eq(2)
.within(() => {
cy.get('input').type('logs{enter}', { force: true });
});
cy.wait('@tableMetadata');
cy.get('.sql-toolbar .table-schema').should('have.length', 2);
selectResultsTab().should('have.length', 2);
});
});

View File

@@ -1,192 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { nanoid } from 'nanoid';
import { selectResultsTab, assertSQLLabResultsAreEqual } from './sqllab.helper';
function parseClockStr(node: JQuery) {
return Number.parseFloat(node.text().replace(/:/g, ''));
}
describe('SqlLab query panel', () => {
beforeEach(() => {
cy.visit('/sqllab');
});
it.skip('supports entering and running a query', () => {
// row limit has to be < ~10 for us to be able to determine how many rows
// are fetched below (because React _Virtualized_ does not render all rows)
let clockTime = 0;
cy.intercept({
method: 'POST',
url: '**/api/v1/sqllab/execute/',
}).as('mockSQLResponse');
cy.get('.TableSelector .Select:eq(0)').click();
cy.get('.TableSelector .Select:eq(0) input[type=text]').focus();
cy.focused().type('{enter}');
cy.get('#brace-editor textarea').focus();
cy.focused().clear();
cy.focused().type(`{selectall}{backspace}SELECT 1`);
cy.get('#js-sql-toolbar button:eq(0)').eq(0).click();
// wait for 300 milliseconds
cy.wait(300);
// started timer
cy.get('.sql-toolbar .label-success').then(node => {
clockTime = parseClockStr(node);
// should be longer than 0.2s
expect(clockTime).greaterThan(0.2);
});
cy.wait('@mockSQLResponse');
// timer is increasing
cy.get('.sql-toolbar .label-success').then(node => {
const newClockTime = parseClockStr(node);
expect(newClockTime).greaterThan(0.9);
clockTime = newClockTime;
});
// rerun the query
cy.get('#js-sql-toolbar button:eq(0)').eq(0).click();
// should restart the timer
cy.get('.sql-toolbar .label-success').contains('00:00:00');
cy.wait('@mockSQLResponse');
cy.get('.sql-toolbar .label-success').then(node => {
expect(parseClockStr(node)).greaterThan(0.9);
});
});
it.skip('successfully saves a query', () => {
cy.intercept('**/api/v1/database/**/tables/**').as('getTables');
const query =
'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
const savedQueryTitle = `CYPRESS TEST QUERY ${nanoid()}`;
// we will assert that the results of the query we save, and the saved query are the same
let initialResultsTable: HTMLElement | null = null;
let savedQueryResultsTable = null;
cy.get('#brace-editor textarea').clear({ force: true });
cy.get('#brace-editor textarea').type(`{selectall}{backspace}${query}`, {
force: true,
});
cy.get('#brace-editor textarea').focus(); // focus => blur is required for updating the query that is to be saved
cy.focused().blur();
// ctrl + r also runs query
cy.get('#brace-editor textarea').type('{ctrl}r', { force: true });
cy.wait('@sqlLabQuery');
// Save results to check against below
selectResultsTab().then(resultsA => {
initialResultsTable = resultsA[0];
});
cy.get('#js-sql-toolbar button')
.eq(1) // save query
.click();
// Enter name + save into modal
cy.get('.modal-sm input').clear({ force: true });
cy.get('.modal-sm input').type(`{selectall}{backspace}${savedQueryTitle}`, {
force: true,
});
cy.get('.modal-sm .modal-body button')
.eq(0) // save
.click();
// first row contains most recent link, follow back to SqlLab
cy.get('table tr:first-child a[href*="savedQueryId"').click();
// will timeout without explicitly waiting here
cy.wait(['@getSavedQuery', '@getTables']);
// run the saved query
cy.get('#js-sql-toolbar button')
.eq(0) // run query
.click();
cy.wait('@sqlLabQuery');
// assert the results of the saved query match the initial results
selectResultsTab().then(resultsB => {
savedQueryResultsTable = resultsB[0];
assertSQLLabResultsAreEqual(initialResultsTable, savedQueryResultsTable);
});
});
it.skip('Create a chart from a query', () => {
cy.intercept('**/api/v1/sqllab/execute/').as('queryFinished');
cy.intercept('**/api/v1/explore/**').as('explore');
cy.intercept('**/api/v1/chart/**').as('chart');
cy.intercept('**/tabstateview/**').as('tabstateview');
// cypress doesn't handle opening a new tab, override window.open to open in the same tab
cy.window().then(win => {
cy.stub(win, 'open', url => {
// eslint-disable-next-line no-param-reassign
win.location.href = url;
});
});
cy.wait('@tabstateview');
const query = 'SELECT gender, name FROM birth_names';
cy.get('.ace_text-input').focus();
cy.focused().clear({ force: true });
cy.focused().type(`{selectall}{backspace}${query}`, { force: true });
cy.get('.sql-toolbar button').contains('Run').click();
cy.wait('@queryFinished');
cy.get(
'.SouthPane .ant-tabs-content > .ant-tabs-tabpane-active > div button:first',
{ timeout: 10000 },
).click();
cy.wait('@explore');
cy.get('[data-test="datasource-control"] .title-select').contains(query);
cy.get('.column-option-label').first().contains('gender');
cy.get('.column-option-label').last().contains('name');
cy.get(
'[data-test="all_columns"] [data-test="dnd-labels-container"] > div:first-child',
).contains('gender');
cy.get(
'[data-test="all_columns"] [data-test="dnd-labels-container"] > div:nth-child(2)',
).contains('name');
cy.wait('@chart');
cy.get('[data-test="slice-container"] table > thead th')
.first()
.contains('gender');
cy.get('[data-test="slice-container"] table > thead th')
.last()
.contains('name');
});
});

View File

@@ -1,41 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export const selectResultsTab = () =>
cy.get('.SouthPane .ReactVirtualized__Table', { timeout: 10000 });
// this function asserts that the result set for two SQL lab table results are equal
export const assertSQLLabResultsAreEqual = (resultsA, resultsB) => {
const [headerA, bodyWrapperA] = resultsA.childNodes;
const bodyA = bodyWrapperA.childNodes[0];
const [headerB, bodyWrapperB] = resultsB.childNodes;
const bodyB = bodyWrapperB.childNodes[0];
expect(headerA.childNodes.length).to.equal(headerB.childNodes.length);
expect(bodyA.childNodes.length).to.equal(bodyB.childNodes.length);
bodyA.childNodes.forEach((rowA, rowIndex) => {
const rowB = bodyB.childNodes[rowIndex];
rowA.childNodes.forEach((cellA, columnIndex) => {
const cellB = rowB.childNodes[columnIndex];
expect(cellA.innerText).to.equal(cellB.innerText);
});
});
};

View File

@@ -1,113 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
describe('SqlLab query tabs', () => {
beforeEach(() => {
cy.visit('/sqllab');
});
const tablistSelector = '[data-test="sql-editor-tabs"] > [role="tablist"]';
const tabSelector = `${tablistSelector} [role="tab"]:not([type="button"])`;
it('allows you to create and close a tab', () => {
cy.get(tabSelector).then(tabs => {
const initialTabCount = tabs.length;
const initialUntitledCount = Math.max(
0,
...tabs
.map(
(i, tabItem) =>
Number(tabItem.textContent?.match(/Untitled Query (\d+)/)?.[1]) ||
0,
)
.toArray(),
);
// add two new tabs
cy.get('[data-test="add-tab-icon"]:visible:last').click({ force: true });
cy.contains('[role="tab"]', `Untitled Query ${initialUntitledCount + 1}`);
cy.get(tabSelector).should('have.length', initialTabCount + 1);
cy.get('[data-test="add-tab-icon"]:visible:last').click({ force: true });
cy.contains('[role="tab"]', `Untitled Query ${initialUntitledCount + 2}`);
cy.get(tabSelector).should('have.length', initialTabCount + 2);
// close the tabs
cy.get(`${tabSelector}:last [data-test="dropdown-trigger"]`).click({
force: true,
});
cy.get('[data-test="close-tab-menu-option"]').click();
cy.get(tabSelector).should('have.length', initialTabCount + 1);
cy.contains('[role="tab"]', `Untitled Query ${initialUntitledCount + 1}`);
cy.get(`${tablistSelector} [aria-label="remove"]:last`).click();
cy.get(tabSelector).should('have.length', initialTabCount);
});
});
it('opens a new tab by a button and a shortcut', () => {
const editorContent = '.ace_editor .ace_content';
const editorInput = '.ace_editor textarea';
const queryLimitSelector = '#js-sql-toolbar .limitDropdown';
cy.get(tabSelector).then(tabs => {
const initialTabCount = tabs.length;
const initialUntitledCount = Math.max(
0,
...tabs
.map(
(i, tabItem) =>
Number(tabItem.textContent?.match(/Untitled Query (\d+)/)?.[1]) ||
0,
)
.toArray(),
);
// configure some editor settings
cy.get(editorInput).type('some random query string', { force: true });
cy.get(queryLimitSelector).parent().click({ force: true });
cy.get('.ant-dropdown-menu')
.last()
.find('.ant-dropdown-menu-item')
.first()
.click({ force: true });
// open a new tab by a button
cy.get('[data-test="add-tab-icon"]:visible:last').click({ force: true });
cy.contains('[role="tab"]', `Untitled Query ${initialUntitledCount + 1}`);
cy.get(tabSelector).should('have.length', initialTabCount + 1);
cy.get(editorContent).contains('SELECT ...');
cy.get(queryLimitSelector).contains('10');
// close the tab
cy.get(`${tabSelector}:last [data-test="dropdown-trigger"]`).click({
force: true,
});
cy.get(`${tablistSelector} [aria-label="remove"]:last`).click({
force: true,
});
cy.get(tabSelector).should('have.length', initialTabCount);
// open a new tab by a shortcut
cy.get('body').type('{ctrl}t');
cy.get(tabSelector).should('have.length', initialTabCount + 1);
cy.contains('[role="tab"]', `Untitled Query ${initialUntitledCount + 1}`);
cy.get(editorContent).contains('SELECT ...');
cy.get(queryLimitSelector).contains('10');
});
});
});

View File

@@ -25,28 +25,6 @@ export interface ChartSpec {
viz: string;
}
const viewTypeIcons = {
card: 'appstore',
list: 'unordered-list',
};
export function setGridMode(type: 'card' | 'list') {
const icon = viewTypeIcons[type];
cy.get(`[aria-label="${icon}"]`).click();
}
export function toggleBulkSelect() {
cy.getBySel('bulk-select').click();
}
export function clearAllInputs() {
cy.get('body').then($body => {
if ($body.find('.ant-select-clear').length) {
cy.get('.ant-select-clear').click({ multiple: true, force: true });
}
});
}
const toSlicelike = ($chart: JQuery<HTMLElement>): Slice => {
const chartId = $chart.attr('data-test-chart-id');
const vizType = $chart.attr('data-test-viz-type');

View File

@@ -25,8 +25,3 @@ export const SUPPORTED_CHARTS_DASHBOARD =
'/superset/dashboard/supported_charts_dash/';
export const TABBED_DASHBOARD = '/superset/dashboard/tabbed_dash/';
export const DATABASE_LIST = '/databaseview/list';
export const DATASET_LIST_PATH = 'tablemodelview/list';
export const ALERT_LIST = '/alert/list/';
export const REPORT_LIST = '/report/list/';
export const LOGIN = '/login/';
export const REGISTER = '/register/';

View File

@@ -3167,9 +3167,9 @@
"integrity": "sha512-Fc8Ne62jJlKHiG/ajlonC4Sd66Pq68fFwK4ihJGNZpGqboc324SQk+lRvMzpPRuJOmfrJefdG8/7JdWX4bzJ2Q=="
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
"integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -4673,9 +4673,9 @@
}
},
"node_modules/flatted": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz",
"integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==",
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
"integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
"dev": true,
"peer": true
},
@@ -5809,9 +5809,9 @@
}
},
"node_modules/lodash": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
},
"node_modules/lodash.clonedeep": {
"version": "4.5.0",
@@ -6930,9 +6930,9 @@
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"engines": {
"node": ">=8.6"
},
@@ -8642,9 +8642,9 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
"integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
"peer": true,
"engines": {
"node": ">= 6"
@@ -11132,9 +11132,9 @@
"integrity": "sha512-Fc8Ne62jJlKHiG/ajlonC4Sd66Pq68fFwK4ihJGNZpGqboc324SQk+lRvMzpPRuJOmfrJefdG8/7JdWX4bzJ2Q=="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
"integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -12253,9 +12253,9 @@
}
},
"flatted": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz",
"integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==",
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
"integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
"dev": true,
"peer": true
},
@@ -13072,9 +13072,9 @@
}
},
"lodash": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
},
"lodash.clonedeep": {
"version": "4.5.0",
@@ -13825,9 +13825,9 @@
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="
},
"pify": {
"version": "2.3.0",
@@ -15063,9 +15063,9 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
"integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
"peer": true
},
"yargs": {

View File

@@ -69,7 +69,7 @@ module.exports = {
],
coverageReporters: ['lcov', 'json-summary', 'html', 'text'],
transformIgnorePatterns: [
'node_modules/(?!d3-(array|interpolate|color|time|scale|time-format|format)|internmap|@mapbox/tiny-sdf|remark-gfm|(?!@ngrx|(?!deck.gl)|d3-scale)|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|uuid|@rjsf/*.|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|geostyler|geostyler-.*|react-error-boundary|react-json-tree|react-base16-styling|lodash-es|rbush|quickselect|react-diff-viewer-continued)',
'node_modules/(?!d3-(array|interpolate|color|time|scale|time-format|format)|internmap|@mapbox/tiny-sdf|remark-gfm|(?!@ngrx|(?!deck.gl)|d3-scale)|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|uuid|@rjsf/*.|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|geostyler|geostyler-.*|(?!geostyler)lodash|react-error-boundary|react-json-tree|react-base16-styling|lodash-es|rbush|quickselect|react-diff-viewer-continued)',
],
preset: 'ts-jest',
transform: {

Some files were not shown because too many files have changed in this diff Show More