Compare commits

..
Author SHA1 Message Date
onheap 5258b07ad6 fix(rls): handle same-named CTEs and quoted aliases in the SQL rewrite (#43005)
Co-authored-by: keyao_yang <keyao.yang@airbnb.com>
(cherry picked from commit a501fed560)
2026-08-13 08:29:06 -03:00
justinpark 948d0e5bef fix prettier 2026-08-07 12:36:05 -07:00
justinpark b008fbe426 Missing translate ref 2026-08-07 12:02:02 -07:00
JUST.in DO IT 428b106782 perf(TimeTable): skip rendering TableView while the window is resizing (#42097)
(cherry picked from commit 657e2d2267)
2026-08-07 11:13:22 -07:00
JUST.in DO IT 14b24bd76f fix(sqllab): invalid height in ResultTable (#37408)
(cherry picked from commit 866f8c51ee)
2026-08-07 11:12:57 -07:00
JUST.in DO IT 04bebf040c fix(sqllab): Invalid multi sorting state in table header (#40680)
(cherry picked from commit b955c90de4)
2026-08-07 11:11:29 -07:00
Evan Rusackas 210da7f0ae fix(mcp): generic auth errors, required token expiry, and safer auth logging (#40646)
Co-authored-by: Claude Code <noreply@anthropic.com>
(cherry picked from commit ca8855dc03)
2026-08-07 11:06:36 -07:00
Amin Ghadersohi 5b98c71f91 fix(mcp): sanitize chart config errors and accept field name aliases (#39606)
(cherry picked from commit ad20285dd6)
2026-08-07 10:53:42 -07:00
Enzo Martellucci 036edfc869 fix(mcp): surface XSS sanitization in chart/dashboard names instead of silently stripping (#39491)
(cherry picked from commit d7941ccfec)
2026-08-07 10:51:49 -07:00
Enzo Martellucci 5203ddffdd fix(mcp): surface validation errors in generate_chart instead of empty response (#39522)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit dae79a6cba)
2026-08-07 10:44:49 -07:00
Luiz OtavioandClaude Opus 5 65a4074438 fix(embedded): compare guest chart payloads against every stored control (#42864)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 11:24:42 -03:00
JUST.in DO IT 5687c29c81 fix(mcp): make streamable-http session mode configurable via MCP_STATELESS_HTTP (#42814)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
(cherry picked from commit d594a4d157)
2026-08-05 21:46:19 -07:00
justinpark a812670ec7 add sql as sensitive param 2026-08-03 17:22:17 -07:00
justinpark 309aec3dab fix(mcp): resolve real tool name and capture entity IDs through call_tool proxy and request wrapper
_resolve_tool_name() was dead code (never invoked, and _CALL_TOOL_PROXY
was undefined), so tool search proxy calls always logged tool="call_tool".
Separately, every MCP tool takes a single `request` argument, so real
arguments arrive nested as {"request": {...}} (and one layer deeper when
routed through the call_tool proxy), which the previous flat
params.get("dashboard_id") lookup could never see through. Also extend
the create-tool output backfill to cover create_virtual_dataset's
dataset_id, which generate_chart/generate_dashboard already had for
chart/dashboard ids.
2026-08-03 17:21:24 -07:00
JUST.in DO IT d4c7513898 fix(mcp): missing params in MCP tool call logs (#42660)
(cherry picked from commit ac97484b2a)
2026-08-03 15:29:18 -07:00
JUST.in DO IT 8f0e824703 fix(mcp): capture created chart/dashboard id in generate_chart/generate_dashboard audit logs (#42367)
(cherry picked from commit 181f5bc9c1)
2026-08-03 15:19:19 -07:00
Luiz Otavio 5fb2ae43af feat(cache): add DATA_CACHE_MAX_VALUE_SIZE to skip caching oversized results (#42570)
(cherry picked from commit afb863684b)
2026-07-31 09:25:02 -03:00
JUST.in DO IT e6680eae9f fix(chat): prevent main content reload when toggling chat panel (#42143) 2026-07-22 08:21:58 -03:00
PRATHAMESH HUKKERI 19a2e29f00 fix(table): prevent pagination reset on cell click (#42136)
Co-authored-by: Prathamesh Hukkeri <prathamesh04@users.noreply.github.com>
(cherry picked from commit c05ac138fb)
2026-07-20 15:47:44 -03:00
Luiz OtavioandClaude Opus 4.8 36accb034c feat(ci): install helm-docs directly instead of using whole brew setup (backport #41629) (#42113)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 15:47:40 -03:00
Luiz OtavioandClaude Opus 4.8 e0b8bbcb21 feat(explore): add CSV/XLS download to drill-to-detail modal (backport #37109) (#42051)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 15:47:36 -03:00
Joe Li a11250a49a fix(dashboard): restore top-level tab drop target for dashboards with content (#39423)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(cherry picked from commit d7fa9301cc)
2026-07-20 15:47:31 -03:00
Luiz OtavioandClaude Opus 4.8 1e1241e9e3 fix(event-log): backport stricter embedded-route regex to 6.1 (#42048)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 15:47:26 -03:00
2af7650975 fix(embedded): backport hideTab + filter-bar fix to 6.1 (#38846, #39417) (#42008)
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-20 15:47:22 -03:00
Luiz OtavioandClaude Opus 4.8 e54c93df05 fix(event-log): add event logging for embedded Superset (#41938)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 15:47:18 -03:00
Michael S. Molina a1fd226396 fix(nav): prevent full reload when clicking logo; redirect / to welcome (#41119)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 59d1b5f300)
2026-07-13 16:08:18 -03:00
Michael S. Molina 8d45e8b21b chore: Adds react/jsx-runtime as a shared dependency 2026-07-13 11:07:40 -03:00
Michael S. Molina a7dbbcb6a9 fix: playwright-tests-experimental failures 2026-07-13 10:37:56 -03:00
Luiz Otavio ec0f2e6d14 fix(cross-filter): correctly cast adhoc column types when cross filtering (#41936)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit e0b1fe4ff4)
2026-07-13 10:28:12 -03:00
Luiz Otavio 55d2e54c8e fix(jinja): drill-to-detail respects remove_filter=True in Jinja templates (#41934)
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit c898341a82)
2026-07-13 10:28:09 -03:00
Luiz Otavio 977bdd3550 chore(ci): update GHA actions to Node.js 24-compatible versions (#40477) (#41932)
(cherry picked from commit b50d423fd0)
2026-07-13 10:28:07 -03:00
Luiz Otavio 7077ced970 fix(chart): chart description not showing (#41453)
(cherry picked from commit 834ccf2613)
(cherry picked from commit 10d3a16e26)
2026-07-13 10:28:03 -03:00
Luiz Otavio fb552055fb fix(chart-explore): allow Save (Overwrite) after editing chart properties (#41602)
(cherry picked from commit 569cfc9825)
2026-07-13 10:28:01 -03:00
592d92e582 feat(extensions): add Chat contribution type (SIP-214) (#41205)
Co-authored-by: Enzo Martellucci <52219496+EnxDev@users.noreply.github.com>
Co-authored-by: Enzo Martellucci <enzomartellucci@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

(cherry picked from commit a90c8e0347)
2026-06-30 10:04:05 -03:00
SkinnyPigeon f2048886c0 feat: Allow specific mcp tools to be disabled (#39835)
(cherry picked from commit 70419e9d8f)
2026-06-12 09:51:31 -03:00
Michael S. Molina 5919bf785a fix: Flaky dataset permissions test 2026-06-11 16:51:52 -03:00
Evan Rusackas 4e45861151 fix(dashboard): address post-approval review feedback on #40528 (#40685)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 49f3dbba73)
2026-06-11 13:22:39 -03:00
Evan Rusackas 726f17b04e fix(dashboard): prevent "undefined undefined" owner names in properties modal (#40528)
Co-authored-by: Claude Code <noreply@anthropic.com>
(cherry picked from commit aba6ea536c)
2026-06-11 13:22:28 -03:00
Jean Massucatto 983de959c6 fix(sqllab): handle scientific notation in big number JSON responses (#39994)
(cherry picked from commit e6179036ec)
2026-06-10 10:58:05 -03:00
Michael S. Molina aa365c88c1 fix(extensions): load extensions async to avoid blocking initial page render 2026-06-09 16:15:19 -03:00
Michael S. Molina 24ddc75948 fix(extensions): add cache headers and strip Vary: Cookie for extension static assets (#40120)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit a06e6ea19b)
2026-05-15 10:07:11 -03:00
JUST.in DO IT d7b60ecf34 fix(sqllab): missing estimate action button (#40101)
(cherry picked from commit 2b71d964cc)
2026-05-15 09:25:10 -03:00
Michael S. Molina c83fb2bb1d chore: CHANGELOG.md for 6.1.0 RC3 2026-05-01 10:02:35 -03:00
Michael S. Molina 0260de3e92 chore: Bump core packages to 0.1.0 RC3 (#39823)
(cherry picked from commit d23b0cad92)
2026-05-01 09:56:22 -03:00
Luiz Otavio 261f0ecafd fix(drill-to-detail): drill to detail by correctly filtering by metric (#39766)
Co-authored-by: Michael S. Molina <michael.s.molina@gmail.com>
(cherry picked from commit df396aa6e9)
2026-04-30 08:44:46 -03:00
Evan Rusackas e33f676b8b docs: Superset 6.1 documentation catch-up — batch 4 (#39446)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
(cherry picked from commit 979f60a6d4)
2026-04-29 15:43:04 -03:00
Michael S. Molina 1bff24aa34 chore(build): remove thread-loader from webpack build (#39763)
(cherry picked from commit 6ce3885f2e)
2026-04-29 15:42:47 -03:00
Evan Rusackas 848809630d docs: Superset 6.1 documentation catch-up — batch 3 (#39445)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
(cherry picked from commit b4f595953e)
2026-04-29 15:41:20 -03:00
Evan Rusackas 6c53dffb09 docs: Superset 6.1 documentation catch-up — batch 2 (#39441)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 2b623fd09a)
2026-04-29 15:41:09 -03:00
Evan Rusackas 861f8d1bb8 docs(mcp): update MCP server docs for 6.1 (#39422)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit fe074c0d76)
2026-04-29 15:40:51 -03:00
JUST.in DO IT 687f168042 fix(dashboard): escape emoji in position_json before saving to prevent truncation (#39737)
Co-authored-by: Michael S. Molina <michael.s.molina@gmail.com>
(cherry picked from commit 54f1e32763)
2026-04-29 10:34:52 -03:00
Jean Massucatto 2f6254bfb4 fix(chart): use categorical axis for bar charts with numeric x-axis (#39141)
Co-authored-by: Enzo Martellucci <52219496+EnxDev@users.noreply.github.com>
(cherry picked from commit 171414f165)
2026-04-29 10:33:48 -03:00
Maxime Beauchemin 3159ec0356 fix(dashboard): apply full transitive ancestor chain for dependent filters (#39504)
(cherry picked from commit 18d89f25ce)
2026-04-28 11:06:05 -03:00
Michael S. Molina fa2e1600cd fix(theme): set color-scheme on html to fix dark mode scrollbars (#39704)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 7bee2afa8e)
2026-04-28 10:57:31 -03:00
Michael S. Molina b55bb4e3ce fix(query-history): enable sorting by Duration column (#39637)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit c4a8b34b11)
2026-04-28 09:13:15 -03:00
Sam Firke 87e5450cbe fix(table chart): fix rerender bug that continuously cleared search box (#39707)
(cherry picked from commit 3395620b6e)
2026-04-28 09:13:03 -03:00
Evan Rusackas 61bcf578a6 fix(explore): ensure unsaved-changes dialog renders above View SQL modal (#39569)
Co-authored-by: yousoph <sophieyou12@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 7c4b2b137c)
2026-04-27 15:13:05 -03:00
JUST.in DO IT 4db4ac41c4 fix(sqllab): explore to chart is disabled (#39630)
(cherry picked from commit 78950fc18e)
2026-04-27 09:57:18 -03:00
Michael S. Molina 84a8df2beb fix(sql-lab): show table expand/collapse arrow only on hover (#39627)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit d6bbe6da9b)
2026-04-27 09:57:04 -03:00
Evan Rusackas 62f568d643 docs: Superset 6.1 documentation catch-up — batch 5 (#39454)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit e1ed5003a8)
2026-04-27 09:47:33 -03:00
Maxime Beauchemin ffc242b5df fix(table): ensure dimensions appear before metrics in column order (#39346)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 4f19bc4c5f)
2026-04-27 09:43:37 -03:00
Michael S. Molina 78d2fcbf49 perf(sql-lab): debounce schema browser search (#39489)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 9fe3f634ec)
2026-04-27 09:39:47 -03:00
Michael S. Molina 68bbc68cce chore: CHANGELOG.md for 6.1.0 RC2 2026-04-17 14:41:26 -03:00
JUST.in DO IT 7a558f7ceb 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>
(cherry picked from commit be680408c9)
2026-04-17 13:11:57 -03:00
Michael S. Molina 3b7ddf88e9 Revert "fix(embedded-sdk): wire hideTab to actually hide the dashboard tab (#38846)"
This reverts commit 9619fa2156.
2026-04-17 13:11:01 -03:00
JUST.in DO IT 232a555d55 fix(sqllab): Relocate schema display on table preview (#39420)
(cherry picked from commit 4bdc8d4c68)
2026-04-17 10:27:33 -03:00
Gabriel Torres Ruiz ba6ec40fed fix(mcp): support explicit query_mode in TableChartConfig (#39412)
(cherry picked from commit 2e0d482ccf)
2026-04-17 10:27:19 -03:00
Gabriel Torres Ruiz 0648f78785 fix(mcp): replace inputSchema with parameters_hint in search_tools results by default (#39411)
(cherry picked from commit e5b3a9c25d)
2026-04-17 10:26:52 -03:00
Gabriel Torres Ruiz 129fcb5451 fix(mcp): prevent LLM from creating new dashboard instead of adding chart to existing one (#39353)
(cherry picked from commit c289731212)
2026-04-17 10:26:38 -03:00
Gabriel Torres Ruiz 6048e2f2e1 fix(parallel-coordinates): improve dark mode visibility for labels, axis text, and data lines (#39415)
(cherry picked from commit f850c6b1b1)
2026-04-17 10:26:24 -03:00
Michael S. Molina 1a537420dc chore: Bump core packages to 0.1.0 RC2 (#39406)
(cherry picked from commit e5820b6b2b)
2026-04-16 15:32:50 -03:00
Mehmet Salih Yavuz 4e9a6db9b3 feat(mcp): add a preview flow to mcp chart updates (#39383)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(cherry picked from commit 69f062b804)
2026-04-16 15:32:37 -03:00
Mehmet Salih Yavuz 02e6d671b4 fix(SelectFilter): auto clear search input (#39157)
(cherry picked from commit 7c76fd3d81)
2026-04-16 15:32:13 -03:00
Luiz Otavio 3cbc83449f fix: add comments to SQL clause validation (#39167)
(cherry picked from commit 0b419a07f5)
2026-04-16 09:22:22 -03:00
JUST.in DO IT 954902db1d fix(sqllab): format_sql to apply db dialect by database_id (#39393)
(cherry picked from commit 0b51e9cd5e)
2026-04-16 09:15:22 -03:00
Amin Ghadersohi 8b9a74a3d4 fix(mcp): always push fresh app context per tool call to prevent g.user race (#39385)
(cherry picked from commit e7b9fb277e)
2026-04-16 09:15:09 -03:00
Amin Ghadersohi 2dca313e41 fix(mcp): update instructions to use correct request wrapper and identifier params (#39392)
(cherry picked from commit 838ee870d0)
2026-04-16 09:14:51 -03:00
innovark b196e11af2 fix(EmptyState): prevent SVG cropping in empty state images (#37287)
Co-authored-by: Joe Li <joe@preset.io>
(cherry picked from commit eaccb2e471)
2026-04-16 09:11:55 -03:00
Grégoire Gailly b3c2965eaf fix(i18n): typo in fr language (#36982)
Co-authored-by: Sam Firke <sfirke@users.noreply.github.com>
(cherry picked from commit b11d4f3ef0)
2026-04-16 09:10:54 -03:00
Michael S. Molina b424683c74 fix(ListView): empty state not filling available width (#39387)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 998b9e387b)
2026-04-15 16:38:22 -03:00
Maxime Beauchemin 119f173009 fix(table): use column label instead of SQL expression for orderby in downloads (#39332)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit b3e88db87e)
2026-04-15 16:38:11 -03:00
Abdul Rehman 89231addf4 fix(css-templates): add missing height to CSS editor in CssTemplateModal (#39221)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(cherry picked from commit 8471e82342)
2026-04-15 16:37:57 -03:00
Richard Fogaca Nienkotter 04565fa232 fix(dashboard): apply dynamic groupby display controls to scoped charts (#39356)
(cherry picked from commit c3a0f2749b)
2026-04-15 16:37:45 -03:00
Maxime Beauchemin ea040d3136 fix(table): fix cross-filter not clearing on second click in Interactive Table (#39253)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit c2d96e0dce)
2026-04-15 16:37:28 -03:00
Abdul Rehman 1afa47bf80 fix(explore): dispatch onChange immediately on NumberControl stepper arrow clicks (#39220)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(cherry picked from commit 44e77fdf2b)
2026-04-15 16:37:15 -03:00
Gabriel Torres Ruiz 94dc92df02 feat(mcp): add create_virtual_dataset tool to save SQL queries as datasets (#39279)
(cherry picked from commit 18d6feb499)
2026-04-15 16:36:59 -03:00
Beto Dealmeida c85d515af3 fix: do_ping takes a connection, not engine (#39013)
(cherry picked from commit 84f7b4a973)
2026-04-15 16:36:29 -03:00
Michael S. Molina 18a8f6cb04 fix(sqllab): show schema refresh icon only on hover (#39367)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit ddcb9be9a7)
2026-04-15 16:36:05 -03:00
Alexandru Soare 9e313ba82f fix(MCP): fix MCP logs (#39159)
(cherry picked from commit ffcc6e8b63)
2026-04-15 16:35:30 -03:00
Luiz Otavio 305927df7b fix(native-filters): prevent infinite recursion in filter scope tree traversal (#39355)
(cherry picked from commit 86575e129b)
2026-04-15 09:47:41 -03:00
JUST.in DO IT bd7b53e341 fix(native-filter): infinite filter loading by deps (#39175)
(cherry picked from commit 499e27ea54)
2026-04-15 09:09:45 -03:00
Alexandru Soare 3f157d9ca1 fix(popup): Dropdown popup width doesn't match input width when tags collapse in oneLine mode (#39136)
(cherry picked from commit c2a35e2eea)
2026-04-14 08:47:11 -03:00
Alexandru Soare 15fa218529 fix(select): select all button cutoff (#39005)
(cherry picked from commit 5138aa2c11)
2026-04-14 08:45:59 -03:00
Alexandru Soare 9499ccf52c fix(explore): Prevent error toast when navigating away from Explore page (#39065)
(cherry picked from commit 66a9e2e16e)
2026-04-14 08:45:25 -03:00
Richard Fogaca Nienkotter 2b4e9909db fix(dashboard): preserve dynamic group by column order (#39333)
(cherry picked from commit 0f417f0040)
2026-04-14 08:45:13 -03:00
Alexandru Soare 2c163576a7 fix(dashboard): Ensure screenshot downloads always generate fresh images/pdfs (#38880)
(cherry picked from commit 1462ac9282)
2026-04-14 08:45:02 -03:00
Maxime Beauchemin 33531088d6 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>
(cherry picked from commit fa1f12a0b5)
2026-04-13 17:01:28 -03:00
Maxime Beauchemin c14f042185 fix(tests): fix async teardown leak in FiltersConfigModal.test.tsx (#39281)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit de40b58e10)
2026-04-13 15:54:13 -03:00
Mike Bridge af0f8176e4 fix(dashboard): hide "Filters out of scope" section when empty (#39201)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
(cherry picked from commit eea3557f61)
2026-04-13 15:53:44 -03:00
Mike Bridge 81ecb7f42b fix(dashboard): allow filter list to scroll in filter config modal sidebar (#39203)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
(cherry picked from commit 7a243d329e)
2026-04-13 15:52:49 -03:00
Maxime Beauchemin 4e16086a9b fix(tests): improve ShareMenuItems test isolation to fix intermittent suite failure (#39280)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 98146251c4)
2026-04-13 15:52:34 -03:00
Maxime Beauchemin c78a599ca6 fix(dataset-editor): fix SQL expression editor extra spaces and height expansion (#39248)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 0aa8cace1b)
2026-04-13 15:52:11 -03:00
Maxime Beauchemin 1d9dbe0697 fix(SqlLab): improve SQL diff modal — responsive width, padding, tabs, and copy button (#39246)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 450701ecec)
2026-04-13 15:51:54 -03:00
Richard Fogaca Nienkotter 0d5c7cb9b0 fix(echarts): prevent tooltip crash during dashboard auto-refresh (#39277)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(cherry picked from commit e9911fbac4)
2026-04-13 15:51:15 -03:00
Gabriel Torres Ruiz dd9724daae fix(ag-grid): jpeg export of ag-grid tables (#38781)
(cherry picked from commit 69c8eef78e)
2026-04-13 15:51:01 -03:00
Enzo Martellucci 1f7838367f fix(table): cross-filtering breaks after renaming column labels via Custom SQL (#38858)
(cherry picked from commit aba7e6dae4)
2026-04-13 15:50:41 -03:00
Mike Bridge 3fdbbb6e7e fix(dashboard): Vertical filter bar gradient is extending past the filter bar area (#39204)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
(cherry picked from commit 8bcc90c766)
2026-04-13 15:50:16 -03:00
venkateshwaran shanmugham 59d67fb786 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>
(cherry picked from commit e39dd1afce)
2026-04-13 15:50:02 -03:00
Amin Ghadersohi e2d6afa38d fix(mcp): strip json_metadata and position_json from get_dashboard_info response (#39101)
(cherry picked from commit 680cef0ee0)
2026-04-13 15:49:48 -03:00
Amin Ghadersohi 252044702a fix(mcp): wire up compact schema serialization for search_tools results (#39229)
(cherry picked from commit e17cf3c808)
2026-04-13 15:49:29 -03:00
Shaitan f35654179f fix(sql-lab): apply access check in SqlExecutionResultsCommand (#38952)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit f49310b8ff)
2026-04-13 15:49:15 -03:00
Vitor Avila 8a915c4783 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>
(cherry picked from commit c7955a38ef)
2026-04-13 15:48:33 -03:00
Amin Ghadersohi f0d7945ae9 fix(mcp): handle OAuth-authenticated databases in execute_sql (#39166)
(cherry picked from commit 68067d7f44)
2026-04-13 15:47:07 -03:00
Enzo Martellucci 32bd0caec3 fix(reports): escape SQL LIKE wildcards in find_by_extra_metadata (#38738)
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
(cherry picked from commit 6649f35a0d)
2026-04-13 15:46:51 -03:00
Mehmet Salih Yavuz 7ee70d9aba fix(AlertsReports): untie filters from alerts reports tabs flag (#38722)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(cherry picked from commit 5263abdc60)
2026-04-13 15:46:26 -03:00
Maxime Beauchemin ccfe29e83f fix(tags): fix Bulk tag modal dropdown clipping and stale tag cache (#39210)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit d915e4f3ff)
2026-04-13 15:40:32 -03:00
Maxime Beauchemin f59eaff400 fix(explore): constrain Edit Dataset modal height to prevent footer cutoff (#39211)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit bad5a35fce)
2026-04-13 15:40:18 -03:00
Amin Ghadersohi 25fb118883 fix(mcp): resolve null fields in list_datasets, list_databases, and save_sql_query (#39206)
(cherry picked from commit 1bde6f3bfd)
2026-04-13 15:39:05 -03:00
Maxime Beauchemin 09292ba228 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>
(cherry picked from commit d63308ca37)
2026-04-13 15:38:34 -03:00
Maxime Beauchemin e4ced6ad82 fix(ace-editor): style bracket matching to blend with theme (#39182)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit b8b2bdedf9)
2026-04-13 15:38:07 -03:00
Maxime Beauchemin 07c548100d 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>
(cherry picked from commit d5017e60c3)
2026-04-13 15:37:54 -03:00
Luiz Otavio 23759b9a02 fix: add template_processor so Jinja gets rendered before SQLGlot parse (#39207)
(cherry picked from commit 2e80f2a473)
2026-04-13 15:37:40 -03:00
JUST.in DO IT 6017b1a3b5 fix(sqllab): Update style for code viewer container (#39075)
(cherry picked from commit 4c2dd63464)
2026-04-13 15:37:25 -03:00
Maxime Beauchemin 6848970d0d fix(sqllab): use monospace font for SQL in database error messages (#39181)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit ed659958f3)
2026-04-13 15:37:05 -03:00
Maxime Beauchemin a8daa0d4dd fix(plugin-chart-handlebars): improve CSS sanitization tooltip and hide when not needed (#39180)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 36de05fe36)
2026-04-13 15:36:49 -03:00
Maxime Beauchemin 04ca466c77 fix(explore): add left-indentation to control panel hierarchy (#39177)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit a64609f4f3)
2026-04-13 15:36:32 -03:00
Maxime Beauchemin 374cc592ac fix(sqllab): demote "Save as new" button from primary to secondary (#39179)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 140f0001f2)
2026-04-13 15:36:16 -03:00
Elizabeth Thompson e9ca6e04d5 fix(reports): propagate PlaywrightTimeout so execution transitions to ERROR state (#39176)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 587fe4af63)
2026-04-13 15:36:02 -03:00
Michael S. Molina fcd2bac21d fix(explore): Unnecessary scroll bars appearing on charts in Explore (#39160)
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
(cherry picked from commit 3a3a6536b7)
2026-04-13 15:35:14 -03:00
Alexandru Soare c41894ac0b fix(filterReports): _generate_native_filter() crashes on null/empty filterValues (#38954)
(cherry picked from commit 4f695e1b4d)
2026-04-13 15:34:57 -03:00
Maxime Beauchemin 1e4ad1ba52 fix(explore): handle boolean false values correctly in control rendering (#39172)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 6ba9096870)
2026-04-13 15:32:57 -03:00
Amin Ghadersohi 1423387010 feat(mcp): add get_chart_type_schema tool for on-demand schema discovery (#39142)
(cherry picked from commit 5f9fc31ae2)
2026-04-13 15:32:24 -03:00
Amin Ghadersohi 685d9a0652 fix(mcp): compress chart config schemas to reduce search_tools token usage (#39018)
(cherry picked from commit bf9aff19b5)
2026-04-13 15:32:03 -03:00
Amin Ghadersohi b9b48fb1e4 fix(mcp): add description and certification fields to default list tool columns (#39017)
(cherry picked from commit 7be2acb2f3)
2026-04-13 15:31:43 -03:00
Amin Ghadersohi 4764eea1dc fix(mcp): add dynamic response truncation for oversized info tool responses (#39107)
(cherry picked from commit 83ad1eca26)
2026-04-13 15:31:26 -03:00
Amin Ghadersohi bc8690187f fix(mcp): remove JWT ValueError g.user fallback in auth layer (#39106)
(cherry picked from commit 92747246fc)
2026-04-13 15:31:09 -03:00
Amin Ghadersohi dcca02dd16 fix(mcp): fix form_data null, dataset URL, ASCII preview, and chart rename (#39109)
(cherry picked from commit 7380a59ab8)
2026-04-13 15:30:21 -03:00
Ville Brofeldt 53d427aa79 fix(security_manager): custom auth_view issue (#39098)
(cherry picked from commit e56f8cc4fb)
2026-04-13 15:29:51 -03:00
Ville Brofeldt a8ff6e463b fix(migrations): check pre-existing foreign keys on create util (#39099)
(cherry picked from commit 7c79b9ab61)
2026-04-13 15:29:27 -03:00
Maxime Beauchemin a881c20598 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>
(cherry picked from commit a62be684a0)
2026-04-13 15:29:12 -03:00
Sam Firke 096ea4ee42 fix(SQL Lab): handle columns without names (#38986)
(cherry picked from commit 12eb40db01)
2026-04-13 15:28:20 -03:00
Amin Ghadersohi 7eb702e99e fix(mcp): handle stale SSL connections, heatmap duplicate labels, and session rollback (#39015)
(cherry picked from commit b3a402d936)
2026-04-06 09:56:06 -03:00
JUST.in DO IT 9689739e1a fix(dashboard): remove opacity on filter dropdown (#39074)
(cherry picked from commit c7d175b842)
2026-04-06 09:53:10 -03:00
Amin Ghadersohi 4a10bf4ca7 fix(mcp): improve execute_sql response-too-large error to suggest limit parameter (#39003)
(cherry picked from commit 851bbeea48)
2026-04-06 09:52:59 -03:00
Kamil Gabryjelski 42fe0f755a fix(mcp): Created dashboard should be in draft state by default (#39011)
(cherry picked from commit 135e0f8099)
2026-04-06 09:52:09 -03:00
Geidō b0adfc64c7 fix(reports): log exception traceback in _get_csv_data (#39069)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 25eea295f6)
2026-04-06 09:51:55 -03:00
Rayan Salhab 4f9ec243b3 fix(ace-editor): fix cursor misalignment in markdown editor (#38928)
(cherry picked from commit ff3b8d8398)
2026-04-06 09:51:09 -03:00
Michael S. Molina bf399b9f97 fix(echarts): fix stacked horizontal bar chart clipping and duplicate x-axis labels (#39012)
(cherry picked from commit 022342839a)
2026-04-01 16:12:44 -03:00
Michael S. Molina b1eb6ac7c9 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>
(cherry picked from commit 38f0dc74f7)
2026-04-01 15:43:07 -03:00
Amin Ghadersohi 0f676a8e67 fix(mcp): handle table chart raw mode in query builders and sanitize dashboard titles (#38990)
(cherry picked from commit 0bae05d4a9)
2026-04-01 15:42:51 -03:00
Amin Ghadersohi d4832fac72 fix(mcp): fix dashboard owners Pydantic crash and preserve chart preview filters (#38987)
(cherry picked from commit 190f1a59c5)
2026-04-01 15:42:37 -03:00
Michael S. Molina 81dbfad95a fix(query): pass datasource table to template processor for schema-aware Jinja rendering (#38984)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 94d8735d4b)
2026-04-01 15:42:23 -03:00
madhushreeag 389897bb9c 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>
(cherry picked from commit 1e2d0faa55)
2026-04-01 15:41:56 -03:00
Michael S. Molina 0f4184db2f fix(mixed-timeseries): apply same axis formatting options as timeseries charts (#38979)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 8559786cc2)
2026-04-01 15:41:36 -03:00
Michael S. Molina 5d8d170093 fix(dashboard): live CSS preview in PropertiesModal (#38960)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit d4d22909cb)
2026-04-01 15:41:13 -03:00
Rui Zhao 5a348c0dae 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>
(cherry picked from commit 53b1d1097c)
2026-04-01 15:40:22 -03:00
Jessica Morris fa6801a525 fix(bubble): Fix Bubble chart axis label rotation (#38917)
(cherry picked from commit f6cd8066ab)
2026-04-01 15:39:52 -03:00
Amin Ghadersohi f8368404cf fix(mcp): batch fix for execute_sql crashes, null timestamps, and deck.gl errors (#38977)
(cherry picked from commit daefedebcd)
2026-04-01 15:39:39 -03:00
Amin Ghadersohi 27c9d806f1 fix(mcp): add TEMPORAL_RANGE filter for temporal x-axis in generate_chart (#38978)
(cherry picked from commit c37a3ec292)
2026-04-01 15:39:26 -03:00
Amin Ghadersohi 0bff78e45b feat(mcp): add Big Number chart type support to MCP service (#38403)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 4245720851)
2026-04-01 15:39:11 -03:00
Enzo Martellucci 2ca54b418f fix(echarts): adapt y-axis ticks and padding for compact timeseries charts (#38673)
(cherry picked from commit f0b20dc445)
2026-04-01 15:38:55 -03:00
Đỗ Trọng Hải 6cff944b7f fix(AlteredSliceTag): not display undefined filter value for chart change record (#38883)
Signed-off-by: hainenber <dotronghai96@gmail.com>
(cherry picked from commit 11f2140c37)
2026-04-01 15:38:01 -03:00
Michael S. Molina ec9ffc4c31 fix(pivot-table): safely cast numeric strings to numbers for date formatting (#38953)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit f1cd1ae710)
2026-03-31 09:21:23 -03:00
Enzo Martellucci ddb285b4c3 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>
(cherry picked from commit e0a0a22542)
2026-03-31 08:58:06 -03:00
Amin Ghadersohi 850c33fa6b fix(mcp): enforce MAX_PAGE_SIZE limit on list tools to prevent oversized responses (#38959)
(cherry picked from commit 2c9cf0bd55)
2026-03-31 08:56:48 -03:00
Kamil Gabryjelski c853d4df63 feat(mcp): support saved metrics from datasets in chart generation (#38955)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(cherry picked from commit 15bab227bb)
2026-03-31 08:54:38 -03:00
Amin Ghadersohi bda02a3fdc fix(mcp): prevent PendingRollbackError from poisoned sessions after SSL drops (#38934)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit d331a043a3)
2026-03-31 08:54:21 -03:00
Enzo Martellucci f1f757b5c5 fix(select): ensure filter dropdown matches input field width (#38886)
(cherry picked from commit 41d401a879)
2026-03-31 08:54:09 -03:00
Amin Ghadersohi bf8e927f2a fix(mcp): validate dataset exists in generate_explore_link before generating URL (#38951)
(cherry picked from commit 89f7e5e7ba)
2026-03-31 08:53:32 -03:00
Amin Ghadersohi 875d0c062f fix(mcp): prevent GRID_ID injection into ROOT_ID on tabbed dashboards (#38890)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit aa1a69555b)
2026-03-30 09:43:35 -03:00
Amin Ghadersohi e08c305396 fix(mcp): remove @parse_request decorator for cleaner tool schemas (#38918)
(cherry picked from commit d1903afc69)
2026-03-30 09:19:48 -03:00
JUST.in DO IT df2a0416eb fix(sqllab): invalid treeview folder expansion (#38897)
(cherry picked from commit a5d2324e21)
2026-03-30 09:18:39 -03:00
Mehmet Salih Yavuz 2aaf935db8 fix(Timeseries): dedup x axis labels (#38733)
(cherry picked from commit f832f9b0d5)
2026-03-30 09:17:28 -03:00
Kamil Gabryjelski 54cb0c1fb4 fix(explore): migrate from window.history to React Router history API (#38887)
(cherry picked from commit fc705d94e3)
2026-03-30 09:16:44 -03:00
JUST.in DO IT 807505a89a fix(sqllab): long cell content overflooding (#38855)
(cherry picked from commit 65eae027fa)
2026-03-30 09:14:25 -03:00
Krishna Chaitanya f968c5cc78 fix(dataset): add email field to owners_data for Chart Explore path (#38836)
(cherry picked from commit ac96f46c76)
2026-03-30 09:14:12 -03:00
Enzo Martellucci c512e30b17 fix(reports): PUT with empty recipients list does not persist the change (#38711)
(cherry picked from commit 40387d5daa)
2026-03-30 09:13:12 -03:00
Richard Fogaca Nienkotter 9fa0b68575 fix(dataset): add missing currency_code_column to DatasetPostSchema (#38853)
(cherry picked from commit 9c288d66b5)
2026-03-30 09:09:43 -03:00
Beto Dealmeida e2d103f9a5 fix: type probing (#38889)
(cherry picked from commit 8983edea66)
2026-03-30 09:09:11 -03:00
Amin Ghadersohi 8d47bd7f42 fix(mcp): add try/except around DAO re-fetch to handle session errors in multi-tenant (#38859)
(cherry picked from commit 6dc3d7ad9f)
2026-03-30 09:08:06 -03:00
JUST.in DO IT bd552209e7 fix(sqllab): inactive leftbar selector on empty state (#38833)
(cherry picked from commit cfa1aba1e0)
2026-03-26 14:01:07 -03:00
JUST.in DO IT 686fa44a5f fix(echart): multiple time shift line pattern (#38866)
(cherry picked from commit e045f49787)
2026-03-26 13:33:09 -03:00
Amin Ghadersohi 77df7c2add fix(mcp): add permission checks to generate_dashboard and update_chart tools (#38845)
(cherry picked from commit 23a5e95884)
2026-03-26 13:32:57 -03:00
Kamil Gabryjelski 6a866335b6 fix(mcp): detect unknown chart config fields and suggest correct ones (#38848)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
(cherry picked from commit 16f5a2a41a)
2026-03-26 13:32:47 -03:00
Đỗ Trọng Hải 26c3021b66 fix(ci): install missing msgcat used for Babel translation update (#38830)
Signed-off-by: hainenber <dotronghai96@gmail.com>
(cherry picked from commit 3506773f51)
2026-03-26 13:31:59 -03:00
Mayank Aggarwal bd8b02c1c0 fix(dashboard): larger JSON metadata editor for better editing UX (#38728) (#38745)
(cherry picked from commit 403f4ad78c)
2026-03-26 13:31:18 -03:00
Shaitan 446358749e 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>
(cherry picked from commit a93e319716)
2026-03-26 13:31:06 -03:00
Richard Fogaca Nienkotter 1e7d781354 fix(echarts): prevent plain legend clipping in dashboards (#38675)
(cherry picked from commit 12aca72074)
2026-03-26 13:30:54 -03:00
Michael S. Molina 9619fa2156 fix(embedded-sdk): wire hideTab to actually hide the dashboard tab (#38846)
(cherry picked from commit 3fb903fdc6)
2026-03-26 13:30:41 -03:00
Joe Li c4af1cbca7 fix(models): correct TabState.latest_query_id column type to match FK target (#38837)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 4b26f8c712)
2026-03-26 13:30:28 -03:00
Alexandru Soare 9a35a4f43a fix(report): raise warning when filter type not recognized (#38676)
(cherry picked from commit 37c4a36fdb)
2026-03-26 13:26:31 -03:00
Amin Ghadersohi a5d4348fb1 feat(mcp): add Handlebars chart type support to MCP service (#38402)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit c596df9294)
2026-03-26 13:25:16 -03:00
Michael S. Molina dd1f946962 fix(extensions-cli): remove publisher prefix from bundle filename (#38823)
(cherry picked from commit 6852349d24)
2026-03-26 13:25:00 -03:00
JUST.in DO IT 27206fc892 fix(sqllab): FilterText does not apply accordingly (#38813)
(cherry picked from commit 7c9d75b69e)
2026-03-26 13:24:50 -03:00
Amin Ghadersohi 861ce50473 fix(mcp): fix generate_dashboard cross-session SQLAlchemy error (#38827)
(cherry picked from commit 09594b32f9)
2026-03-26 13:24:37 -03:00
Alexandru Soare 1d170f0da1 fix(keys): Unsafe dict access in get_native_filters_params() crashes execution (#38272)
(cherry picked from commit 89d1b80ce7)
2026-03-24 11:59:29 -03:00
Shaitan a33c2a9c0e fix(sqllab): add authorization check to query cost estimation (#38648)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 962abf6904)
2026-03-24 11:26:27 -03:00
Amin Ghadersohi ac8d6b0c53 fix(mcp): prevent encoding errors and fix tool bugs on MCP client transports (#38786)
(cherry picked from commit ed3c5280a9)
2026-03-24 11:26:11 -03:00
Mehmet Salih Yavuz de42d4a986 fix(Matrixify): readd matrixify_enable guard missing (#38759)
(cherry picked from commit 7222327992)
2026-03-24 11:25:56 -03:00
Levis Mbote 11b510ecad fix(explore): display actual data type instead of "column" in column tooltip (#38554)
(cherry picked from commit e67bc5bee5)
2026-03-23 13:40:39 -03:00
Mehmet Salih Yavuz a16f0c81b5 fix(MainNav): display all menu items on smaller screens (#38732)
(cherry picked from commit fdcb942f3c)
2026-03-23 13:39:24 -03:00
Mehmet Salih Yavuz 155f55dbe1 fix(AlertsReports): validate anchor_list is a list (#38723)
(cherry picked from commit 100ad7d9ee)
2026-03-23 13:38:49 -03:00
Mehmet Salih Yavuz deeedef0dc feat(matrixify): Revamp control panel (#38519) 2026-03-23 13:37:06 -03:00
Mehmet Salih Yavuz 967e78a716 fix(DropdownContainer): add fresh to avoid stale data (#38702)
(cherry picked from commit cc34d19d24)
2026-03-23 10:16:46 -03:00
João Pedro Alves Barbosa a541d69019 fix(table): improve conditional formatting text contrast (#38705)
(cherry picked from commit 02ffb52f4a)
2026-03-23 09:53:59 -03:00
Đỗ Trọng Hải 493f6c0aed 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>
(cherry picked from commit 83823911b5)
2026-03-23 09:53:34 -03:00
Đỗ Trọng Hải c26d2de616 fix(sec): remove compromised Trivy actions (#38780)
Signed-off-by: hainenber <dotronghai96@gmail.com>
(cherry picked from commit 7004369c68)
2026-03-23 09:45:45 -03:00
Amin Ghadersohi 6d1a1b1863 fix(mcp): convert adhoc filters to QueryObject format before query compilation (#38774)
(cherry picked from commit 44c2c765ae)
2026-03-23 09:43:36 -03:00
Amin Ghadersohi 68cc13cfbf fix(mcp): normalize call_tool proxy arguments to prevent encoding TypeError (#38775)
(cherry picked from commit 0d5721910e)
2026-03-23 09:43:22 -03:00
Amin GhadersohiandClaude Opus 4.6 935226c736 feat(mcp): add horizontal bar chart orientation support to generate_chart (#38390)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 16:40:56 -03:00
Kamil GabryjelskiandClaude Opus 4.6 9239db5a32 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 16:34:03 -03:00
Enzo Martellucci cf493a928a fix(reports): validate nativeFilters on report create/update and deactivate on dashboard filter deletion (#38715) 2026-03-20 16:34:03 -03:00
Kamil GabryjelskiandClaude Opus 4.6 67b2bf0646 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 16:34:03 -03:00
Amin Ghadersohi af54788b5e fix(mcp): fix dashboard slug null and execute_sql encoding error (#38710) 2026-03-20 16:34:03 -03:00
Alexandru Soare 0915e675df fix(button): Theming configurations for button elements is not consistent (#38604) 2026-03-20 16:34:03 -03:00
Levis Mbote 884f8f7a35 fix(timeseries-table): enable proper column sorting in timeseries-table chart (#38579) 2026-03-20 16:34:03 -03:00
Levis Mbote da5f968a8e fix(theme): persist local theme id so "Local" tag remains after navigation (#38527) 2026-03-20 16:34:03 -03:00
Levis Mbote e9150afba6 fix(dashboard): correct tab underline width for newly added dashboard tabs. (#38524) 2026-03-20 16:34:03 -03:00
Levis Mbote 519e7c58de fix(theme): ensure colorLink follows colorPrimary when not explicitly set (#38517) 2026-03-20 16:34:03 -03:00
Alexandru Soare 1f94c88025 fix(firebolt): Firebolt SQL entered with EXCLUDE is rewritten to EXCEPT (#38742) 2026-03-20 16:34:03 -03:00
Kamil GabryjelskiandClaude Opus 4.6 d7633752bd 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-20 16:34:03 -03:00
Kamil Gabryjelski c2b3d36435 fix: Add aliases and groupby list to chart schemas (#38740) 2026-03-20 16:33:58 -03:00
Luiz Otavio c68dee2caf fix(sql): remove WHERE 1 = 1 when temporal filter has "No filter" selected (#38704) 2026-03-20 16:33:58 -03:00
Joe LiandClaude Opus 4.6 30690aaf7b 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-20 16:33:58 -03:00
Michael S. Molina 25915f016b fix(chart): prevent chart list from failing when a datasource lacks explore_url (#38721) 2026-03-20 16:33:58 -03:00
Kamil Gabryjelski b9259db772 fix: Row limit support for chart mcp tools (#38717) 2026-03-20 16:33:58 -03:00
Amin GhadersohiandClaude Opus 4.6 9277f85d65 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-20 16:33:53 -03:00
f7e4fe9d0f 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-20 16:33:53 -03:00
João Pedro Alves BarbosaandClaude Opus 4.6 2e09934bb5 fix(map-box): prevent clusters from being smaller than individual points (#38458)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 16:33:53 -03:00
Michael S. Molina 435e405263 fix: Simplify extension folder name (#38690) 2026-03-20 16:33:53 -03:00
54b313c659 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-20 16:33:53 -03:00
Beto Dealmeida e2495119a3 feat: apply RLS conservatively (#38683) 2026-03-20 16:33:53 -03:00
Amin Ghadersohi 87a63a81e2 feat(mcp): Add tool annotations for MCP directory compliance (#38641) 2026-03-20 16:33:53 -03:00
Amin GhadersohiandClaude Opus 4.6 b95e556840 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-20 16:33:47 -03:00
Amin GhadersohiandClaude Opus 4.6 134e77b7c2 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-20 16:33:47 -03:00
Amin GhadersohiandClaude Opus 4.6 5adf07aef3 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-20 16:33:43 -03:00
Amin Ghadersohi 9b6c4486c0 refactor(mcp): use serialize_user_object in get_instance_info (#38613) 2026-03-20 16:33:43 -03:00
Amin Ghadersohi 4ce0627c73 fix(mcp): extract role names as strings in UserInfo serialization (#38612) 2026-03-20 16:33:43 -03:00
Amin Ghadersohi 530ad25c90 docs: move MCP deployment guide to admin docs, add user-facing AI guide (#38585) 2026-03-20 16:33:43 -03:00
Amin GhadersohiandClaude Opus 4.6 f11a4834d2 feat(mcp): implement RBAC permission checking for MCP tools (#38407)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 16:33:43 -03:00
Amin GhadersohiandClaude Opus 4.6 50ff9fdb3e feat(mcp): auto-generate dashboard title from chart names when omitted (#38410)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 16:33:37 -03:00
Đỗ Trọng Hải a83ff0057c fix(ci): allow docs testing to run despite absence of db diagnostics data (#38655)
Signed-off-by: hainenber <dotronghai96@gmail.com>
(cherry picked from commit ca403dc45d)
2026-03-17 11:58:50 -03:00
João Pedro Alves Barbosa cffca7367c 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>
(cherry picked from commit 96705c156a)
2026-03-17 11:57:36 -03:00
Joe Li e855fbf71d fix(embedded): default to light theme instead of system preference (#38644)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit aa5adb0fce)
2026-03-17 11:56:19 -03:00
Đỗ Trọng Hải 1726169c1a fix(FilterBar): reduce padded space between filter header and first filter (#38646)
Signed-off-by: hainenber <dotronghai96@gmail.com>
(cherry picked from commit afe093f1ca)
2026-03-17 11:55:46 -03:00
Mayank Aggarwal 8b20d95366 fix(docs): use absolute API doc links in developer docs (#38649)
(cherry picked from commit cc066b3576)
2026-03-17 11:55:32 -03:00
amaannawab923 41371e4816 fix(ag-grid-table): fix failing buildQuery test expectation (#38636)
(cherry picked from commit 6e7d6a85b4)
2026-03-17 11:53:16 -03:00
Luiz Otavio 185c0eb3bf style(metadata-bar): use bold font weight for metadata bar title (#38608)
(cherry picked from commit e8061a9c2b)
2026-03-17 11:53:02 -03:00
Amin Ghadersohi 4a153a0ec3 fix(mcp): return all statement results for multi-statement SQL queries (#38388)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit b6c3b3ef46)
2026-03-17 11:52:09 -03:00
Rafael Benitez aaaead02f1 fix(world-map): add fallback fill color when colorFn returns null (#38602)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit ba7271b4d8)
2026-03-17 11:51:23 -03:00
amaannawab923 4baedcc794 fix(ag-grid-table): fix AND filter conditions not applied (#38369)
(cherry picked from commit ca2d26a1e2)
2026-03-17 11:51:10 -03:00
Alexandru Soare 825b284492 fix(timeshiftcolor): Time shift color to match the original color (#38473)
(cherry picked from commit f6106cd26f)
2026-03-17 11:50:54 -03:00
Michael S. Molina 33b0b6b3bb fix(editor): implement missing methods, fix cursor position clearing (#38603)
(cherry picked from commit 1867336907)
2026-03-17 11:50:14 -03:00
Ville Brofeldt e42f6c3a1c fix(extensions): fix gitignore template and bump version (#38614)
(cherry picked from commit f5383263bc)
2026-03-17 11:49:57 -03:00
Amin Ghadersohi b3eaa5ad01 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>
(cherry picked from commit d5cf77cd60)
2026-03-17 11:49:40 -03:00
Kamil Gabryjelski e41653faff fix(mcp): Support form_data_key without chart identifier for unsaved charts (#38628)
(cherry picked from commit af5e05db2e)
2026-03-17 11:48:15 -03:00
Enzo Martellucci 39bdccd7ee fix(deckgl): polygon chart not rendering when boundary column contains nested geometry JSON (#38595)
(cherry picked from commit 32a64d02c7)
2026-03-17 11:45:42 -03:00
Enzo Martellucci ba2cfac373 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>
(cherry picked from commit 9516d1a306)
2026-03-17 11:45:20 -03:00
Kamil Gabryjelski d170decfc5 fix(mcp): Improve validation errors and field aliases to reduce failed LLM tool calls (#38625)
(cherry picked from commit d91b96814e)
2026-03-17 11:44:42 -03:00
Amin Ghadersohi b791979c37 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>
(cherry picked from commit fc156d0014)
2026-03-17 11:43:52 -03:00
Mehmet Salih Yavuz 3ad8d484d7 fix: add parent_slice_id for multilayer charts to embed (#38243)
(cherry picked from commit 95f61bd223)
2026-03-17 11:41:47 -03:00
Mehmet Salih Yavuz 343e7f33af fix: add embedded box sizing rule for layout (#38351)
Co-authored-by: Joe Li <joe@preset.io>
(cherry picked from commit 7f476a79b3)
2026-03-17 11:41:12 -03:00
Yuriy Krasilnikov 3521504b05 fix(embedded): prevent double RLS application in virtual datasets (#37395)
(cherry picked from commit 09e9c6a522)
2026-03-17 11:40:36 -03:00
Ville Brofeldt f63c0d4caa fix: support nested function calls in cache_key_wrapper (#38569)
(cherry picked from commit a9def2fc15)
2026-03-17 11:40:05 -03:00
Alexandru Soare cfcaaa9db4 fix(matrixify): Matrixify to not override slice id (#38515)
Co-authored-by: Evan Rusackas <evan@preset.io>
(cherry picked from commit 27197faba9)
2026-03-17 11:39:41 -03:00
amaannawab923 224e9ea411 fix(ag-grid): persist AG Grid column filters in explore permalinks (#38393)
(cherry picked from commit 9215eb5e45)
2026-03-17 11:38:59 -03:00
Amin Ghadersohi ec8177fe15 fix(charts): set reasonable default y-axis title margin to prevent label overlap (#38389)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit fe7f220c21)
2026-03-17 11:37:41 -03:00
Amin Ghadersohi 88195cdb54 fix(mcp): honor target_tab parameter when adding charts to tabbed dashboards (#38409)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 3bb9704cd5)
2026-03-17 11:36:22 -03:00
Amin Ghadersohi a3dba466cb fix(mcp): wrap LoggingMiddleware.on_message event_logger in try/except (#38560)
(cherry picked from commit 6d7cfac8b2)
2026-03-17 11:35:39 -03:00
Đỗ Trọng Hải 1354dc6881 fix(i18n): correct variable name for translated SQL Lab query message (#38494)
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
(cherry picked from commit 31754a39c9)
2026-03-17 11:35:00 -03:00
Michael S. Molina 249c21655f chore: CHANGELOG.md and UPDATING.md for 6.1.0 RC1 2026-03-11 10:32:14 -03:00
Michael S. Molina 224a922341 fix: SQL Lab tab content padding (#38561)
(cherry picked from commit bde48e563e)
2026-03-10 11:45:24 -03:00
Amin Ghadersohi a9b24da0a2 fix(mcp): improve default chart names with descriptive format (#38406)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 0cfd760a36)
2026-03-10 08:25:44 -03:00
Amin Ghadersohi ab64ad7ac7 fix(mcp): add missing __init__.py for chart, dashboard, dataset packages (#38400)
(cherry picked from commit 5c2cbb58bc)
2026-03-10 08:24:46 -03:00
Amin Ghadersohi d266146bbb fix(mcp): add guardrails to prevent LLM artifact generation (#38391)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 5fa70bdbd8)
2026-03-10 08:24:00 -03:00
Amin Ghadersohi 10415fe8be fix(mcp): add missing command.validate() to MCP chart data tools (#38521)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 2a876e8b86)
2026-03-10 08:23:47 -03:00
Amin Ghadersohi d42caf744f feat(mcp): register GlobalErrorHandlerMiddleware and LoggingMiddleware (#38523)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 0533ca9941)
2026-03-10 08:23:38 -03:00
Enzo Martellucci d8e346d52d fix(embedded): add CurrentUserRestApi read permission to Public role defaults (#38474)
(cherry picked from commit a17f38a4e2)
2026-03-10 08:22:45 -03:00
Amin Ghadersohi 8d7a36df5a fix(mcp): resolve chatbot tool call flakiness with URL and instruction fixes (#38532)
(cherry picked from commit 6ef4794778)
2026-03-10 08:22:27 -03:00
Amin Ghadersohi 77c7f9b5e8 fix(mcp): make fastmcp truly optional during Superset startup (#38534)
(cherry picked from commit 4cd3ce164d)
2026-03-10 08:22:09 -03:00
Evan Rusackas 6ebaf5919f fix(docs): swizzle MethodEndpoint to fix SSG crash on all API pages (#38533)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 8e3e57c1c8)
2026-03-10 08:21:54 -03:00
6814 changed files with 226093 additions and 972995 deletions
+11 -7
View File
@@ -24,9 +24,7 @@ notifications:
discussions: notifications@superset.apache.org
github:
pull_requests:
del_branch_on_merge: true
allow_update_branch: true
del_branch_on_merge: true
description: "Apache Superset is a Data Visualization and Data Exploration Platform"
homepage: https://superset.apache.org/
labels:
@@ -77,17 +75,23 @@ github:
# combination here.
contexts:
- lint-check
- cypress-matrix-required
- cypress-matrix (0, chrome)
- cypress-matrix (1, chrome)
- cypress-matrix (2, chrome)
- cypress-matrix (3, chrome)
- cypress-matrix (4, chrome)
- cypress-matrix (5, chrome)
- dependency-review
- frontend-build
- playwright-tests-required
- playwright-tests (chromium)
- pre-commit (current)
- pre-commit (previous)
- test-mysql
- test-postgres-required
- test-postgres (current)
- test-postgres-hive
- test-postgres-presto
- test-sqlite
- unit-tests-required
- unit-tests (current)
required_pull_request_reviews:
dismiss_stale_reviews: false
+2 -2
View File
@@ -105,9 +105,9 @@ Charts built from enriched datasets containing:
pre-commit install
# Quick validation (faster than --all-files)
pre-commit run # Staged files only
pre-commit run # Staged files only
pre-commit run mypy # Python type checking
pre-commit run format # Code formatting
pre-commit run prettier # Code formatting
pre-commit run eslint # Frontend linting
```
+1
View File
@@ -32,6 +32,7 @@
"ms-python.vscode-pylance",
"charliermarsh.ruff",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
}
+1
View File
@@ -59,6 +59,7 @@
"ms-python.vscode-pylance",
"charliermarsh.ruff",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
}
+8 -17
View File
@@ -1,6 +1,8 @@
# Notify all committers of DB migration changes, per SIP-59
/superset/migrations/ @mistercrunch @michael-s-molina @betodealmeida @eschutho @sadpandajoe @rusackas
# https://github.com/apache/superset/issues/13351
/superset/migrations/ @mistercrunch @michael-s-molina @betodealmeida @eschutho @sadpandajoe
# Notify some committers of changes in the components
@@ -10,35 +12,24 @@
# Notify Helm Chart maintainers about changes in it
/helm/superset/ @dpgaspar @villebro @nytai @michael-s-molina @mistercrunch @rusackas @Antonio-RiveroMartnez @hainenber
/helm/superset/ @craig-rueda @dpgaspar @villebro @nytai @michael-s-molina @mistercrunch @rusackas @Antonio-RiveroMartnez
# Notify E2E test maintainers of changes
/superset-frontend/playwright/ @sadpandajoe @geido @eschutho @rusackas @mistercrunch
/superset-frontend/cypress-base/ @sadpandajoe @geido @eschutho @rusackas @mistercrunch
/superset-frontend/cypress-base/ @sadpandajoe @geido @eschutho @rusackas @betodealmeida @mistercrunch
# Notify PMC members of changes to GitHub Actions
/.github/ @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @kgabryje @sha174n @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 @kgabryje @dpgaspar @sha174n @sadpandajoe @hainenber
/.github/ @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 @kgabryje @dpgaspar @sha174n @Antonio-RiveroMartnez
/.asf.yaml @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar @Antonio-RiveroMartnez
# Maps are a finicky contribution process we care about
**/*.geojson @villebro @rusackas
**/*.ipynb @villebro @rusackas
/superset-frontend/plugins/plugin-chart-country-map/ @villebro @rusackas
# Notify translation maintainers of changes to translations
/superset/translations/ @sfirke @rusackas @villebro @sadpandajoe @hainenber
/superset-frontend/plugins/legacy-plugin-chart-country-map/ @villebro @rusackas
# Notify PMC members of changes to extension-related files
+3 -2
View File
@@ -41,8 +41,8 @@ body:
label: Superset version
options:
- master / latest-dev
- "6.1.0"
- "6.0.0"
- "5.0.0"
validations:
required: true
- type: dropdown
@@ -50,8 +50,9 @@ body:
attributes:
label: Python version
options:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- Not applicable
- I don't know
validations:
+38
View File
@@ -0,0 +1,38 @@
# Security Policy
This is a project of the [Apache Software Foundation](https://apache.org) and follows the
ASF [vulnerability handling process](https://apache.org/security/#vulnerability-handling).
## Reporting Vulnerabilities
**⚠️ Please do not file GitHub issues for security vulnerabilities as they are public! ⚠️**
Apache Software Foundation takes a rigorous standpoint in annihilating the security issues
in its software projects. Apache Superset is highly sensitive and forthcoming to issues
pertaining to its features and functionality.
If you have any concern or believe you have found a vulnerability in Apache Superset,
please get in touch with the Apache Superset Security Team privately at
e-mail address [security@superset.apache.org](mailto:security@superset.apache.org).
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
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
reported to the maintainers of those projects. Results from security scans of Apache
Superset dependencies found on its official Docker image can be remediated at release time
by extending the image itself.
**Your responsible disclosure and collaboration are invaluable.**
## Extra Information
- [Apache Superset documentation](https://superset.apache.org/docs/security)
- [Common Vulnerabilities and Exposures by release](https://superset.apache.org/docs/security/cves)
- [How Security Vulnerabilities are Reported & Handled in Apache Superset (Blog)](https://preset.io/blog/how-security-vulnerabilities-are-reported-and-handled-in-apache-superset/)
+13 -20
View File
@@ -24,39 +24,32 @@ runs:
- name: Interpret Python Version
id: set-python-version
shell: bash
env:
INPUT_PYTHON_VERSION: ${{ inputs.python-version }}
run: |
if [ "$INPUT_PYTHON_VERSION" = "current" ]; then
RESOLVED_VERSION="3.11"
elif [ "$INPUT_PYTHON_VERSION" = "next" ]; then
if [ "${{ inputs.python-version }}" = "current" ]; then
echo "PYTHON_VERSION=3.11" >> $GITHUB_ENV
elif [ "${{ inputs.python-version }}" = "next" ]; then
# currently disabled in GHA matrixes because of library compatibility issues
RESOLVED_VERSION="3.12"
elif printf '%s' "$INPUT_PYTHON_VERSION" | grep -Eq '^[0-9]+\.[0-9]+(\.[0-9]+)?$'; then
RESOLVED_VERSION="$INPUT_PYTHON_VERSION"
echo "PYTHON_VERSION=3.12" >> $GITHUB_ENV
elif [ "${{ inputs.python-version }}" = "previous" ]; then
echo "PYTHON_VERSION=3.10" >> $GITHUB_ENV
else
echo "Invalid python-version: '$INPUT_PYTHON_VERSION'" >&2
exit 1
echo "PYTHON_VERSION=${{ inputs.python-version }}" >> $GITHUB_ENV
fi
echo "python-version=$RESOLVED_VERSION" >> "$GITHUB_OUTPUT"
- name: Set up Python ${{ steps.set-python-version.outputs.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v5
with:
python-version: ${{ steps.set-python-version.outputs.python-version }}
python-version: ${{ env.PYTHON_VERSION }}
cache: ${{ inputs.cache }}
- name: Install dependencies
env:
INPUT_INSTALL_SUPERSET: ${{ inputs.install-superset }}
INPUT_REQUIREMENTS_TYPE: ${{ inputs.requirements-type }}
run: |
if [ "$INPUT_INSTALL_SUPERSET" = "true" ]; then
if [ "${{ inputs.install-superset }}" = "true" ]; then
sudo apt-get update && sudo apt-get -y install libldap2-dev libsasl2-dev
pip install --upgrade pip setuptools wheel uv
if [ "$INPUT_REQUIREMENTS_TYPE" = "dev" ]; then
if [ "${{ inputs.requirements-type }}" = "dev" ]; then
uv pip install --system -r requirements/development.txt
elif [ "$INPUT_REQUIREMENTS_TYPE" = "base" ]; then
elif [ "${{ inputs.requirements-type }}" = "base" ]; then
uv pip install --system -r requirements/base.txt
fi
-9
View File
@@ -27,15 +27,6 @@ runs:
- name: Set up QEMU
if: ${{ inputs.build == 'true' }}
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
with:
# Pin the binfmt image to a specific QEMU release. The default
# (`tonistiigi/binfmt:latest`) is a moving target, and drift across
# QEMU's x86_64→aarch64 translator has been the proximate cause of
# intermittent `exit code: 132` (SIGILL) failures during the arm64
# leg of the multi-platform docker build — newer Node native modules
# emit instructions QEMU's user-mode emulation occasionally drops on
# the floor. Pinning a known-good release stabilises that path.
image: tonistiigi/binfmt:qemu-v8.1.5
- name: Set up Docker Buildx
if: ${{ inputs.build == 'true' }}
@@ -17,14 +17,12 @@ runs:
- name: Install supersetbot from npm
if: ${{ inputs.from-npm == 'true' }}
shell: bash
# zizmor: ignore[adhoc-packages] - supersetbot is a first-party Apache CLI (apache-superset/supersetbot) installed globally as a tool; a global CLI install has no application manifest/lockfile context
run: npm install -g supersetbot
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
if: ${{ inputs.from-npm == 'false' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
repository: apache-superset/supersetbot
path: supersetbot
@@ -32,7 +30,6 @@ runs:
if: ${{ inputs.from-npm == 'false' }}
shell: bash
working-directory: supersetbot
# zizmor: ignore[adhoc-packages] - installs the locally packed supersetbot tarball built from the trusted apache-superset/supersetbot checkout; no lockfile applies to a global CLI install
run: |
# simple trick to install globally with dependencies
npm pack
+288 -88
View File
@@ -1,24 +1,26 @@
version: 2
enable-beta-ecosystems: true
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
cooldown:
default-days: 7
- package-ecosystem: "npm"
ignore:
# TODO: remove below entries once the application supports React >= 19.0.0
- dependency-name: "react"
update-types: ["version-update:semver-major"]
- dependency-name: "react-dom"
update-types: ["version-update:semver-major"]
- dependency-name: "@types/react"
update-types: ["version-update:semver-major"]
- dependency-name: "@types/react-dom"
update-types: ["version-update:semver-major"]
# TODO: remove below entries until React >= 18.0.0
- dependency-name: "storybook"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
- dependency-name: "@storybook*"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
- dependency-name: "eslint-plugin-storybook"
- dependency-name: "react-error-boundary"
- dependency-name: "@rjsf/*"
# remark-gfm v4+ requires react-markdown v9+, which needs React 18
- dependency-name: "remark-gfm"
- dependency-name: "react-markdown"
# TODO: remove below entries until React >= 19.0.0
- dependency-name: "react-icons"
# JSDOM v30 doesn't play well with Jest v30
# Source: https://jestjs.io/blog#known-issues
@@ -28,78 +30,37 @@ updates:
# See https://github.com/apache/superset/pull/37384#issuecomment-3793991389
# TODO: remove the plugin once Lodash usage has been migrated to a more readily tree-shakeable alternative
- dependency-name: "@swc/plugin-transform-imports"
# deck.gl and luma.gl share strict peer constraints across the root and
# plugin workspaces, and root overrides pin their transitive versions.
# Upgrade both families together in a manually validated change.
- dependency-name: "@deck.gl/*"
- dependency-name: "@luma.gl/*"
# `just-handlerbars-helpers` library in plugin-chart-handlebars requires `currencyformatter`` to be < 2
- dependency-name: "currencyformatter.js"
update-types: ["version-update:semver-major"]
# TODO: remove below clause once https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/940 lands onto a future release
# and confirm the issue https://github.com/apache/superset/issues/39600 is fixed
- dependency-name: "react-checkbox-tree"
update-types: ["version-update:semver-major"]
# Babel 8 (7.x -> 8.x) is blocked on the surrounding ecosystem: @emotion/babel-plugin
# (NodePath#hoist), babel-plugin-jsx-remove-data-test-id (t.jSXOpeningElement), and
# ts-jest all rely on Babel APIs removed in v8 and have not shipped Babel 8 support.
# Ignore the coordinated major bump until the ecosystem catches up; it must be done
# as a single manual upgrade anyway. TODO: remove when Babel 8 support is viable.
- dependency-name: "@babel/*"
update-types: ["version-update:semver-major"]
# v2.0.0 renamed ZSTDDecompress to decompress and made it async, breaking
# the webpack dev proxy (see #38662, #39138, #39139). Dependabot reopened
# the same bump in #39369 after the first revert, so pin it here instead
# of relying on a package.json comment (package.json is JSON and can't
# hold comments). Remove this once the proxy code is updated to await
# the async decompress() API.
- dependency-name: "simple-zstd"
groups:
storybook:
applies-to: version-updates
patterns:
- "@storybook*"
- "storybook"
update-types:
- "patch"
directory: "/superset-frontend/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
groups:
rjsf:
patterns:
- "@rjsf/*"
typescript-eslint:
patterns:
- "@typescript-eslint/*"
- "typescript-eslint"
babel:
patterns:
- "@babel/*"
storybook:
patterns:
- "@storybook/*"
- "storybook"
- "eslint-plugin-storybook"
ag-grid:
patterns:
- "ag-grid-react"
- "ag-grid-community"
open-pull-requests-limit: 30
versioning-strategy: increase
cooldown:
default-days: 7
- package-ecosystem: "pip"
directory: "/"
# NOTE: `uv` support is in beta, more details here:
# https://github.com/dependabot/dependabot-core/pull/10040#issuecomment-2696978430
- package-ecosystem: "uv"
directory: "requirements/"
open-pull-requests-limit: 10
# Bump the lower bound to the new version, not just widen the upper
# bound. Without this, a `sqlglot>=28.10.0, <29` constraint upgraded
# to `<30` would keep the stale lower bound forever, dragging
# transitively-resolved versions with it. See #40186 (review thread).
versioning-strategy: increase
schedule:
interval: "weekly"
labels:
- pip
- uv
- dependabot
cooldown:
default-days: 7
- package-ecosystem: "npm"
directory: ".github/actions"
@@ -107,33 +68,29 @@ updates:
interval: "daily"
open-pull-requests-limit: 10
versioning-strategy: increase
cooldown:
default-days: 7
- package-ecosystem: "npm"
directory: "/docs/"
schedule:
interval: "daily"
ignore:
# TODO: remove below entries until React >= 18.0.0 in superset-frontend
- dependency-name: "storybook"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
- dependency-name: "@storybook*"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
- dependency-name: "eslint-plugin-storybook"
- dependency-name: "react-error-boundary"
groups:
storybook:
applies-to: version-updates
patterns:
- "@storybook/*"
- "@storybook*"
- "storybook"
docusaurus:
patterns:
- "@docusaurus/*"
docusaurus-openapi:
patterns:
- "docusaurus-plugin-openapi-docs"
- "docusaurus-theme-openapi-docs"
typescript-eslint:
patterns:
- "@typescript-eslint/*"
- "typescript-eslint"
update-types:
- "patch"
schedule:
interval: "daily"
open-pull-requests-limit: 10
versioning-strategy: increase
cooldown:
default-days: 7
- package-ecosystem: "npm"
directory: "/superset-websocket/"
@@ -143,8 +100,6 @@ updates:
- npm
- dependabot
versioning-strategy: increase
cooldown:
default-days: 7
- package-ecosystem: "npm"
directory: "/superset-websocket/utils/client-ws-app/"
@@ -155,5 +110,250 @@ updates:
- dependabot
open-pull-requests-limit: 10
versioning-strategy: increase
cooldown:
default-days: 7
# Now for all of our plugins and packages!
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-calendar/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-partition/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-world-map/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/plugin-chart-pivot-table/"
ignore:
# TODO: remove below entries until React >= 19.0.0
- dependency-name: "react-icons"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-chord/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-horizon/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-rose/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-preset-chart-deckgl/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/plugin-chart-table/"
ignore:
# TODO: remove below entries until React >= 19.0.0
- dependency-name: "react-icons"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-country-map/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-map-box/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-preset-chart-nvd3/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/plugin-chart-word-cloud/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-paired-t-test/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/plugin-chart-echarts/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/plugin-chart-ag-grid-table/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/plugin-chart-cartodiagram/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/plugins/plugin-chart-handlebars/"
ignore:
# `just-handlerbars-helpers` library in plugin-chart-handlebars requires `currencyformatter`` to be < 2
- dependency-name: "currencyformatter.js"
update-types: ["version-update:semver-major"]
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/packages/generator-superset/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/packages/superset-ui-chart-controls/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/packages/superset-ui-core/"
ignore:
# not until React >= 18.0.0
- dependency-name: "react-markdown"
- dependency-name: "remark-gfm"
- dependency-name: "react-error-boundary"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/superset-frontend/packages/superset-ui-switchboard/"
schedule:
interval: "daily"
labels:
- npm
- dependabot
open-pull-requests-limit: 5
versioning-strategy: increase
-15
View File
@@ -17,11 +17,6 @@
- any-glob-to-any-file:
- 'superset/migrations/**'
"risk:ci-script":
- changed-files:
- any-glob-to-any-file:
- 'scripts/**'
############################################
# Dependencies
############################################
@@ -77,11 +72,6 @@
- any-glob-to-any-file:
- 'superset/translations/zh/**'
"i18n:czech":
- changed-files:
- any-glob-to-any-file:
- 'superset/translations/cs/**'
"i18n:traditional-chinese":
- changed-files:
- any-glob-to-any-file:
@@ -127,11 +117,6 @@
- any-glob-to-any-file:
- 'superset/translations/sk/**'
"i18n:latvian":
- changed-files:
- any-glob-to-any-file:
- 'superset/translations/lv/**'
"i18n:ukrainian":
- changed-files:
- any-glob-to-any-file:
+40 -126
View File
@@ -20,6 +20,10 @@ set -e
GITHUB_WORKSPACE=${GITHUB_WORKSPACE:-.}
ASSETS_MANIFEST="$GITHUB_WORKSPACE/superset/static/assets/manifest.json"
# Rounded job start time, used to create a unique Cypress build id for
# parallelization so we can manually rerun a job after 20 minutes
NONCE=$(echo "$(date "+%Y%m%d%H%M") - ($(date +%M)%20)" | bc)
# Echo only when not in parallel mode
say() {
if [[ $(echo "$INPUT_PARALLEL" | tr '[:lower:]' '[:upper:]') != 'TRUE' ]]; then
@@ -55,15 +59,6 @@ build-assets() {
say "::endgroup::"
}
build-embedded-sdk() {
cd "$GITHUB_WORKSPACE/superset-embedded-sdk"
say "::group::Build embedded SDK bundle for E2E tests"
npm ci
npm run build
say "::endgroup::"
}
build-instrumented-assets() {
cd "$GITHUB_WORKSPACE/superset-frontend"
@@ -114,7 +109,7 @@ testdata() {
say "::group::Load test data"
# must specify PYTHONPATH to make `tests.superset_test_config` importable
export PYTHONPATH="$GITHUB_WORKSPACE"
uv pip install --system -e .
pip install -e .
superset db upgrade
superset load_test_users
superset load_examples --load-test-data
@@ -127,25 +122,11 @@ playwright_testdata() {
say "::group::Load all examples for Playwright tests"
# must specify PYTHONPATH to make `tests.superset_test_config` importable
export PYTHONPATH="$GITHUB_WORKSPACE"
uv pip install --system -e .
pip install -e .
superset db upgrade
superset load_test_users
superset load_examples
superset init
# Enable DML on the examples database so Playwright tests can create/drop
# temporary tables via SQL Lab without depending on external data sources.
superset shell <<'PYEOF'
import sys
from superset.extensions import db
from superset.models.core import Database
examples_db = db.session.query(Database).filter_by(database_name='examples').first()
if not examples_db:
sys.exit('ERROR: examples database not found. load_examples may have failed.')
examples_db.allow_dml = True
db.session.commit()
print('Enabled allow_dml on examples database')
PYEOF
say "::endgroup::"
}
@@ -180,13 +161,10 @@ cypress-run-all() {
local APP_ROOT=$2
cd "$GITHUB_WORKSPACE/superset-frontend/cypress-base"
# Start the Superset backend via gunicorn (not `flask run`). The Flask
# development server is single-threaded and has no crash-recovery, so
# heavy tests (dashboard import/export, SQL Lab) can knock it offline
# for the rest of the run — surfacing as `ECONNREFUSED` / `socket hang up`
# / `Missing CSRF token` cascades. Gunicorn gives us multiple workers,
# a request timeout, and worker-recycling under load.
local serverlog="${HOME}/superset-cypress.log"
# Start Flask and run it in background
# --no-debugger means disable the interactive debugger on the 500 page
# so errors can print to stderr.
local flasklog="${HOME}/flask.log"
local port=8081
CYPRESS_BASE_URL="http://localhost:${port}"
if [ -n "$APP_ROOT" ]; then
@@ -195,63 +173,8 @@ cypress-run-all() {
fi
export CYPRESS_BASE_URL
# Mirrors the args in docker/entrypoints/run-server.sh (1 worker × 20
# gthread threads) to keep parity with production. Multi-worker
# configurations expose timing-sensitive races in the SQL Lab → Explore
# navigation flow under E2E. We diverge from the entrypoint on:
# --timeout 120: heavy dashboard import/export specs exceed the 60s
# default
# superset.app:create_app(): explicit factory so we don't depend on
# FLASK_APP being exported
#
# No --max-requests, matching the entrypoint's default of 0 (recycling
# off). With a single worker a recycle takes the whole backend offline for
# the graceful-timeout drain — browser keep-alive connections hold it open
# for the full 30s — plus ~5s of app boot. A run issues ~3800 requests in
# ~8 minutes, so recycling every 500 produced seven ~35s outages per run
# and flaked whichever specs happened to navigate into one. Lowering
# --graceful-timeout is not enough: a dashboard load plus chart render
# needs 6-10s, which still lands inside the window.
nohup gunicorn \
--bind "127.0.0.1:$port" \
--workers 1 \
--worker-class gthread \
--threads 20 \
--timeout 120 \
--access-logfile - \
--error-logfile - \
"superset.app:create_app()" \
>"$serverlog" 2>&1 </dev/null &
local serverPid=$!
# Ensure the backend is cleaned up and its log is emitted even when the
# test runner fails under `set -e`.
trap '
echo "::group::gunicorn log for Cypress run"
cat "'"$serverlog"'" || true
echo "::endgroup::"
kill '"$serverPid"' 2>/dev/null || true
' EXIT
# Wait for the backend to be ready before launching Cypress; otherwise
# the first spec can race the server bind and see connection errors.
local timeout=60
say "Waiting for gunicorn server to start on port $port..."
while [ $timeout -gt 0 ]; do
if curl -f "http://localhost:${port}${APP_ROOT}/health" >/dev/null 2>&1; then
say "gunicorn server is ready"
break
fi
sleep 1
timeout=$((timeout - 1))
done
if [ $timeout -eq 0 ]; then
echo "::error::gunicorn server failed to start within 60 seconds"
echo "::group::Server startup log"
cat "$serverlog"
echo "::endgroup::"
return 1
fi
nohup flask run --no-debugger -p $port >"$flasklog" 2>&1 </dev/null &
local flaskProcessId=$!
USE_DASHBOARD_FLAG=''
if [ "$USE_DASHBOARD" = "true" ]; then
@@ -261,8 +184,15 @@ cypress-run-all() {
# UNCOMMENT the next few commands to monitor memory usage
# monitor_memory & # Start memory monitoring in the background
# memoryMonitorPid=$!
python ../../scripts/cypress_run.py --retries 5 $USE_DASHBOARD_FLAG
python ../../scripts/cypress_run.py --parallelism $PARALLELISM --parallelism-id $PARALLEL_ID --group $PARALLEL_ID --retries 5 $USE_DASHBOARD_FLAG
# kill $memoryMonitorPid
# After job is done, print out Flask log for debugging
echo "::group::Flask log for default run"
cat "$flasklog"
echo "::endgroup::"
# make sure the program exits
kill $flaskProcessId
}
playwright-install() {
@@ -280,53 +210,29 @@ playwright-run() {
local APP_ROOT=$1
local TEST_PATH=$2
# Start the Superset backend via gunicorn from the project root.
# See cypress-run-all() above for the rationale — the Flask dev server
# cannot survive the dashboard import/export tests under load.
# Start Flask from the project root (same as Cypress)
cd "$GITHUB_WORKSPACE"
local serverlog="${HOME}/superset-playwright.log"
local flasklog="${HOME}/flask-playwright.log"
local port=8081
# Use 127.0.0.1 explicitly: `flask run` binds IPv4 only, and Node's DNS
# resolution for `localhost` can return `::1` first (IPv6), which then
# refuses against the IPv4 listener and surfaces as
# `connect ECONNREFUSED ::1:<port>` in API helpers driven from Node
# (e.g., the embedded test app's exposed token fetcher).
PLAYWRIGHT_BASE_URL="http://127.0.0.1:${port}"
PLAYWRIGHT_BASE_URL="http://localhost:${port}"
if [ -n "$APP_ROOT" ]; then
export SUPERSET_APP_ROOT=$APP_ROOT
PLAYWRIGHT_BASE_URL=${PLAYWRIGHT_BASE_URL}${APP_ROOT}/
fi
export PLAYWRIGHT_BASE_URL
# See cypress-run-all() above for the args rationale (1 worker × 20
# gthread threads matching docker/entrypoints/run-server.sh, a 120s
# timeout for heavy E2E load, and why worker recycling is off).
nohup gunicorn \
--bind "127.0.0.1:$port" \
--workers 1 \
--worker-class gthread \
--threads 20 \
--timeout 120 \
--access-logfile - \
--error-logfile - \
"superset.app:create_app()" \
>"$serverlog" 2>&1 </dev/null &
local serverPid=$!
nohup flask run --no-debugger -p $port >"$flasklog" 2>&1 </dev/null &
local flaskProcessId=$!
# Ensure cleanup on exit (and emit the server log on failure)
trap '
echo "::group::gunicorn log for Playwright run"
cat "'"$serverlog"'" || true
echo "::endgroup::"
kill '"$serverPid"' 2>/dev/null || true
' EXIT
# Ensure cleanup on exit
trap "kill $flaskProcessId 2>/dev/null || true" EXIT
# Wait for server to be ready with health check
local timeout=60
say "Waiting for gunicorn server to start on port $port..."
say "Waiting for Flask server to start on port $port..."
while [ $timeout -gt 0 ]; do
if curl -f ${PLAYWRIGHT_BASE_URL}/health >/dev/null 2>&1; then
say "gunicorn server is ready"
say "Flask server is ready"
break
fi
sleep 1
@@ -334,9 +240,9 @@ playwright-run() {
done
if [ $timeout -eq 0 ]; then
echo "::error::gunicorn server failed to start within 60 seconds"
echo "::group::Server startup log"
cat "$serverlog"
echo "::error::Flask server failed to start within 60 seconds"
echo "::group::Flask startup log"
cat "$flasklog"
echo "::endgroup::"
return 1
fi
@@ -351,6 +257,7 @@ playwright-run() {
if ! find "playwright/tests/${TEST_PATH}" -name "*.spec.ts" -type f 2>/dev/null | grep -q .; then
echo "No test files found in ${TEST_PATH} - skipping test run"
say "::endgroup::"
kill $flaskProcessId
return 0
fi
echo "Running tests: ${TEST_PATH}"
@@ -367,6 +274,13 @@ playwright-run() {
fi
say "::endgroup::"
# After job is done, print out Flask log for debugging
echo "::group::Flask log for Playwright run"
cat "$flasklog"
echo "::endgroup::"
# make sure the program exits
kill $flaskProcessId
return $status
}
+11 -14
View File
@@ -23,15 +23,16 @@ on:
jobs:
bump-python-package:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
permissions:
actions: write
contents: write
pull-requests: write
checks: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: true
ref: master
@@ -40,9 +41,9 @@ jobs:
uses: ./.github/actions/setup-supersetbot/
- name: Set up Python ${{ inputs.python-version }}
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: "3.11"
python-version: "3.10"
- name: Install uv
run: pip install uv
@@ -50,31 +51,27 @@ 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 "${INPUT_PACKAGE}" ]; then
PACKAGE_OPT="-p ${INPUT_PACKAGE}"
if [ -n "${{ github.event.inputs.package }}" ]; then
PACKAGE_OPT="-p ${{ github.event.inputs.package }}"
fi
GROUP_OPT=""
if [ -n "${INPUT_GROUP}" ]; then
GROUP_OPT="-g ${INPUT_GROUP}"
if [ -n "${{ github.event.inputs.group }}" ]; then
GROUP_OPT="-g ${{ github.event.inputs.group }}"
fi
EXTRA_FLAGS="${INPUT_EXTRA_FLAGS}"
EXTRA_FLAGS="${{ github.event.inputs.extra-flags }}"
supersetbot bump-python \
--verbose \
--use-current-repo \
--include-subpackages \
--limit ${INPUT_LIMIT} \
--limit ${{ github.event.inputs.limit }} \
$PACKAGE_OPT \
$GROUP_OPT \
$EXTRA_FLAGS
+43
View File
@@ -0,0 +1,43 @@
name: Cancel Duplicates
on:
workflow_run:
workflows:
- "Miscellaneous"
types:
- requested
jobs:
cancel-duplicate-runs:
name: Cancel duplicate workflow runs
runs-on: ubuntu-24.04
permissions:
actions: write
contents: read
steps:
- name: Check number of queued tasks
id: check_queued
env:
GITHUB_TOKEN: ${{ github.token }}
GITHUB_REPO: ${{ github.repository }}
run: |
get_count() {
echo $(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$GITHUB_REPO/actions/runs?status=$1" | \
jq ".total_count")
}
count=$(( `get_count queued` + `get_count in_progress` ))
echo "Found $count unfinished jobs."
echo "count=$count" >> $GITHUB_OUTPUT
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
if: steps.check_queued.outputs.count >= 20
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Cancel duplicate workflow runs
if: steps.check_queued.outputs.count >= 20
env:
GITHUB_TOKEN: ${{ github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
pip install click requests typing_extensions python-dateutil
python ./scripts/cancel_github_workflows.py
@@ -1,77 +0,0 @@
name: Check DB migration conflict
on:
push:
paths:
- "superset/migrations/**"
branches:
- "master"
- "[0-9].[0-9]*"
pull_request:
paths:
- "superset/migrations/**"
types: [synchronize, opened, reopened, ready_for_review]
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
check_db_migration_conflict:
name: Check DB migration conflict
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check and notify
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ github.token }}
script: |
// API reference: https://octokit.github.io/rest.js
const currentBranch = context.ref.replace('refs/heads/', '');
// Find all pull requests to current branch
const opts = github.rest.pulls.list.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
base: context.ref,
state: 'open',
sort: 'updated',
per_page: 100,
});
const pulls = await github.paginate(opts);
if (pulls.length > 0) {
console.log(`Found ${pulls.length} open PRs for base branch "${currentBranch}"`)
}
for (const pull of pulls) {
const listFilesOpts = await github.rest.pulls.listFiles.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pull.number,
});
const files = await github.paginate(listFilesOpts);
if (
files.some(x => x.contents_url.includes('/contents/superset/migrations'))
) {
console.log(`PR #${pull.number} "${pull.title}" also added db migration`)
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pull.number,
body:
`# 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️` +
`❗ @${pull.user.login} Your base branch \`${currentBranch}\` has ` +
'also updated `superset/migrations`.\n' +
'\n' +
'**Please consider rebasing your branch and [resolving potential db migration conflicts](https://superset.apache.org/docs/contributing/development#merging-db-migrations).**',
});
}
}
+2 -24
View File
@@ -8,11 +8,6 @@ on:
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
permissions:
contents: read
pull-requests: read
actions: read
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
@@ -20,14 +15,10 @@ concurrency:
jobs:
check-python-deps:
runs-on: ubuntu-26.04
runs-on: ubuntu-22.04
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -43,19 +34,6 @@ jobs:
if: steps.check.outputs.python
uses: ./.github/actions/setup-backend/
# Authenticate the Docker daemon so the python:slim pull in
# uv-pip-compile.sh uses our (much higher) authenticated rate limit
# instead of the shared-runner anonymous one. Best-effort: on fork PRs the
# secrets are unavailable, so this no-ops and the pull falls back to
# anonymous (covered by the retry loop in the script).
- name: Login to Docker Hub
if: steps.check.outputs.python
continue-on-error: true
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Run uv
if: steps.check.outputs.python
run: ./scripts/uv-pip-compile.sh
@@ -0,0 +1,75 @@
name: Check DB migration conflict
on:
push:
paths:
- "superset/migrations/**"
branches:
- "master"
- "[0-9].[0-9]*"
pull_request:
paths:
- "superset/migrations/**"
types: [synchronize, opened, reopened, ready_for_review]
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
check_db_migration_conflict:
name: Check DB migration conflict
runs-on: ubuntu-24.04
permissions:
contents: read
pull-requests: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check and notify
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{ github.token }}
script: |
// API reference: https://octokit.github.io/rest.js
const currentBranch = context.ref.replace('refs/heads/', '');
// Find all pull requests to current branch
const opts = github.rest.pulls.list.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
base: context.ref,
state: 'open',
sort: 'updated',
per_page: 100,
});
const pulls = await github.paginate(opts);
if (pulls.length > 0) {
console.log(`Found ${pulls.length} open PRs for base branch "${currentBranch}"`)
}
for (const pull of pulls) {
const listFilesOpts = await github.rest.pulls.listFiles.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pull.number,
});
const files = await github.paginate(listFilesOpts);
if (
files.some(x => x.contents_url.includes('/contents/superset/migrations'))
) {
console.log(`PR #${pull.number} "${pull.title}" also added db migration`)
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pull.number,
body:
`# 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️ 🙅‍♂️` +
`❗ @${pull.user.login} Your base branch \`${currentBranch}\` has ` +
'also updated `superset/migrations`.\n' +
'\n' +
'**Please consider rebasing your branch and [resolving potential db migration conflicts](https://superset.apache.org/docs/contributing/development#merging-db-migrations).**',
});
}
}
+82
View File
@@ -0,0 +1,82 @@
name: Claude PR Assistant
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
check-permissions:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude'))
runs-on: ubuntu-latest
outputs:
allowed: ${{ steps.check.outputs.allowed }}
steps:
- name: Check if user is allowed
id: check
run: |
# List of allowed users
ALLOWED_USERS="mistercrunch,rusackas"
# Get the commenter's username
COMMENTER="${{ github.event.comment.user.login }}"
echo "Checking permissions for user: $COMMENTER"
# Check if user is in allowed list
if [[ ",$ALLOWED_USERS," == *",$COMMENTER,"* ]]; then
echo "allowed=true" >> $GITHUB_OUTPUT
echo "✅ User $COMMENTER is allowed to use Claude"
else
echo "allowed=false" >> $GITHUB_OUTPUT
echo "❌ User $COMMENTER is not allowed to use Claude"
fi
deny-access:
needs: check-permissions
if: needs.check-permissions.outputs.allowed == 'false'
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: Comment access denied
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const message = `👋 Hi @${{ github.event.comment.user.login || github.event.review.user.login || github.event.issue.user.login }}!
Thanks for trying to use Claude Code, but currently only certain team members have access to this feature.
If you believe you should have access, please contact a project maintainer.`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: message
});
claude-code-action:
needs: check-permissions
if: needs.check-permissions.outputs.allowed == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 1
- name: Run Claude PR Action
uses: anthropics/claude-code-action@28f83620103c48a57093dcc2837eec89e036bb9f # beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
timeout_minutes: "60"
+10 -32
View File
@@ -15,39 +15,12 @@ concurrency:
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-26.04
timeout-minutes: 10
permissions:
contents: read
pull-requests: read
outputs:
python: ${{ steps.check.outputs.python }}
frontend: ${{ steps.check.outputs.frontend }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
analyze:
name: Analyze
needs: changes
# Skip on PRs that touch neither code group (e.g. docs-only) so the
# analysis runners don't spin up. push/schedule runs always proceed:
# the change-detector returns "all changed" for non-PR events.
if: needs.changes.outputs.python == 'true' || needs.changes.outputs.frontend == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 30
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read
pull-requests: read
security-events: write
strategy:
@@ -58,13 +31,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
persist-credentials: false
token: ${{ secrets.GITHUB_TOKEN }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -75,6 +52,7 @@ jobs:
# queries: security-extended,security-and-quality
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
@@ -1,63 +0,0 @@
name: Auto-approve Dependabot patch bumps
# Posts an approving review on Dependabot PRs that only bump a patch
# version, using the same trigger/guard convention already proven to work
# for Dependabot PRs in sync-requirements-for-python-dep-upgrade-pr.yml
# (plain `pull_request` gets a working, write-capable GITHUB_TOKEN here
# because Dependabot pushes branches directly to this repo, not a fork).
#
# This does NOT auto-merge anything - repo-wide auto-merge is disabled
# (Settings > General > Pull Requests > "Allow auto-merge" is off), and
# flipping that is a separate, repo-wide decision this workflow doesn't
# make on its own. Branch protection also still requires 1 approving
# review; this just means that review can already exist by the time a
# human looks at the PR, for the (large majority of) ecosystems whose
# files aren't matched by any CODEOWNERS pattern. One ecosystem - the npm
# bump under .github/actions - matches the /.github/ CODEOWNERS entry, so
# those PRs will still need a human owner's approval regardless of this
# workflow; it posts a review there too, but that alone won't satisfy the
# code-owner requirement.
on:
pull_request:
types: [opened, synchronize]
# Cancel a superseded run if Dependabot pushes to the same PR again before
# the previous run finished (matches the pattern used elsewhere in
# superset-docs-verify.yml).
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions: {}
jobs:
approve-patch-bump:
name: Approve patch-level bump
# Mirrors the guard in sync-requirements-for-python-dep-upgrade-pr.yml:
# limited to (1) PRs authored by Dependabot and (2) the upstream repo,
# since forked PRs don't get a write-capable token here anyway.
if: >
github.repository == 'apache/superset' &&
github.event.pull_request.user.login == 'dependabot[bot]' &&
github.event.pull_request.head.repo.fork == false
runs-on: ubuntu-latest
permissions:
pull-requests: write # to post the approving review via `gh pr review`
steps:
- name: Fetch Dependabot metadata
id: metadata
# This exact SHA is on ASF Infra's action allowlist
# (apache/infrastructure-actions approved_patterns.yml) as of this
# writing. Do not bump without opening an Infra ticket to allow
# the new SHA first!
uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0
- name: Approve patch-level bump
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
DEPENDENCY_NAMES: ${{ steps.metadata.outputs.dependency-names }}
run: |
gh pr review --approve "$PR_URL" \
--body "Auto-approved: patch-level bump only ($DEPENDENCY_NAMES)."
+7 -15
View File
@@ -20,19 +20,17 @@ concurrency:
permissions:
contents: read
actions: read
jobs:
dependency-review:
if: github.event_name == 'pull_request'
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
steps:
- name: "Checkout Repository"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: "Dependency Review"
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
continue-on-error: true
with:
fail-on-severity: critical
# compatible/incompatible licenses addressed here: https://www.apache.org/legal/resolved.html
@@ -43,21 +41,15 @@ jobs:
# the latest version. It's MIT: https://github.com/nbubna/store/blob/master/LICENSE-MIT
# pkg:npm/node-forge@1.3.1
# selecting BSD-3-Clause licensing terms for node-forge to ensure compatibility with Apache
allow-dependencies-licenses: pkg:npm/rgbcolor, pkg:npm/jszip@3.10.1
allow-dependencies-licenses: pkg:npm/store2@2.14.2, pkg:npm/node-forge@1.3.1, pkg:npm/rgbcolor, pkg:npm/jszip@3.10.1
python-dependency-liccheck:
# NOTE: Configuration for liccheck lives in our pyproject.yml.
# You cannot use a liccheck.ini file in this workflow.
runs-on: ubuntu-slim
runs-on: ubuntu-22.04
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout Repository"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup Python
uses: ./.github/actions/setup-backend/
+36 -120
View File
@@ -9,57 +9,26 @@ on:
branches:
- "master"
permissions:
contents: read
pull-requests: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-26.04
timeout-minutes: 10
permissions:
contents: read
pull-requests: read
outputs:
python: ${{ steps.check.outputs.python }}
frontend: ${{ steps.check.outputs.frontend }}
docker: ${{ steps.check.outputs.docker }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
setup_matrix:
runs-on: ubuntu-slim
timeout-minutes: 5
runs-on: ubuntu-24.04
outputs:
matrix_config: ${{ steps.set_matrix.outputs.matrix_config }}
steps:
- id: set_matrix
run: |
MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev", "lean"]'; else echo '["dev", "lean", "websocket", "dockerize", "py311", "py312"]'; fi)
MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev", "lean"]'; else echo '["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"]'; fi)
echo "matrix_config=${MATRIX_CONFIG}" >> $GITHUB_OUTPUT
echo $GITHUB_OUTPUT
docker-build:
name: docker-build
needs: [setup_matrix, changes]
if: >-
needs.changes.outputs.python == 'true' ||
needs.changes.outputs.frontend == 'true' ||
needs.changes.outputs.docker == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 60
needs: setup_matrix
runs-on: ubuntu-24.04
strategy:
matrix:
build_preset: ${{fromJson(needs.setup_matrix.outputs.matrix_config)}}
@@ -71,29 +40,18 @@ jobs:
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Free up disk space
shell: bash
run: |
# Reclaim large preinstalled toolchains we don't use. The image
# build, and especially the docker-compose sanity check (which
# rebuilds from scratch whenever the registry cache image
# apache/superset-cache is unavailable), can otherwise exhaust the
# runner's root disk and fail with "no space left on device".
echo "Disk before cleanup:"; df -h /
sudo rm -rf \
/usr/share/dotnet \
/usr/local/lib/android \
/opt/ghc \
/usr/local/.ghcup \
/opt/hostedtoolcache/CodeQL \
/usr/local/share/boost || true
echo "Disk after cleanup:"; df -h /
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Docker Environment
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
uses: ./.github/actions/setup-docker
with:
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
@@ -101,56 +59,36 @@ jobs:
build: "true"
- name: Setup supersetbot
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
uses: ./.github/actions/setup-supersetbot/
- name: Build Docker Image
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_PRESET: ${{ matrix.build_preset }}
run: |
# Single platform builds in pull_request context to speed things up
if [ "$GITHUB_EVENT_NAME" = "push" ]; then
if [ "${{ github.event_name }}" = "push" ]; then
PLATFORM_ARG="--platform linux/arm64 --platform linux/amd64"
# can only --load images in single-platform builds
PUSH_OR_LOAD="--push"
elif [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
elif [ "${{ github.event_name }}" = "pull_request" ]; then
PLATFORM_ARG="--platform linux/amd64"
PUSH_OR_LOAD="--load"
fi
# Retry to absorb transient Docker Hub registry errors (base-image
# pull timeouts, 504/401 on push, ECONNRESET) that otherwise fail
# the whole job. buildx reuses the buildkit layer cache from the
# failed attempt, so a retry mostly re-does just the failed push.
#
# supersetbot's "dev"/"lean" presets pin their own --build-arg
# PY_VER, which lands ahead of --extra-flags on the assembled
# buildx command line; docker/buildx keeps the last value for a
# repeated --build-arg key, so appending PY_VER here overrides
# supersetbot's pin and keeps the build on the Dockerfile's own
# supported Python version.
for attempt in 1 2 3; do
if supersetbot docker \
$PUSH_OR_LOAD \
--preset "$BUILD_PRESET" \
--context "$EVENT" \
--context-ref "$RELEASE" $FORCE_LATEST \
--extra-flags "--build-arg PY_VER=3.11.14-slim-trixie --build-arg INCLUDE_CHROMIUM=false --tag $IMAGE_TAG" \
$PLATFORM_ARG; then
break
fi
if [ "$attempt" -eq 3 ]; then
echo "::error::supersetbot docker build failed after 3 attempts"
exit 1
fi
echo "::warning::Build attempt ${attempt} failed; retrying in 30s..."
sleep 30
done
supersetbot docker \
$PUSH_OR_LOAD \
--preset ${{ matrix.build_preset }} \
--context "$EVENT" \
--context-ref "$RELEASE" $FORCE_LATEST \
--extra-flags "--build-arg INCLUDE_CHROMIUM=false --tag $IMAGE_TAG" \
$PLATFORM_ARG
# in the context of push (using multi-platform build), we need to pull the image locally
- name: Docker pull
if: github.event_name == 'push'
if: github.event_name == 'push' && (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker)
run: |
for i in 1 2 3; do
docker pull $IMAGE_TAG && break
@@ -158,6 +96,7 @@ jobs:
done
- name: Print docker stats
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
run: |
echo "SHA: ${{ github.sha }}"
echo "IMAGE: $IMAGE_TAG"
@@ -165,12 +104,10 @@ jobs:
docker history $IMAGE_TAG
- name: docker-compose sanity check
if: matrix.build_preset == 'dev'
if: (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker) && matrix.build_preset == 'dev'
shell: bash
env:
BUILD_PRESET: ${{ matrix.build_preset }}
run: |
export SUPERSET_BUILD_TARGET=$BUILD_PRESET
export SUPERSET_BUILD_TARGET=${{ matrix.build_preset }}
# This should reuse the CACHED image built in the previous steps
docker compose build superset-init --build-arg DEV_MODE=false --build-arg INCLUDE_CHROMIUM=false
docker compose up superset-init --exit-code-from superset-init
@@ -178,31 +115,20 @@ jobs:
docker-compose-image-tag:
# Run this job only on pushes to master (not for PRs)
# goal is to check that building the latest image works, not required for all PR pushes
needs: changes
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && needs.changes.outputs.docker == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 30
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Free up disk space
shell: bash
run: |
# The sanity check rebuilds the image from scratch whenever the
# registry cache image apache/superset-cache is unavailable, which
# can exhaust the runner's root disk ("no space left on device").
echo "Disk before cleanup:"; df -h /
sudo rm -rf \
/usr/share/dotnet \
/usr/local/lib/android \
/opt/ghc \
/usr/local/.ghcup \
/opt/hostedtoolcache/CodeQL \
/usr/local/share/boost || true
echo "Disk after cleanup:"; df -h /
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Docker Environment
if: steps.check.outputs.docker
uses: ./.github/actions/setup-docker
with:
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
@@ -210,17 +136,7 @@ jobs:
build: "false"
install-docker-compose: "true"
- name: docker-compose sanity check
if: steps.check.outputs.docker
shell: bash
run: |
docker compose -f docker-compose-image-tag.yml up superset-init --exit-code-from superset-init
actions-timeline:
needs: [docker-build, docker-compose-image-tag]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+22 -21
View File
@@ -6,33 +6,34 @@ on:
- "master"
- "[0-9].[0-9]*"
permissions:
contents: read
jobs:
config:
runs-on: ubuntu-24.04
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
- name: "Check for secrets"
id: check
shell: bash
run: |
if [ -n "${{ (secrets.NPM_TOKEN != '') || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
build:
# Publishing uses npm trusted publishing (OIDC), so there is no NPM_TOKEN to
# gate on. Restrict to the canonical repo: forks cannot mint a valid OIDC
# token for this package and must not publish.
if: github.repository == 'apache/superset'
runs-on: ubuntu-slim
permissions:
contents: read
id-token: write # required for npm trusted publishing (OIDC)
needs: config
if: needs.config.outputs.has-secrets
runs-on: ubuntu-24.04
defaults:
run:
working-directory: superset-embedded-sdk
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
persist-credentials: false
# Note: registry-url is intentionally omitted. When set, actions/setup-node
# writes an .npmrc with `_authToken=${NODE_AUTH_TOKEN}` and a placeholder
# token, which makes npm attempt token auth and skip the OIDC
# trusted-publishing exchange. With no .npmrc auth line, npm authenticates
# via OIDC against the default registry (registry.npmjs.org).
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: "./superset-embedded-sdk/.nvmrc"
node-version-file: './superset-embedded-sdk/.nvmrc'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm run ci:release
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+5 -10
View File
@@ -6,9 +6,6 @@ on:
- "superset-embedded-sdk/**"
types: [synchronize, opened, reopened, ready_for_review]
permissions:
contents: read
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
@@ -16,18 +13,16 @@ concurrency:
jobs:
embedded-sdk-test:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
defaults:
run:
working-directory: superset-embedded-sdk
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: "./superset-embedded-sdk/.nvmrc"
registry-url: "https://registry.npmjs.org"
node-version-file: './superset-embedded-sdk/.nvmrc'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm test
- run: npm run build
@@ -0,0 +1,81 @@
name: Cleanup ephemeral envs (PR close) [DEPRECATED]
# ⚠️ DEPRECATION NOTICE ⚠️
# This workflow is deprecated and will be removed in a future version.
# The new Superset Showtime workflow handles cleanup automatically.
# See .github/workflows/showtime.yml and showtime-cleanup.yml for replacements.
# Migration guide: https://github.com/mistercrunch/superset-showtime
on:
pull_request_target:
types: [closed]
jobs:
config:
runs-on: ubuntu-24.04
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
- name: "Check for secrets"
id: check
shell: bash
run: |
if [ -n "${{ (secrets.AWS_ACCESS_KEY_ID != '' && secrets.AWS_SECRET_ACCESS_KEY != '') || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
ephemeral-env-cleanup:
needs: config
if: needs.config.outputs.has-secrets
name: Cleanup ephemeral envs
runs-on: ubuntu-24.04
permissions:
pull-requests: write
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2
- name: Describe ECS service
id: describe-services
run: |
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
- name: Delete ECS service
if: steps.describe-services.outputs.active == 'true'
id: delete-service
run: |
aws ecs delete-service \
--cluster superset-ci \
--service pr-${{ github.event.number }}-service \
--force
- name: Login to Amazon ECR
if: steps.describe-services.outputs.active == 'true'
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Delete ECR image tag
if: steps.describe-services.outputs.active == 'true'
id: delete-image-tag
run: |
aws ecr batch-delete-image \
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
--repository-name superset-ci \
--image-ids imageTag=pr-${{ github.event.number }}
- name: Comment (success)
if: steps.describe-services.outputs.active == 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{github.token}}
script: |
github.rest.issues.createComment({
issue_number: ${{ github.event.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: '⚠️ **DEPRECATED WORKFLOW** - Ephemeral environment shutdown and build artifacts deleted. Please migrate to the new Superset Showtime system for future PRs.'
})
+344
View File
@@ -0,0 +1,344 @@
name: Ephemeral env workflow [DEPRECATED]
# ⚠️ DEPRECATION NOTICE ⚠️
# This workflow is deprecated and will be removed in a future version.
# Please use the new Superset Showtime workflow instead:
# - Use label "🎪 trigger-start" instead of "testenv-up"
# - Showtime provides better reliability and easier management
# - See .github/workflows/showtime.yml for the replacement
# - Migration guide: https://github.com/mistercrunch/superset-showtime
# Example manual trigger:
# gh workflow run ephemeral-env.yml --ref fix_ephemerals --field label_name="testenv-up" --field issue_number=666
on:
pull_request_target:
types:
- labeled
workflow_dispatch:
inputs:
label_name:
description: 'Label name to simulate label-based /testenv trigger'
required: true
default: 'testenv-up'
issue_number:
description: 'Issue or PR number'
required: true
jobs:
ephemeral-env-label:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-label
cancel-in-progress: true
name: Evaluate ephemeral env label trigger
runs-on: ubuntu-24.04
permissions:
pull-requests: write
outputs:
slash-command: ${{ steps.eval-label.outputs.result }}
feature-flags: ${{ steps.eval-feature-flags.outputs.result }}
sha: ${{ steps.get-sha.outputs.sha }}
env:
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
steps:
- name: Check for the "testenv-up" label
id: eval-label
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
LABEL_NAME="${{ github.event.inputs.label_name }}"
else
LABEL_NAME="${{ github.event.label.name }}"
fi
echo "Evaluating label: $LABEL_NAME"
if [[ "$LABEL_NAME" == "testenv-up" ]]; then
echo "result=up" >> $GITHUB_OUTPUT
else
echo "result=noop" >> $GITHUB_OUTPUT
fi
- name: Get event SHA
id: get-sha
if: steps.eval-label.outputs.result == 'up'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
let prSha;
// If event is workflow_dispatch, use the issue_number from inputs
if (context.eventName === "workflow_dispatch") {
const prNumber = "${{ github.event.inputs.issue_number }}";
if (!prNumber) {
console.log("No PR number found.");
return;
}
// Fetch PR details using the provided issue_number
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
prSha = pr.head.sha;
} else {
// If it's not workflow_dispatch, use the PR head sha from the event
prSha = context.payload.pull_request.head.sha;
}
console.log(`PR SHA: ${prSha}`);
core.setOutput("sha", prSha);
- name: Looking for feature flags in PR description
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
id: eval-feature-flags
if: steps.eval-label.outputs.result == 'up'
with:
script: |
const description = context.payload.pull_request
? context.payload.pull_request.body || ''
: context.payload.inputs.pr_description || '';
const pattern = /FEATURE_(\w+)=(\w+)/g;
let results = [];
[...description.matchAll(pattern)].forEach(match => {
const config = {
name: `SUPERSET_FEATURE_${match[1]}`,
value: match[2],
};
results.push(config);
});
return results;
- name: Reply with confirmation comment
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
if: steps.eval-label.outputs.result == 'up'
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const action = '${{ steps.eval-label.outputs.result }}';
const user = context.actor;
const runId = context.runId;
const workflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
const issueNumber = context.payload.pull_request
? context.payload.pull_request.number
: context.payload.inputs.issue_number;
if (!issueNumber) {
throw new Error("Issue number is not available.");
}
const body = `⚠️ **DEPRECATED WORKFLOW** ⚠️\n\n@${user} This workflow is deprecated! Please use the new **Superset Showtime** system instead:\n\n` +
`- Replace "testenv-up" label with "🎪 trigger-start"\n` +
`- Better reliability and easier management\n` +
`- See https://github.com/mistercrunch/superset-showtime for details\n\n` +
`Processing your ephemeral environment request [here](${workflowUrl}). Action: **${action}**.` +
` More information on [how to use or configure ephemeral environments]` +
`(https://superset.apache.org/docs/contributing/howtos/#github-ephemeral-environments)`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body,
});
ephemeral-docker-build:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-build
cancel-in-progress: true
needs: ephemeral-env-label
if: needs.ephemeral-env-label.outputs.slash-command == 'up'
name: ephemeral-docker-build
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ needs.ephemeral-env-label.outputs.sha }} : ${{steps.get-sha.outputs.sha}} )"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ needs.ephemeral-env-label.outputs.sha }}
persist-credentials: false
- name: Setup Docker Environment
uses: ./.github/actions/setup-docker
with:
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
build: "true"
install-docker-compose: "false"
- name: Setup supersetbot
uses: ./.github/actions/setup-supersetbot/
- name: Build ephemeral env image
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
supersetbot docker \
--push \
--load \
--preset ci \
--platform linux/amd64 \
--context-ref "$RELEASE" \
--extra-flags "--build-arg INCLUDE_CHROMIUM=false"
- name: Configure AWS credentials
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 }}
aws-region: us-west-2
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@c962da2960ed15f492addc26fffa274485265950 # v2
- name: Load, tag and push image to ECR
id: push-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: superset-ci
IMAGE_TAG: apache/superset:${{ needs.ephemeral-env-label.outputs.sha }}-ci
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
run: |
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-$PR_NUMBER-ci
docker push -a $ECR_REGISTRY/$ECR_REPOSITORY
ephemeral-env-up:
needs: [ephemeral-env-label, ephemeral-docker-build]
if: needs.ephemeral-env-label.outputs.slash-command == 'up'
name: Spin up an ephemeral environment
runs-on: ubuntu-24.04
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Configure AWS credentials
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 }}
aws-region: us-west-2
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@c962da2960ed15f492addc26fffa274485265950 # v2
- name: Check target image exists in ECR
id: check-image
continue-on-error: true
env:
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
run: |
aws ecr describe-images \
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
--repository-name superset-ci \
--image-ids imageTag=pr-$PR_NUMBER-ci
- name: Fail on missing container image
if: steps.check-image.outcome == 'failure'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{ github.token }}
script: |
const errMsg = '@${{ github.event.comment.user.login }} Container image not yet published for this PR. Please try again when build is complete.';
github.rest.issues.createComment({
issue_number: ${{ github.event.inputs.issue_number || github.event.pull_request.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: errMsg
});
core.setFailed(errMsg);
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@77954e213ba1f9f9cb016b86a1d4f6fcdea0d57e # v1
with:
task-definition: .github/workflows/ecs-task-definition.json
container-name: superset-ci
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-ci
- name: Update env vars in the Amazon ECS task definition
run: |
cat <<< "$(jq '.containerDefinitions[0].environment += ${{ needs.ephemeral-env-label.outputs.feature-flags }}' < ${{ steps.task-def.outputs.task-definition }})" > ${{ steps.task-def.outputs.task-definition }}
- 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
- name: Create ECS service
id: create-service
if: steps.describe-services.outputs.active != 'true'
env:
ECR_SUBNETS: subnet-0e15a5034b4121710,subnet-0e8efef4a72224974
ECR_SECURITY_GROUP: sg-092ff3a6ae0574d91
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
run: |
aws ecs create-service \
--cluster superset-ci \
--service-name pr-$PR_NUMBER-service \
--task-definition superset-ci \
--launch-type FARGATE \
--desired-count 1 \
--platform-version LATEST \
--network-configuration "awsvpcConfiguration={subnets=[$ECR_SUBNETS],securityGroups=[$ECR_SECURITY_GROUP],assignPublicIp=ENABLED}" \
--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@cbf54ec46642b86ff78c2f5793da6746954cf8ff # v2
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service
cluster: superset-ci
wait-for-service-stability: true
wait-for-minutes: 10
- 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
- name: Get network interface
id: get-eni
run: |
echo "eni=$(aws ecs describe-tasks --cluster superset-ci --tasks ${{ steps.list-tasks.outputs.task }} | jq '.tasks[0].attachments[0].details | map(select(.name=="networkInterfaceId"))[0].value')" >> $GITHUB_OUTPUT
- name: Get public IP
id: get-ip
run: |
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@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{github.token}}
script: |
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
github.rest.issues.createComment({
issue_number: issue_number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `@${{ github.actor }} Ephemeral environment spinning up at http://${{ steps.get-ip.outputs.ip }}:8080. Credentials are 'admin'/'admin'. Please allow several minutes for bootstrapping and startup.`
});
- name: Comment (failure)
if: ${{ failure() }}
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{github.token}}
script: |
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
github.rest.issues.createComment({
issue_number: issue_number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '@${{ github.event.inputs.user_login || github.event.comment.user.login }} Ephemeral environment creation failed. Please check the Actions logs for details.'
})
+5 -10
View File
@@ -6,12 +6,9 @@ on:
- "master"
- "[0-9].[0-9]*"
permissions:
contents: read
jobs:
config:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
@@ -19,25 +16,23 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${FOSSA_API_KEY}" ]; then
if [ -n "${{ (secrets.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
name: Generate Report
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Setup Java
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: "temurin"
java-version: "11"
+7 -28
View File
@@ -6,44 +6,23 @@ on:
- "master"
- "[0-9].[0-9]*"
pull_request:
branches:
- "**"
permissions:
contents: read
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
types: [synchronize, opened, reopened, ready_for_review]
jobs:
validate-all-ghas:
runs-on: ubuntu-26.04
permissions:
contents: read
# Required for the zizmor action to upload its SARIF results to
# GitHub code scanning (advanced-security is enabled by default).
security-events: write
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: "20"
node-version: '20'
- name: Install Dependencies
# Versions are pinned to avoid ad-hoc, unpinned package installs.
# Bump deliberately when upgrading.
# zizmor: ignore[adhoc-packages] - @action-validator is a global CLI tool installed to validate the repo's workflows; a global CLI install has no application manifest/lockfile context, and the versions are pinned above
run: npm install -g @action-validator/core@0.6.0 @action-validator/cli@0.6.0
run: npm install -g @action-validator/core @action-validator/cli --save-dev
- name: Run Script
run: bash .github/workflows/github-action-validator.sh
- name: Check for security issues on GHA workflows
uses: zizmorcore/zizmor-action@3dc1ecc9bcb9e94e9b2c709687979e1298497054 # v0.6.2
-115
View File
@@ -1,115 +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.
name: Hold Label CI Gate
on:
pull_request:
types: [labeled, unlabeled]
permissions: {}
jobs:
cancel-on-hold:
name: Cancel CI runs when hold label applied
if: github.event.action == 'labeled' && startsWith(github.event.label.name, 'hold')
runs-on: ubuntu-26.04
permissions:
actions: write
pull-requests: read
steps:
- name: Cancel in-progress workflow runs
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { owner, repo } = context.repo;
const sha = context.payload.pull_request.head.sha;
const { data: { workflow_runs: runs } } =
await github.rest.actions.listWorkflowRunsForRepo({
owner,
repo,
head_sha: sha,
per_page: 100,
});
const active = runs.filter(r =>
['in_progress', 'queued', 'waiting', 'requested', 'pending'].includes(r.status)
);
core.info(`Found ${active.length} active run(s) to cancel for SHA ${sha}`);
for (const run of active) {
try {
await github.rest.actions.cancelWorkflowRun({
owner,
repo,
run_id: run.id,
});
core.info(`Cancelled run ${run.id} (${run.name})`);
} catch (err) {
core.warning(`Could not cancel run ${run.id}: ${err.message}`);
}
}
rerun-on-unhold:
name: Re-run CI when hold label removed
if: github.event.action == 'unlabeled' && startsWith(github.event.label.name, 'hold')
runs-on: ubuntu-24.04
permissions:
actions: write
pull-requests: read
steps:
- name: Re-trigger cancelled workflow runs
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { owner, repo } = context.repo;
const sha = context.payload.pull_request.head.sha;
// Check that no other hold* labels remain on the PR
const labels = context.payload.pull_request.labels.map(l => l.name);
const stillHeld = labels.some(l => l.startsWith('hold'));
if (stillHeld) {
core.info('PR still has a hold label — skipping re-run.');
return;
}
const { data: { workflow_runs: runs } } =
await github.rest.actions.listWorkflowRunsForRepo({
owner,
repo,
head_sha: sha,
per_page: 100,
});
const cancelled = runs.filter(r => r.conclusion === 'cancelled');
core.info(`Found ${cancelled.length} cancelled run(s) to re-trigger for SHA ${sha}`);
for (const run of cancelled) {
try {
await github.rest.actions.reRunWorkflow({
owner,
repo,
run_id: run.id,
});
core.info(`Re-triggered run ${run.id} (${run.name})`);
} catch (err) {
core.warning(`Could not re-run ${run.id}: ${err.message}`);
}
}
-33
View File
@@ -1,33 +0,0 @@
name: supersetbot orglabel based on author
on:
issues:
types: [opened, edited]
pull_request:
types: [opened, edited]
jobs:
superbot-orglabel:
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: write
issues: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup supersetbot
uses: ./.github/actions/setup-supersetbot/
- name: Execute supersetbot orglabel command
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Label the issue with the appropriate org using supersetbot
# - this requires for the author to be publicly associated with their org
# - and for the org to be listed in `supersetbot/src/metadata.js`
supersetbot orglabel --issue ${{ github.event.number || github.event.issue.number }} --repo ${{ github.repository }} || true
+34
View File
@@ -0,0 +1,34 @@
name: supersetbot orglabel based on author
on:
issues:
types: [created, edited]
pull_request:
types: [created, edited]
jobs:
superbot-orglabel:
runs-on: ubuntu-24.04
permissions:
contents: read
pull-requests: write
issues: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Setup supersetbot
uses: ./.github/actions/setup-supersetbot/
- name: Execute supersetbot orglabel command
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Label the issue with the appropriate org using supersetbot
# - this requires for the author to be publicly associated with their org
# - and for the org to be listed in `supersetbot/src/metadata.js`
supersetbot orglabel --issue ${{ github.event.number }} --repo ${{ github.repository }} || true
@@ -1,54 +0,0 @@
name: Label Merge Conflicts
# Sweeps every open PR and labels the ones GitHub reports as CONFLICTING with
# `requires:rebase` (removing it once a rebase makes the PR mergeable again),
# so the label can be used to filter the PR backlog for the ones that need a
# rebase before they can be reviewed/merged.
#
# The action itself always re-checks *every* open PR via GraphQL on each run
# regardless of what triggered it (see eps1lon/actions-label-merge-conflict's
# sources/main.ts) - there's no way to scope it to "just this PR". The
# project's own README suggests triggering on `push` (to the default branch)
# plus `pull_request_target: [synchronize]`, but on a repo with Superset's PR
# volume that combination would re-sweep the entire open-PR list on every
# merge to master *and* every push to *any* open PR - many times an hour.
# A schedule bounds that to a fixed, predictable cadence instead; adjust it
# if 2 hours turns out to be too slow or too chatty in practice.
on:
schedule:
- cron: "0 */2 * * *"
workflow_dispatch:
# Avoid two full backlog sweeps racing (a manual workflow_dispatch landing
# mid-schedule-tick, say); queue rather than cancel so an in-progress
# paginated sweep always runs to completion.
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions: {}
jobs:
label-merge-conflicts:
# Scheduled/dispatch workflows still run on forks that carry this file;
# skip anywhere but the canonical repo.
if: github.repository == 'apache/superset'
name: Label Merge Conflicts
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # to add/remove requires:rebase and need:merge
steps:
# ASF Infra allowlists this whole action via a wildcard
# (eps1lon/actions-label-merge-conflict@*), so any pinned SHA/version
# is already fine here - no Infra ticket needed for future bumps.
- uses: eps1lon/actions-label-merge-conflict@0273be72a0bbd58fcd71d0d6c02c209b50d1e5e1 # v3.1.0
with:
dirtyLabel: "requires:rebase"
# A conflicting PR isn't actually ready to merge; strip that signal
# if it was previously set so reviewers don't act on a stale one.
removeOnDirtyLabel: "need:merge"
repoToken: ${{ secrets.GITHUB_TOKEN }}
# Intentionally no commentOnDirty/commentOnClean: the label alone is
# the signal (matches the label's existing description, and avoids
# a one-time comment storm across the whole backlog on first run).
+2 -7
View File
@@ -2,19 +2,14 @@ name: "Pull Request Labeler"
on:
- pull_request_target
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
steps:
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
- uses: actions/labeler@v6
with:
sync-labels: true
+22 -24
View File
@@ -6,34 +6,32 @@ on:
jobs:
latest-release:
name: Add/update tag to new release
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
submodules: recursive
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Check for latest tag
id: latest-tag
env:
RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
run: |
source ./scripts/tag_latest_release.sh "$RELEASE_TAG_NAME" --dry-run
- name: Check for latest tag
id: latest-tag
run: |
source ./scripts/tag_latest_release.sh $(echo ${{ github.event.release.tag_name }}) --dry-run
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Run latest-tag
uses: ./.github/actions/latest-tag
if: steps.latest-tag.outputs.SKIP_TAG != 'true'
with:
description: Superset latest release
tag-name: latest
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Run latest-tag
uses: ./.github/actions/latest-tag
if: (! ${{ steps.latest-tag.outputs.SKIP_TAG }} )
with:
description: Superset latest release
tag-name: latest
env:
GITHUB_TOKEN: ${{ github.token }}
+5 -8
View File
@@ -4,9 +4,6 @@ on:
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
permissions:
contents: read
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
@@ -15,17 +12,17 @@ concurrency:
jobs:
license_check:
name: License Check
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Setup Java
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: "temurin"
java-version: "11"
distribution: 'temurin'
java-version: '11'
- name: Run license check
run: ./scripts/check_license.sh
-113
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.
#
# Mirror the Docker Hub service-container images that CI relies on into the
# repository's GitHub Container Registry (GHCR) namespace.
#
# WHY: CI jobs declare Postgres/MySQL/Redis/Presto as `services:` containers
# pulled anonymously from Docker Hub. Anonymous pulls share the runner's IP
# rate limit, which causes intermittent timeouts / 429s / 502s on `master`
# and same-repo PRs. The obvious fix — adding `credentials:` to the service
# blocks — breaks fork PRs hard: forks can't read secrets, so the templated
# username/password resolve to '' and GitHub rejects the workflow at parse
# time ("Unexpected value ''"), failing every fork job at "Set up job".
#
# Mirroring to GHCR sidesteps both problems: public GHCR images are pulled
# without Docker Hub's anonymous rate limit AND without any credentials, so
# the consuming workflows need no `credentials:` block and forks work
# unchanged.
#
# ONE-TIME BOOTSTRAP (maintainer, after this lands on the default branch):
# 1. Run this workflow once (Actions tab → "Mirror service images to GHCR"
# → Run workflow), or wait for the weekly schedule.
# 2. In the org's Packages settings, set each mirrored package's visibility
# to **public** (apache/superset → ci/postgres, ci/mysql, ci/redis,
# ci/presto). Public visibility is what lets fork CI pull without auth.
# 3. Only then merge the follow-up that repoints the `services.*.image`
# refs at these GHCR copies and drops the `credentials:` blocks.
#
# NOTE: this mirrors only the images declared as `services:` containers (the
# ones that broke forks). The `bde2020` hive-metastore image pulled via
# `docker compose` in the Presto/Hive job is a separate path and is left for
# a follow-up.
name: Mirror service images to GHCR
on:
schedule:
# Weekly, Monday 06:00 UTC — keeps the mirror fresh as upstream tags move.
- cron: "0 6 * * 1"
workflow_dispatch: {}
concurrency:
group: mirror-service-images
cancel-in-progress: false
permissions:
contents: read
packages: write
jobs:
mirror:
# Never run on forks: they lack both the secrets and write access to the
# apache GHCR namespace, so a scheduled run there would only ever fail.
if: github.repository == 'apache/superset'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Keep this list in sync with the `services.*.image` refs in
# superset-e2e.yml, superset-python-integrationtest.yml, and
# superset-python-presto-hive.yml.
image:
- postgres:17-alpine
- redis:7-alpine
- mysql:8.0
- starburstdata/presto:350-e.6
steps:
- name: Log in to Docker Hub (authenticated source pulls)
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GHCR (push target)
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Copy image to GHCR
env:
# Pass the matrix value through the environment rather than
# interpolating it into the shell, to avoid template injection.
SRC_IMAGE: ${{ matrix.image }}
run: |
set -euo pipefail
# Destination keeps the image's short name (drop any namespace),
# under a `ci/` prefix in this repo's GHCR namespace.
name="${SRC_IMAGE##*/}"
dst="ghcr.io/${GITHUB_REPOSITORY}/ci/${name}"
echo "Mirroring docker.io/${SRC_IMAGE} -> ${dst}"
# imagetools copies the full (multi-arch) manifest registry-to-
# registry without a local pull/retag/push round trip.
docker buildx imagetools create --tag "${dst}" "docker.io/${SRC_IMAGE}"
echo "- \`docker.io/${SRC_IMAGE}\` → \`${dst}\`" >> "${GITHUB_STEP_SUMMARY}"
+4 -7
View File
@@ -7,20 +7,17 @@ on:
permissions:
pull-requests: read
# Let each label event run to completion. Cancelling in-progress runs leaves
# CANCELLED entries in the PR's check-suite rollup, which poisons GitHub's
# `status:success` search filter even though all real CI passed. The job is
# a tiny no-op github-script call, so the wasted compute is negligible.
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: false
cancel-in-progress: true
jobs:
check-hold-label:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
steps:
- name: Check for 'hold' label
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
+4 -14
View File
@@ -8,26 +8,15 @@ on:
# Possible values: https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request
types: [opened, edited, reopened, synchronize]
# Serialize runs per PR without cancelling: the `edited` trigger means a PR
# opened and then edited has two queued runs for the same head SHA. On
# first-time-contributor PRs those runs start together when a maintainer
# approves workflows, and cancel-in-progress lets the older run cancel the
# newer one — leaving a permanently-cancelled required check on the head SHA
# that blocks merging until manually re-run. This job takes seconds, so let
# queued runs complete instead.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: false
jobs:
lint-check:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
permissions:
contents: read
pull-requests: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -37,5 +26,6 @@ jobs:
on-failed-regex-fail-action: true
on-failed-regex-request-changes: false
on-failed-regex-create-review: false
on-failed-regex-comment: "Please format your PR title to match: `%regex%`!"
on-failed-regex-comment:
"Please format your PR title to match: `%regex%`!"
repo-token: "${{ github.token }}"
+9 -120
View File
@@ -7,15 +7,9 @@ on:
- "[0-9].[0-9]*"
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
# Nightly full-tree sweep. Per-PR runs only lint changed files, so a change
# that invalidates an untouched file (e.g. a type change that breaks an
# importing test) can pass every PR yet leave master red. This catches that.
schedule:
- cron: "0 6 * * *"
permissions:
contents: read
actions: read
# cancel previous workflow jobs for PRs
concurrency:
@@ -24,23 +18,16 @@ concurrency:
jobs:
pre-commit:
runs-on: ubuntu-26.04
timeout-minutes: 20
runs-on: ubuntu-24.04
strategy:
matrix:
# Run the full version spread on push (master/release) and nightly,
# but only the current version on PRs — lint/format/type results
# rarely differ across patch versions, so 3x per PR is wasteful.
python-version: ${{ github.event_name == 'pull_request' && fromJSON('["current"]') || fromJSON('["current", "next"]') }}
python-version: ["current", "previous", "next"]
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
# Full history so we can diff a PR/push against its base commit to
# determine changed files (see "Determine changed files" below).
fetch-depth: 0
- name: Setup Python
uses: ./.github/actions/setup-backend/
@@ -48,17 +35,15 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
- name: Install helm-docs
run: go install github.com/norwoodj/helm-docs/cmd/helm-docs@v1.14.2
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: "superset-frontend/.nvmrc"
cache: "npm"
cache-dependency-path: "superset-frontend/package-lock.json"
node-version: '20'
- name: Install Frontend Dependencies
run: |
@@ -71,105 +56,18 @@ jobs:
yarn install --immutable
- name: Cache pre-commit environments
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: ~/.cache/pre-commit
key: pre-commit-v2-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: |
pre-commit-v2-${{ runner.os }}-py${{ matrix.python-version }}-
- name: Determine changed files
id: changed_files
env:
EVENT_NAME: ${{ github.event_name }}
BEFORE_SHA: ${{ github.event.before }}
run: |
set -euo pipefail
# Scheduled runs check the whole tree (see the pre-commit step).
if [ "${EVENT_NAME}" = "schedule" ]; then
echo "mode=all" >> "$GITHUB_OUTPUT"
exit 0
fi
# Resolve the commit to diff against.
base=""
if [ "${EVENT_NAME}" = "pull_request" ]; then
# HEAD is the PR merge commit, so its first parent is the current
# tip of the base branch. github.event.pull_request.base.sha is
# NOT that: GitHub freezes it at PR creation, so on a long-lived
# PR it points at the original branch point and the diff picks up
# all of the base branch's churn since then — thousands of paths,
# enough for the CHANGED_FILES env var below to exceed the
# kernel's per-variable size limit and kill the step with
# "Argument list too long" before bash even starts.
base="$(git rev-parse HEAD^1 2>/dev/null || true)"
elif [ -n "${BEFORE_SHA:-}" ] && \
[ "${BEFORE_SHA}" != "0000000000000000000000000000000000000000" ]; then
base="${BEFORE_SHA}"
fi
# Fail closed: if the diff base can't be resolved, check every file
# instead of silently checking nothing. Previously an empty file list
# made `pre-commit run --files` a no-op that still reported success,
# which let unlinted code reach master.
if [ -z "${base}" ] || ! git cat-file -e "${base}^{commit}" 2>/dev/null; then
echo "::notice::Could not resolve a diff base; falling back to --all-files."
echo "mode=all" >> "$GITHUB_OUTPUT"
exit 0
fi
# Files present in HEAD that changed since the base (drop deletions).
files="$(git diff --name-only --diff-filter=ACMRT "${base}...HEAD")"
# Env vars have a hard per-variable size limit (E2BIG at step
# start). A PR that legitimately touches thousands of files is
# better served by --all-files anyway.
if [ "$(printf '%s' "${files}" | wc -c)" -gt 100000 ]; then
echo "::notice::Changed-file list too large to pass via env; falling back to --all-files."
echo "mode=all" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ -z "${files}" ]; then
echo "mode=none" >> "$GITHUB_OUTPUT"
else
echo "mode=files" >> "$GITHUB_OUTPUT"
{
echo "files<<__CHANGED_FILES_EOF__"
echo "${files}"
echo "__CHANGED_FILES_EOF__"
} >> "$GITHUB_OUTPUT"
fi
- name: pre-commit
env:
MODE: ${{ steps.changed_files.outputs.mode }}
CHANGED_FILES: ${{ steps.changed_files.outputs.files }}
run: |
set +e # Don't exit immediately on failure
export SKIP=type-checking-frontend
case "${MODE}" in
all)
echo "️ Running pre-commit on all files."
pre-commit run --all-files
;;
files)
echo "️ Running pre-commit on changed files:"
echo "${CHANGED_FILES}"
# shellcheck disable=SC2086
pre-commit run --files ${CHANGED_FILES}
;;
none)
echo "️ No source files changed; nothing for pre-commit to check."
exit 0
;;
*)
echo "⚠️ Unrecognized changed-files mode '${MODE}'; checking all files."
pre-commit run --all-files
;;
esac
export SKIP=eslint-frontend,type-checking-frontend
pre-commit run --all-files
PRE_COMMIT_EXIT_CODE=$?
git diff --quiet --exit-code
GIT_DIFF_EXIT_CODE=$?
@@ -189,12 +87,3 @@ jobs:
echo "📖 More details here: https://superset.apache.org/docs/contributing/development#git-hooks"
exit 1
fi
actions-timeline:
needs: pre-commit
if: always()
runs-on: ubuntu-26.04
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+8 -16
View File
@@ -6,12 +6,9 @@ on:
- "master"
- "[0-9].[0-9]*"
permissions:
contents: read
jobs:
config:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
@@ -19,23 +16,18 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${NPM_TOKEN}" ]; then
if [ -n "${{ (secrets.NPM_TOKEN != '' && secrets.GH_PERSONAL_ACCESS_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-26.04
permissions:
contents: write
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
# pulls all commits (needed for lerna / semantic release to correctly version)
fetch-depth: 0
- name: Get tags and filter trigger tags
@@ -50,13 +42,13 @@ jobs:
- name: Install Node.js
if: env.HAS_TAGS
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: "./superset-frontend/.nvmrc"
node-version-file: './superset-frontend/.nvmrc'
- name: Cache npm
if: env.HAS_TAGS
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
@@ -70,7 +62,7 @@ jobs:
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- name: Cache npm
if: env.HAS_TAGS
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # 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 }}
@@ -1,187 +0,0 @@
name: Scheduled Docker image refresh
# Re-runs the Docker image build against the latest published release on a
# weekly cadence. The code being built doesn't change — but the base image
# layers (python:*-slim-trixie and its OS packages) DO get upstream
# security patches between Superset releases, and those patches don't
# reach our published images unless we rebuild.
#
# Without this workflow, `apache/superset:<latest>` lags behind upstream
# Debian/Python base patches by whatever interval falls between Superset
# releases (typically 36 weeks). With it, the lag drops to at most one
# week regardless of release cadence.
#
# This is a security-hygiene cron, not a release. It overwrites the
# existing tags for the most recent release (e.g. `apache/superset:5.0.0`
# and `apache/superset:latest`) with bit-for-bit-equivalent contents
# layered on a refreshed base. Image digests change; everything users
# actually pin against (image content, code, deps) does not.
on:
schedule:
# Mondays at 06:00 UTC — gives the weekend for upstream patches to
# settle and surfaces failures at the start of the work week so a
# human can react.
- cron: "0 6 * * 1"
# Manual trigger so operators can force a refresh on demand (e.g.
# immediately after a high-severity base-image CVE drops).
workflow_dispatch: {}
permissions:
contents: read
# Serialize with itself and with the release publisher (tag-release.yml) —
# both push to the same Docker Hub tags, so a race could end with stale
# layers winning. Both workflows must declare this group for the lock to work.
concurrency:
group: docker-publish-latest-release
cancel-in-progress: false
jobs:
config:
runs-on: ubuntu-26.04
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
latest-release: ${{ steps.latest.outputs.tag }}
force-latest: ${{ steps.latest.outputs.force-latest }}
steps:
- name: Check for Docker Hub secrets
id: check
shell: bash
run: |
if [ -n "${DOCKERHUB_USER}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
env:
DOCKERHUB_USER: ${{ (secrets.DOCKERHUB_USER != '' && secrets.DOCKERHUB_TOKEN != '') || '' }}
- name: Look up latest published release
id: latest
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPOSITORY: ${{ github.repository }}
run: |
# `releases/latest` returns the latest non-prerelease, non-draft
# release — which is exactly what `apache/superset:latest`
# should reflect.
TAG=$(gh api "repos/${REPOSITORY}/releases/latest" --jq .tag_name)
if [ -z "$TAG" ] || [ "$TAG" = "null" ]; then
echo "::error::Could not determine latest release tag"
exit 1
fi
echo "Latest release: $TAG"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
# Only move `:latest` when the release flagged "latest" is also the
# highest semver release. This guards against a mis-click leaving an
# older maintenance release (e.g. a 5.x patch shipped after 6.0 GA)
# marked latest, which would otherwise roll `:latest` back a major
# version on the next cron run. If it isn't the newest, we still
# refresh that release's own version tag but leave `:latest` alone.
HIGHEST=$(gh api --paginate "repos/${REPOSITORY}/releases" \
--jq '.[] | select(.draft|not) | select(.prerelease|not) | .tag_name' \
| sed 's/^v//' | sort -V | tail -n1)
if [ "${TAG#v}" = "$HIGHEST" ]; then
echo "force-latest=1" >> "$GITHUB_OUTPUT"
else
echo "::warning::Latest-flagged release $TAG is not the highest semver ($HIGHEST); refreshing its version tag but leaving :latest untouched"
fi
docker-rebuild:
needs: config
if: needs.config.outputs.has-secrets == '1'
name: docker-rebuild
runs-on: ubuntu-26.04
strategy:
# Mirror the same matrix the release publisher uses so every variant
# operators consume from Docker Hub gets the refreshed base.
matrix:
build_preset: ["dev", "lean", "websocket", "dockerize", "py311", "py312"]
fail-fast: false
steps:
- name: "Checkout release tag: ${{ needs.config.outputs.latest-release }}"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.config.outputs.latest-release }}
fetch-depth: 0
persist-credentials: false
# Keep workflow tooling on the triggering revision. Release tags can
# contain action pins that no longer satisfy the repository allowlist.
- name: Checkout workflow actions
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.sha }}
path: workflow-source
persist-credentials: false
sparse-checkout: .github/actions
- name: Setup Docker Environment
uses: ./workflow-source/.github/actions/setup-docker
with:
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
install-docker-compose: "false"
build: "true"
- name: Use Node.js 20
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 20
- name: Setup supersetbot
uses: ./workflow-source/.github/actions/setup-supersetbot/
- name: Rebuild and push
env:
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_PRESET: ${{ matrix.build_preset }}
LATEST_RELEASE: ${{ needs.config.outputs.latest-release }}
FORCE_LATEST_FLAG: ${{ needs.config.outputs.force-latest == '1' && '--force-latest' || '' }}
run: |
# Reuses the same supersetbot invocation as the release
# publisher (`tag-release.yml`), so the resulting tags are
# identical to what a manual release dispatch would produce —
# just with a freshly-pulled base image layer underneath.
# `--force-latest` is only passed when the config job confirmed the
# fetched release is the newest one (see FORCE_LATEST_FLAG above).
supersetbot docker \
--push \
--preset "$BUILD_PRESET" \
--context release \
--context-ref "$LATEST_RELEASE" \
$FORCE_LATEST_FLAG \
--platform "linux/arm64" \
--platform "linux/amd64"
# The whole point of this cron is catching base-image CVEs, so a silent
# failure is the expensive case — a red X in the Actions tab nobody is
# watching on a Monday. File a tracked issue when any rebuild leg fails so
# a missed security refresh surfaces instead of sitting unnoticed.
notify-on-failure:
needs: [config, docker-rebuild]
if: failure() && needs.config.outputs.has-secrets == '1'
runs-on: ubuntu-26.04
permissions:
contents: read
issues: write
steps:
- name: Open a tracking issue
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPOSITORY: ${{ github.repository }}
LATEST_RELEASE: ${{ needs.config.outputs.latest-release }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
gh issue create \
--repo "$REPOSITORY" \
--title "Scheduled Docker image refresh failed for ${LATEST_RELEASE}" \
--label "infra:container" \
--label "#bug" \
--body "The weekly Docker base-image refresh failed for release \`${LATEST_RELEASE}\`. Published images may be missing upstream base-layer security patches until this is resolved.
Failed run: ${RUN_URL}"
+3 -4
View File
@@ -24,14 +24,13 @@ jobs:
permissions:
contents: read
issues: write # delete orphaned showtime label definitions (label CRUD is the issues API)
pull-requests: write
steps:
- name: Install Superset Showtime
run: pip install superset-showtime
- name: Cleanup expired environments and orphaned labels
- name: Cleanup expired environments
run: |
echo "Cleaning up environments respecting TTL labels, and pruning orphaned 🎪 labels"
python -m showtime cleanup --respect-ttl --force
echo "Cleaning up environments respecting TTL labels"
python -m showtime cleanup --respect-ttl
+11 -23
View File
@@ -2,8 +2,6 @@ name: 🎪 Superset Showtime
# Ultra-simple: just sync on any PR state change
on:
# zizmor: ignore[dangerous-triggers] - required to react to PR label changes; PR code is
# only checked out and built after the maintainer-authorization gate (write/admin actors)
pull_request_target:
types: [labeled, unlabeled, synchronize, closed]
@@ -11,11 +9,11 @@ on:
workflow_dispatch:
inputs:
pr_number:
description: "PR number to sync"
description: 'PR number to sync'
required: true
type: number
sha:
description: "Specific SHA to deploy (optional, defaults to latest)"
description: 'Specific SHA to deploy (optional, defaults to latest)'
required: false
type: string
@@ -39,7 +37,7 @@ jobs:
steps:
- name: Security Check - Authorize Maintainers Only
id: auth
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
@@ -104,12 +102,10 @@ jobs:
- name: Install Superset Showtime
if: steps.auth.outputs.authorized == 'true'
run: |
echo "::notice::Maintainer $GITHUB_ACTOR triggered deploy for PR ${PULL_REQUEST_NUMBER}"
echo "::notice::Maintainer ${{ github.actor }} triggered deploy for PR ${{ github.event.pull_request.number || github.event.inputs.pr_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
@@ -117,14 +113,12 @@ 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 "${INPUT_PR_NUMBER}" ]]; then
PR_NUM="${INPUT_PR_NUMBER}"
elif [[ -n "${{ github.event.inputs.pr_number }}" ]]; then
PR_NUM="${{ github.event.inputs.pr_number }}"
else
echo "❌ No PR number found in event or inputs"
exit 1
@@ -133,8 +127,8 @@ jobs:
echo "Using PR number: $PR_NUM"
# Run sync check-only with optional SHA override
if [[ -n "${INPUT_SHA}" ]]; then
OUTPUT=$(python -m showtime sync $PR_NUM --check-only --sha "${INPUT_SHA}")
if [[ -n "${{ github.event.inputs.sha }}" ]]; then
OUTPUT=$(python -m showtime sync $PR_NUM --check-only --sha "${{ github.event.inputs.sha }}")
else
OUTPUT=$(python -m showtime sync $PR_NUM --check-only)
fi
@@ -153,14 +147,10 @@ jobs:
- name: Checkout PR code (only if build needed)
if: steps.auth.outputs.authorized == 'true' && steps.check.outputs.build_needed == 'true'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ steps.check.outputs.target_sha }}
persist-credentials: false
# Building fork PR code is Showtime's purpose: deploys are gated on the
# maintainer-authorization step above (write/admin actors only), so this
# checkout is an explicit, authorized opt-in rather than an automatic one.
allow-unsafe-pr-checkout: true
- name: Setup Docker Environment (only if build needed)
if: steps.auth.outputs.authorized == 'true' && steps.check.outputs.build_needed == 'true'
@@ -179,11 +169,9 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
CHECK_PR_NUMBER: ${{ steps.check.outputs.pr_number }}
CHECK_TARGET_SHA: ${{ steps.check.outputs.target_sha }}
run: |
PR_NUM="$CHECK_PR_NUMBER"
TARGET_SHA="$CHECK_TARGET_SHA"
PR_NUM="${{ steps.check.outputs.pr_number }}"
TARGET_SHA="${{ steps.check.outputs.target_sha }}"
if [[ -n "$TARGET_SHA" ]]; then
python -m showtime sync $PR_NUM --sha "$TARGET_SHA"
else
+3 -12
View File
@@ -8,11 +8,6 @@ on:
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
permissions:
contents: read
pull-requests: read
actions: read
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
@@ -20,7 +15,7 @@ concurrency:
jobs:
test-load-examples:
runs-on: ubuntu-26.04
runs-on: ubuntu-24.04
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -41,12 +36,8 @@ jobs:
ports:
- 16379:6379
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -66,7 +57,7 @@ jobs:
- name: superset init
if: steps.check.outputs.python
run: |
uv pip install --system -e .
pip install -e .
superset db upgrade
superset load_test_users
- name: superset load_examples
+9 -36
View File
@@ -2,7 +2,6 @@ name: Docs Deployment
on:
# Deploy after integration tests complete on master
# zizmor: ignore[dangerous-triggers] - runs in base-branch context after a trusted upstream workflow; scoped to master
workflow_run:
workflows: ["Python-Integration"]
types: [completed]
@@ -18,23 +17,9 @@ on:
workflow_dispatch: {}
# Serialize deploys: the action pushes to apache/superset-site without
# rebasing, so concurrent runs race on the final push and the loser fails
# with `! [rejected] asf-site -> asf-site (fetch first)`. Cancel any
# in-progress run as soon as a newer one starts — the destination repo
# isn't touched until the final push step, so canceling mid-build is safe,
# and the freshest content always wins.
concurrency:
group: docs-deploy-asf-site
cancel-in-progress: true
permissions:
contents: read
actions: read
jobs:
config:
runs-on: ubuntu-26.04
runs-on: ubuntu-24.04
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
@@ -42,41 +27,29 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${SUPERSET_SITE_BUILD}" ]; then
if [ -n "${{ (secrets.SUPERSET_SITE_BUILD != '' && secrets.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
# For workflow_run triggers, only deploy when the triggering run originated
# from this repository (not a fork), ensuring the checked-out code and any
# local actions executed with deploy credentials are trusted.
if: >-
needs.config.outputs.has-secrets &&
(github.event_name != 'workflow_run' ||
github.event.workflow_run.head_repository.full_name == github.repository)
if: needs.config.outputs.has-secrets
name: Build & Deploy
runs-on: ubuntu-26.04
runs-on: ubuntu-24.04
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout ${{ github.event.workflow_run.head_sha || github.sha }}"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
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@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: "./docs/.nvmrc"
- name: Setup Python
uses: ./.github/actions/setup-backend/
- uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: "zulu"
java-version: "21"
@@ -95,7 +68,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@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
uses: dawidd6/action-download-artifact@8a338493df3d275e4a7a63bcff3b8fe97e51a927 # v19
continue-on-error: true
with:
workflow: superset-python-integrationtest.yml
@@ -104,7 +77,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@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
uses: dawidd6/action-download-artifact@8a338493df3d275e4a7a63bcff3b8fe97e51a927 # v19
continue-on-error: true
with:
workflow: superset-python-integrationtest.yml
+40 -69
View File
@@ -7,7 +7,6 @@ on:
- "superset/db_engine_specs/**"
- ".github/workflows/superset-docs-verify.yml"
types: [synchronize, opened, reopened, ready_for_review]
# zizmor: ignore[dangerous-triggers] - runs in base-branch context and only consumes artifacts from the trusted upstream workflow
workflow_run:
workflows: ["Python-Integration"]
types: [completed]
@@ -17,95 +16,68 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.workflow_run.head_sha || github.run_id }}
cancel-in-progress: true
permissions:
contents: read
jobs:
lychee:
# See docs here: https://github.com/lycheeverse/lychee-action
linkinator:
# See docs here: https://github.com/marketplace/actions/linkinator
# Only run on pull_request, not workflow_run
if: github.event_name == 'pull_request'
name: Link Checking
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Restores the on-disk request cache (.lycheecache) lychee writes when
# `--cache` is set, so re-runs don't re-check every external link from
# scratch. Key never matches exactly (github.run_id is unique per run),
# so actions/cache always saves a fresh copy afterwards; restore-keys
# falls back to the most recent prior cache on lookup.
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .lycheecache
key: lychee-cache-${{ github.run_id }}
restore-keys: lychee-cache-
# v2.8.0 and v2.9.0 are both on ASF Infra's action allowlist
# (apache/infrastructure-actions approved_patterns.yml) as of this
# writing. Do not bump past v2.9.0 without opening an Infra ticket
# to allow the new SHA first!
- uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0
- 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
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
with:
fail: false
args: >-
--verbose --no-progress
--cache --max-cache-age 7d
--exclude '^https://github.com/apache/(superset|incubator-superset)/(pull|issues)/\d+'
--exclude '^https://github.com/apache/(superset|incubator-superset)/commit/[a-f0-9]+'
--exclude 'superset-frontend/.*CHANGELOG\.md'
--exclude 'http://localhost:8088/'
--exclude 'http://127.0.0.1:3000/'
--exclude 'http://localhost:9001/'
--exclude 'https://charts.bitnami.com/bitnami'
--exclude 'https://www.li.me/'
--exclude 'https://www.fanatics.com/'
--exclude 'https://tails.com/gb/'
--exclude 'https://www.techaudit.info/'
--exclude 'https://avetilearning.com/'
--exclude 'https://www.udemy.com/'
--exclude 'https://trustmedis.com/'
--exclude 'http://theiconic.com.au/'
--exclude 'https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html'
--exclude '^https://img\.shields\.io/.*'
--exclude 'https://vkusvill.ru/'
--exclude 'https://www.linkedin.com/in/mark-thomas-b16751158/'
--exclude 'https://theiconic.com.au/'
--exclude 'https://wattbewerb.de/'
--exclude 'https://timbr.ai/'
--exclude 'https://opensource.org/license/apache-2-0'
--exclude 'https://www.plaidcloud.com/'
'./**/*.md' './**/*.mdx'
paths: "**/*.md, **/*.mdx"
linksToSkip: >-
^https://github.com/apache/(superset|incubator-superset)/(pull|issues)/\d+,
^https://github.com/apache/(superset|incubator-superset)/commit/[a-f0-9]+,
superset-frontend/.*CHANGELOG\.md,
http://localhost:8088/,
http://127.0.0.1:3000/,
http://localhost:9001/,
https://charts.bitnami.com/bitnami,
https://www.li.me/,
https://www.fanatics.com/,
https://tails.com/gb/,
https://www.techaudit.info/,
https://avetilearning.com/,
https://www.udemy.com/,
https://trustmedis.com/,
http://theiconic.com.au/,
https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html,
^https://img\.shields\.io/.*,
https://vkusvill.ru/,
https://www.linkedin.com/in/mark-thomas-b16751158/,
https://theiconic.com.au/,
https://wattbewerb.de/,
https://timbr.ai/,
https://opensource.org/license/apache-2-0,
https://www.plaidcloud.com/
build-on-pr:
# Build docs when PR changes docs/** (uses committed databases.json)
if: github.event_name == 'pull_request'
name: Build (PR trigger)
runs-on: ubuntu-26.04
runs-on: ubuntu-24.04
defaults:
run:
working-directory: docs
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: "./docs/.nvmrc"
- name: yarn install
run: |
yarn install --check-cache
- name: Lint docs links
# Fast source-level check for bare relative internal links
# like `[Foo](../foo)` that Docusaurus's onBrokenLinks
# setting can't catch. Runs in seconds; fails fast before
# the expensive build step.
run: |
yarn lint:docs-links
- name: yarn typecheck
run: |
yarn typecheck
@@ -118,29 +90,28 @@ jobs:
# Only runs if integration tests succeeded
if: >
github.event_name == 'workflow_run' &&
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_repository.full_name == github.repository
github.event.workflow_run.conclusion == 'success'
name: Build (after integration tests)
runs-on: ubuntu-26.04
runs-on: ubuntu-24.04
defaults:
run:
working-directory: docs
steps:
- name: "Checkout PR head: ${{ github.event.workflow_run.head_sha }}"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
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@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # 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@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
uses: dawidd6/action-download-artifact@8a338493df3d275e4a7a63bcff3b8fe97e51a927 # v19
with:
workflow: superset-python-integrationtest.yml
run_id: ${{ github.event.workflow_run.id }}
+56 -148
View File
@@ -10,60 +10,39 @@ on:
workflow_dispatch:
inputs:
use_dashboard:
description: "Use Cypress Dashboard (true/false) [paid service - trigger manually when needed]. You MUST provide a branch and/or PR number below for this to work."
description: 'Use Cypress Dashboard (true/false) [paid service - trigger manually when needed]. You MUST provide a branch and/or PR number below for this to work.'
required: false
default: "false"
default: 'false'
ref:
description: "The branch or tag to checkout"
description: 'The branch or tag to checkout'
required: false
default: ""
default: ''
pr_id:
description: "The pull request ID to checkout"
description: 'The pull request ID to checkout'
required: false
default: ""
default: ''
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-26.04
timeout-minutes: 10
permissions:
contents: read
pull-requests: read
outputs:
python: ${{ steps.check.outputs.python }}
frontend: ${{ steps.check.outputs.frontend }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
cypress-matrix:
needs: changes
if: (needs.changes.outputs.python == 'true' || needs.changes.outputs.frontend == 'true') && github.event.pull_request.draft == false
runs-on: ubuntu-26.04
timeout-minutes: 30
# Somehow one test flakes on 24.04 for unknown reasons, this is the only GHA left on 22.04
runs-on: ubuntu-22.04
permissions:
contents: read
pull-requests: read
strategy:
# when one test fails, DO NOT cancel the other
# app_root variant, because this will kill Cypress processes
# parallel_id, because this will kill Cypress processes
# leaving the Dashboard hanging ...
# https://github.com/cypress-io/github-action/issues/48
fail-fast: false
matrix:
parallel_id: [0, 1, 2, 3, 4, 5]
browser: ["chrome"]
app_root: ${{ github.event_name == 'push' && fromJSON('["", "/app/prefix"]') || fromJSON('[""]') }}
app_root: ["", "/app/prefix"]
env:
SUPERSET_ENV: development
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -90,58 +69,71 @@ 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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
submodules: recursive
# -------------------------------------------------------
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: ./.github/actions/setup-backend/
if: steps.check.outputs.python || steps.check.outputs.frontend
- name: Setup postgres
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: setup-postgres
- name: Import test data
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: testdata
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: "./superset-frontend/.nvmrc"
cache: "npm"
cache-dependency-path: "superset-frontend/package-lock.json"
node-version-file: './superset-frontend/.nvmrc'
- name: Install npm dependencies
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: npm-install
- name: Build javascript packages
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: build-instrumented-assets
- name: Install cypress
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: cypress-install
- name: Run Cypress
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
env:
CYPRESS_BROWSER: ${{ matrix.browser }}
PARALLEL_ID: ${{ matrix.parallel_id }}
PARALLELISM: 6
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
NODE_OPTIONS: "--max-old-space-size=4096"
with:
@@ -149,23 +141,19 @@ jobs:
- name: Set safe app root
if: failure()
id: set-safe-app-root
env:
APP_ROOT: ${{ matrix.app_root }}
run: |
APP_ROOT="${{ matrix.app_root }}"
SAFE_APP_ROOT=${APP_ROOT//\//_}
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
- name: Upload Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
if: failure()
with:
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}-${{ matrix.parallel_id }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
playwright-tests:
needs: changes
if: needs.changes.outputs.python == 'true' || needs.changes.outputs.frontend == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 30
runs-on: ubuntu-22.04
permissions:
contents: read
pull-requests: read
@@ -173,7 +161,7 @@ jobs:
fail-fast: false
matrix:
browser: ["chromium"]
app_root: ${{ github.event_name == 'push' && fromJSON('["", "/app/prefix"]') || fromJSON('[""]') }}
app_root: ["", "/app/prefix"]
env:
SUPERSET_ENV: development
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -198,163 +186,83 @@ 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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
submodules: recursive
# -------------------------------------------------------
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: ./.github/actions/setup-backend/
if: steps.check.outputs.python || steps.check.outputs.frontend
- name: Setup postgres
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: setup-postgres
- name: Import test data
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: playwright_testdata
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: "./superset-frontend/.nvmrc"
cache: "npm"
cache-dependency-path: "superset-frontend/package-lock.json"
node-version-file: './superset-frontend/.nvmrc'
- name: Install npm dependencies
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: npm-install
- name: Build javascript packages
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: build-instrumented-assets
- name: Build embedded SDK
uses: ./.github/actions/cached-dependencies
with:
run: build-embedded-sdk
- name: Install Playwright
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: playwright-install
- name: Run Playwright (Required Tests)
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
env:
NODE_OPTIONS: "--max-old-space-size=4096"
with:
run: playwright-run "${{ matrix.app_root }}"
- name: Run Playwright (Soft-delete Tests)
uses: ./.github/actions/cached-dependencies
env:
NODE_OPTIONS: "--max-old-space-size=4096"
# Scoped to this step: each playwright-run boots its own gunicorn
# with the step's env, so the Required Tests server above keeps
# master's Flask configuration while this one runs with SOFT_DELETE
# on — the same isolation pattern as the Embedded step in
# superset-playwright.yml. Without a flag-on server the
# recently-archived specs skip themselves everywhere and ship zero
# executed E2E coverage; in the Required run above they are
# collected and skipped, which is expected.
SUPERSET_FEATURE_SOFT_DELETE: "true"
with:
run: playwright-run "${{ matrix.app_root }}" recently-archived/
- name: Set safe app root
if: failure()
id: set-safe-app-root
env:
APP_ROOT: ${{ matrix.app_root }}
run: |
APP_ROOT="${{ matrix.app_root }}"
SAFE_APP_ROOT=${APP_ROOT//\//_}
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
- name: Upload Playwright Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
if: failure()
with:
path: |
${{ github.workspace }}/superset-frontend/playwright-results/
${{ github.workspace }}/superset-frontend/test-results/
name: playwright-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
# Stable required-status-check anchors. cypress-matrix and playwright-tests
# are matrix jobs gated on change detection (python || frontend). On a PR
# that touches neither — e.g. a docs-only PR — they are skipped at the job
# level, which happens before matrix expansion, so the per-combination
# contexts (`cypress-matrix (0, chrome)`, `playwright-tests (chromium)`) are
# never produced and branch protection waits on them forever. These
# always-running jobs report a single stable context that passes when the
# underlying matrix job succeeded or was skipped, and fails only on a real
# failure. Require these in .asf.yaml instead of the matrix-expanded names.
#
# A matrix job reads as "skipped" in two distinct cases, and only the first
# is a legitimate pass: (a) change detection succeeded and gated the job off
# (docs-only PR); (b) the `changes` job itself failed or was cancelled, in
# which case GHA skips its dependents too. Accepting (b) would let a broken
# change-detector report a false green, so each anchor first requires
# `changes` to have succeeded before honouring a skip.
cypress-matrix-required:
needs: [changes, cypress-matrix]
if: always()
runs-on: ubuntu-26.04
timeout-minutes: 5
permissions: {}
steps:
- name: Check cypress-matrix result
env:
CHANGES: ${{ needs.changes.result }}
RESULT: ${{ needs.cypress-matrix.result }}
run: |
if [ "$CHANGES" != "success" ]; then
echo "change detection did not succeed (result: $CHANGES); refusing to pass on a skipped matrix"
exit 1
fi
if [ "$RESULT" != "success" ] && [ "$RESULT" != "skipped" ]; then
echo "cypress-matrix did not pass (result: $RESULT)"
exit 1
fi
echo "cypress-matrix result: $RESULT (changes: $CHANGES)"
playwright-tests-required:
needs: [changes, playwright-tests]
if: always()
runs-on: ubuntu-26.04
timeout-minutes: 5
permissions: {}
steps:
- name: Check playwright-tests result
env:
CHANGES: ${{ needs.changes.result }}
RESULT: ${{ needs.playwright-tests.result }}
run: |
if [ "$CHANGES" != "success" ]; then
echo "change detection did not succeed (result: $CHANGES); refusing to pass on a skipped matrix"
exit 1
fi
if [ "$RESULT" != "success" ] && [ "$RESULT" != "skipped" ]; then
echo "playwright-tests did not pass (result: $RESULT)"
exit 1
fi
echo "playwright-tests result: $RESULT (changes: $CHANGES)"
actions-timeline:
needs: [cypress-matrix, playwright-tests, cypress-matrix-required, playwright-tests-required]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+5 -22
View File
@@ -8,11 +8,6 @@ on:
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
permissions:
contents: read
pull-requests: read
actions: read
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
@@ -20,19 +15,16 @@ concurrency:
jobs:
test-superset-extensions-cli-package:
runs-on: ubuntu-26.04
timeout-minutes: 30
runs-on: ubuntu-24.04
strategy:
matrix:
# Full version spread on push (master/release) + nightly; current only
# on PRs to cut runner cost (cross-version breaks are caught at merge).
python-version: ${{ github.event_name == 'pull_request' && fromJSON('["current"]') || fromJSON('["current", "next"]') }}
python-version: ["previous", "current", "next"]
defaults:
run:
working-directory: superset-extensions-cli
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -57,7 +49,7 @@ jobs:
- name: Upload coverage reports to Codecov
if: steps.check.outputs.superset-extensions-cli
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
with:
file: ./coverage.xml
flags: superset-extensions-cli
@@ -66,16 +58,7 @@ jobs:
- name: Upload HTML coverage report
if: steps.check.outputs.superset-extensions-cli
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: superset-extensions-cli-coverage-html
path: htmlcov/
actions-timeline:
needs: test-superset-extensions-cli-package
if: always()
runs-on: ubuntu-26.04
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+33 -50
View File
@@ -16,24 +16,14 @@ concurrency:
env:
TAG: apache/superset:GHA-${{ github.run_id }}
permissions:
contents: read
jobs:
frontend-build:
runs-on: ubuntu-26.04
timeout-minutes: 30
# The change detector reads the PR's file list, which needs
# `pull-requests: read`. Public repos serve that endpoint without it;
# private forks return 403.
permissions:
contents: read
pull-requests: read
runs-on: ubuntu-24.04
outputs:
should-run: ${{ steps.check.outputs.frontend }}
steps:
- name: Checkout Code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 0
@@ -57,21 +47,21 @@ jobs:
git show -s --format=raw HEAD
docker buildx build \
-t $TAG \
--cache-from=type=registry,ref=apache/superset-cache:3.11-slim-trixie \
--cache-from=type=registry,ref=apache/superset-cache:3.10-slim-trixie \
--target superset-node-ci \
.
- name: Save Docker Image as Artifact
if: steps.check.outputs.frontend
run: |
docker save $TAG | zstd -3 --threads=0 > docker-image.tar.zst
docker save $TAG | gzip > docker-image.tar.gz
- name: Upload Docker Image Artifact
if: steps.check.outputs.frontend
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: docker-image
path: docker-image.tar.zst
path: docker-image.tar.gz
sharded-jest-tests:
needs: frontend-build
@@ -80,8 +70,7 @@ jobs:
matrix:
shard: [1, 2, 3, 4, 5, 6, 7, 8]
fail-fast: false
runs-on: ubuntu-26.04
timeout-minutes: 20
runs-on: ubuntu-24.04
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
@@ -89,8 +78,7 @@ jobs:
name: docker-image
- name: Load Docker Image
run: |
zstd -d < docker-image.tar.zst | docker load
run: docker load < docker-image.tar.gz
- name: npm run test with coverage
run: |
@@ -102,7 +90,7 @@ jobs:
"npm run test -- --coverage --shard=${{ matrix.shard }}/8 --coverageReporters=json"
- name: Upload Coverage Artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: coverage-artifacts-${{ matrix.shard }}
path: superset-frontend/coverage
@@ -110,13 +98,12 @@ jobs:
report-coverage:
needs: [sharded-jest-tests]
if: needs.frontend-build.outputs.should-run == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 15
runs-on: ubuntu-24.04
permissions:
id-token: write
steps:
- name: Checkout Code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 0
@@ -128,20 +115,31 @@ jobs:
pattern: coverage-artifacts-*
path: coverage/
- name: Reorganize test result reports
run: |
find coverage/
for i in {1..8}; do
mv coverage/coverage-artifacts-${i}/coverage-final.json coverage/coverage-shard-${i}.json
done
shell: bash
- name: Merge Code Coverage
run: npx nyc merge coverage/ merged-output/coverage-summary.json
- name: Upload Code Coverage
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
with:
flags: javascript
use_oidc: true
verbose: true
directory: coverage
disable_search: true
files: merged-output/coverage-summary.json
slug: apache/superset
lint-frontend:
needs: frontend-build
if: needs.frontend-build.outputs.should-run == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 20
runs-on: ubuntu-24.04
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
@@ -150,7 +148,7 @@ jobs:
- name: Load Docker Image
run: |
zstd -d < docker-image.tar.zst | docker load
docker load < docker-image.tar.gz
- name: lint
run: |
@@ -165,8 +163,7 @@ jobs:
validate-frontend:
needs: frontend-build
if: needs.frontend-build.outputs.should-run == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 20
runs-on: ubuntu-24.04
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
@@ -174,19 +171,17 @@ jobs:
name: docker-image
- name: Load Docker Image
run: |
zstd -d < docker-image.tar.zst | docker load
run: docker load < docker-image.tar.gz
- name: Validate dependency tree
- name: Build Plugins Packages
run: |
docker run --rm $TAG bash -c \
"npm ls --all --package-lock-only --depth=0 --json > /dev/null"
"npm run plugins:build"
test-storybook:
needs: frontend-build
if: needs.frontend-build.outputs.should-run == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 25
runs-on: ubuntu-24.04
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
@@ -194,21 +189,9 @@ jobs:
name: docker-image
- name: Load Docker Image
run: |
zstd -d < docker-image.tar.zst | docker load
run: docker load < docker-image.tar.gz
- name: Build Storybook and Run Tests
run: |
docker run --rm $TAG bash -c \
"npm run build-storybook && npx playwright install-deps && npx playwright install chromium && npm run test-storybook:ci"
actions-timeline:
needs: [report-coverage, lint-frontend, validate-frontend, test-storybook]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
@@ -1,77 +0,0 @@
name: "Helm: lint and test charts"
on:
pull_request:
types: [opened, reopened, synchronize]
paths:
- "helm/**"
permissions:
contents: read
actions: read
# Serialize runs per PR without cancelling: when a first-time contributor's
# queued runs are approved together, cancel-in-progress lets an older run
# cancel a newer one, leaving a permanently-cancelled required check on the
# head SHA. Queued runs are cheap here, so let them all complete.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: false
jobs:
lint-test:
runs-on: ubuntu-slim
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
submodules: recursive
fetch-depth: 0
- name: Set up Helm
uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
with:
version: v3.21.3
- name: Setup Python
uses: ./.github/actions/setup-backend/
with:
install-superset: "false"
# Still vendored (not de-vendored like chart-releaser-action below): the
# allowlisted helm/chart-testing-action@v2.8.0 depends internally on
# astral-sh/setup-uv@v7.0.0, which isn't itself on the ASF Actions
# allowlist (only v8.1.0+ are, at apache/infrastructure-actions'
# actions.yml). Needs an INFRA request before this can de-vendor too.
- name: Set up chart-testing
uses: ./.github/actions/chart-testing-action
- name: Run chart-testing (list-changed)
id: list-changed
run: |
changed=$(ct list-changed --print-config)
if [[ -n "$changed" ]]; then
echo "changed=true" >> $GITHUB_OUTPUT
fi
env:
CT_CHART_DIRS: helm
CT_SINCE: HEAD
- name: Run chart-testing (lint)
run: ct lint --print-config
env:
CT_CHART_DIRS: helm
CT_LINT_CONF: lintconf.yaml
CT_SINCE: HEAD
CT_CHART_REPOS: bitnami=https://charts.bitnami.com/bitnami
- name: Set up helm-unittest
run: helm plugin install https://github.com/helm-unittest/helm-unittest --version v1.1.1
- name: Run helm-unittest
run: helm unittest helm/superset
+55
View File
@@ -0,0 +1,55 @@
name: "Helm: lint and test charts"
on:
pull_request:
types: [opened, edited, reopened, synchronize]
paths:
- "helm/**"
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
lint-test:
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
fetch-depth: 0
- name: Set up Helm
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
with:
version: v3.16.4
- name: Setup Python
uses: ./.github/actions/setup-backend/
with:
install-superset: 'false'
- name: Set up chart-testing
uses: ./.github/actions/chart-testing-action
- name: Run chart-testing (list-changed)
id: list-changed
run: |
changed=$(ct list-changed --print-config)
if [[ -n "$changed" ]]; then
echo "changed=true" >> $GITHUB_OUTPUT
fi
env:
CT_CHART_DIRS: helm
CT_SINCE: HEAD
- name: Run chart-testing (lint)
run: ct lint --print-config
env:
CT_CHART_DIRS: helm
CT_LINT_CONF: lintconf.yaml
CT_SINCE: HEAD
CT_CHART_REPOS: bitnami=https://charts.bitnami.com/bitnami
+24 -92
View File
@@ -1,9 +1,6 @@
# This workflow automates the release process for Helm charts.
# Each run force-recreates a single 'helm-publish' branch from the tip of 'gh-pages' and
# opens (or reuses) one pull request against 'gh-pages', allowing the changes to be
# reviewed and merged manually. Because chart-releaser rebuilds index.yaml from all
# published GitHub releases, the branch always contains every chart released since the
# last merge, and the PR can never go stale or conflict with gh-pages.
# The workflow creates a new branch for the release and opens a pull request against the 'gh-pages' branch,
# allowing the changes to be reviewed and merged manually.
name: "Helm: release charts"
@@ -21,15 +18,9 @@ on:
required: false
default: "master"
# Serialize runs: concurrent runs would race on force-pushing the shared
# helm-publish branch while chart-releaser is mid-release.
concurrency:
group: helm-release
cancel-in-progress: false
jobs:
release:
runs-on: ubuntu-26.04
runs-on: ubuntu-24.04
permissions:
contents: write
pull-requests: write
@@ -38,7 +29,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ inputs.ref || github.ref_name }}
persist-credentials: true
@@ -51,7 +42,7 @@ jobs:
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
with:
version: v3.5.4
@@ -66,13 +57,11 @@ jobs:
echo "DEBUG TAGS"
git show-ref --tags
- name: Set pages branch name
- name: Create unique pages branch name
id: vars
run: echo "branch_name=helm-publish" >> $GITHUB_ENV
run: echo "branch_name=helm-publish-${GITHUB_SHA:0:7}" >> $GITHUB_ENV
- name: Force recreate branch from gh-pages
env:
BRANCH_NAME: ${{ env.branch_name }}
run: |
# Ensure a clean working directory
git reset --hard
@@ -84,110 +73,53 @@ jobs:
git fetch origin gh-pages
# Check out and reset the target branch based on gh-pages
git checkout -B "$BRANCH_NAME" origin/gh-pages
git checkout -B ${{ env.branch_name }} origin/gh-pages
# Remove submodules from the branch
git submodule deinit -f --all
# Force push to the remote branch
git push origin "$BRANCH_NAME" --force
git push origin ${{ env.branch_name }} --force
# Return to the original branch
git checkout local_gha_temp
- name: Fetch/list all tags
run: |
git submodule update
cat .github/actions/chart-releaser-action/action.yml
- name: Run chart-releaser
uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0
uses: ./.github/actions/chart-releaser-action
with:
version: v1.6.0
charts_dir: helm
mark_as_latest: false
# A helm/** change without a Chart.yaml version bump repackages the
# already-released version; without this, cr aborts on the existing
# release tag (422 already_exists) instead of proceeding to rebuild
# the index, and the whole run fails.
skip_existing: true
pages_branch: ${{ env.branch_name }}
env:
CR_TOKEN: "${{ github.token }}"
CR_RELEASE_NAME_TEMPLATE: "superset-helm-chart-{{ .Version }}"
- name: Open or reuse Pull Request
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
- name: Open Pull Request
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const branchName = process.env.BRANCH_NAME;
const branchName = '${{ env.branch_name }}';
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
if (!branchName) {
throw new Error("Branch name is not defined.");
}
// The branch is force-recreated from gh-pages on every run, so an
// already-open PR for it now reflects this run's charts; opening
// another would both fail (422) and recreate the stale-PR pileup
// this fixed branch exists to avoid.
const { data: existing } = await github.rest.pulls.list({
const pr = await github.rest.pulls.create({
owner,
repo,
state: "open",
head: `${owner}:${branchName}`,
base: "gh-pages",
title: `Helm chart release for ${branchName}`,
head: branchName,
base: "gh-pages", // Adjust if the target branch is different
body: `This PR releases Helm charts to the gh-pages branch.`,
});
let current;
if (existing.length > 0) {
current = existing[0];
core.info(`Reusing existing pull request: ${current.html_url}`);
} else {
const { data: pr } = await github.rest.pulls.create({
owner,
repo,
title: "Helm chart release",
head: branchName,
base: "gh-pages", // Adjust if the target branch is different
body: [
"This PR releases Helm charts to the gh-pages branch.",
"",
"It is force-updated from the tip of `gh-pages` by every release run,",
"so it always contains every chart released since the last merge and",
"never needs to be closed as superseded.",
].join("\n"),
});
current = pr;
core.info(`Pull request created: ${current.html_url}`);
}
// Sweep release PRs left open by older runs (per-SHA helm-publish-*
// branches from the previous scheme). Their content is a subset of
// the evergreen PR, so close them with a pointer to it.
const { data: openPrs } = await github.rest.pulls.list({
owner,
repo,
state: "open",
base: "gh-pages",
per_page: 100,
});
for (const stale of openPrs) {
if (
stale.number !== current.number &&
stale.head.repo?.full_name === process.env.GITHUB_REPOSITORY &&
stale.head.ref.startsWith("helm-publish")
) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: stale.number,
body: `Superseded by #${current.number}, which now carries all unreleased charts. Closing.`,
});
await github.rest.pulls.update({
owner,
repo,
pull_number: stale.number,
state: "closed",
});
core.info(`Closed superseded release PR #${stale.number}`);
}
}
core.info(`Pull request created: ${pr.data.html_url}`);
env:
BRANCH_NAME: ${{ env.branch_name }}
+24 -65
View File
@@ -10,46 +10,23 @@ on:
workflow_dispatch:
inputs:
ref:
description: "The branch or tag to checkout"
description: 'The branch or tag to checkout'
required: false
default: ""
default: ''
pr_id:
description: "The pull request ID to checkout"
description: 'The pull request ID to checkout'
required: false
default: ""
default: ''
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-26.04
timeout-minutes: 10
permissions:
contents: read
pull-requests: read
outputs:
python: ${{ steps.check.outputs.python }}
frontend: ${{ steps.check.outputs.frontend }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
# NOTE: Required Playwright tests are in superset-e2e.yml (E2E / playwright-tests)
# This workflow contains only experimental tests that run in shadow mode
playwright-tests-experimental:
needs: changes
if: needs.changes.outputs.python == 'true' || needs.changes.outputs.frontend == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 30
runs-on: ubuntu-22.04
continue-on-error: true
permissions:
contents: read
@@ -83,78 +60,71 @@ 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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
submodules: recursive
# -------------------------------------------------------
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: ./.github/actions/setup-backend/
if: steps.check.outputs.python || steps.check.outputs.frontend
- name: Setup postgres
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: setup-postgres
- name: Import test data
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: playwright_testdata
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: "./superset-frontend/.nvmrc"
cache: "npm"
cache-dependency-path: "superset-frontend/package-lock.json"
node-version-file: './superset-frontend/.nvmrc'
- name: Install npm dependencies
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: npm-install
- name: Build javascript packages
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: build-instrumented-assets
- name: Build embedded SDK
uses: ./.github/actions/cached-dependencies
with:
run: build-embedded-sdk
- name: Install Playwright
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: playwright-install
- name: Run Playwright (Experimental Tests)
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
env:
NODE_OPTIONS: "--max-old-space-size=4096"
with:
run: playwright-run "${{ matrix.app_root }}" experimental/
- name: Run Playwright (Embedded Tests)
uses: ./.github/actions/cached-dependencies
env:
NODE_OPTIONS: "--max-old-space-size=4096"
# Scope embedded-only env vars to this step. Setting them at the job
# level enabled the EMBEDDED_SUPERSET feature flag inside Flask for
# the preceding "Required Tests" and "Experimental Tests" steps too,
# which loads extra handlers and destabilizes the werkzeug dev
# server under the 2-worker Playwright load. Required Tests should
# match master's Flask configuration.
SUPERSET_FEATURE_EMBEDDED_SUPERSET: "true"
INCLUDE_EMBEDDED: "true"
with:
run: playwright-run "${{ matrix.app_root }}" embedded
- name: Set safe app root
if: failure()
id: set-safe-app-root
@@ -163,21 +133,10 @@ jobs:
SAFE_APP_ROOT=${APP_ROOT//\//_}
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
- name: Upload Playwright Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
if: failure()
with:
path: |
${{ github.workspace }}/superset-frontend/playwright-results/
${{ github.workspace }}/superset-frontend/test-results/
name: playwright-experimental-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
actions-timeline:
needs: playwright-tests-experimental
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
@@ -1,11 +1,6 @@
# Python integration tests
name: Python-Integration
# Least-privilege default for GITHUB_TOKEN. Jobs that need more (e.g. OIDC for
# codecov uploads) opt in via their own job-level `permissions:` block.
permissions:
contents: read
on:
push:
branches:
@@ -19,32 +14,8 @@ concurrency:
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-26.04
timeout-minutes: 10
permissions:
contents: read
pull-requests: read
outputs:
python: ${{ steps.check.outputs.python }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
test-mysql:
needs: changes
if: needs.changes.outputs.python == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 45
permissions:
id-token: write
runs-on: ubuntu-24.04
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -54,8 +25,6 @@ jobs:
services:
mysql:
image: mysql:8.0
# Authenticated pulls use our higher Docker Hub rate limit. Empty on
# fork PRs (secrets unavailable) -> runner falls back to anonymous.
env:
MYSQL_ROOT_PASSWORD: root
ports:
@@ -72,31 +41,40 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: ./.github/actions/setup-backend/
if: steps.check.outputs.python
- name: Setup MySQL
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: setup-mysql
- name: Start Celery worker
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: celery-worker
- name: Python integration tests (MySQL)
if: steps.check.outputs.python
run: |
./scripts/python_tests.sh
- name: Upload code coverage
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # 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:
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
SUPERSET__SQLALCHEMY_DATABASE_URI: |
@@ -119,23 +97,17 @@ jobs:
print(f'Generated diagnostics for {len(docs)} databases')
"
- name: Upload database diagnostics artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: steps.check.outputs.python
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: database-diagnostics
path: databases-diagnostics.json
retention-days: 7
test-postgres:
needs: changes
if: needs.changes.outputs.python == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 45
permissions:
id-token: write
runs-on: ubuntu-24.04
strategy:
matrix:
# Full version spread on push (master/release) + nightly; current only
# on PRs to cut runner cost (cross-version breaks are caught at merge).
python-version: ${{ github.event_name == 'pull_request' && fromJSON('["current"]') || fromJSON('["current", "next"]') }}
python-version: ["current", "previous", "next"]
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -157,41 +129,44 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: ./.github/actions/setup-backend/
if: steps.check.outputs.python
with:
python-version: ${{ matrix.python-version }}
- name: Setup Postgres
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: |
setup-postgres
- name: Start Celery worker
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: celery-worker
- name: Python integration tests (PostgreSQL)
if: steps.check.outputs.python
run: |
./scripts/python_tests.sh
- name: Upload code coverage
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
with:
flags: python,postgres
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset
test-sqlite:
needs: changes
if: needs.changes.outputs.python == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 45
permissions:
id-token: write
runs-on: ubuntu-24.04
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -207,62 +182,37 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: ./.github/actions/setup-backend/
if: steps.check.outputs.python
- name: Install dependencies
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: |
# sqlite needs this working directory
mkdir ${{ github.workspace }}/.temp
- name: Start Celery worker
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: celery-worker
- name: Python integration tests (SQLite)
if: steps.check.outputs.python
run: |
./scripts/python_tests.sh
- name: Upload code coverage
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
with:
flags: python,sqlite
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset
# Stable required-status-check anchor for the matrix-based test-postgres job.
# It is gated on change detection, so on non-Python PRs it is skipped and
# never produces its `test-postgres (current)` context (a job-level skip
# happens before matrix expansion). This always-running job reports a single
# context branch protection can require: it passes when test-postgres
# succeeded or was skipped, and fails only on a real failure.
test-postgres-required:
needs: [changes, test-postgres]
if: always()
runs-on: ubuntu-26.04
timeout-minutes: 5
steps:
- name: Check test-postgres result
env:
RESULT: ${{ needs.test-postgres.result }}
run: |
if [ "$RESULT" != "success" ] && [ "$RESULT" != "skipped" ]; then
echo "test-postgres did not pass (result: $RESULT)"
exit 1
fi
echo "test-postgres result: $RESULT"
actions-timeline:
needs: [test-mysql, test-postgres, test-sqlite, test-postgres-required]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
@@ -15,32 +15,8 @@ concurrency:
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-26.04
timeout-minutes: 10
permissions:
contents: read
pull-requests: read
outputs:
python: ${{ steps.check.outputs.python }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
test-postgres-presto:
needs: changes
if: needs.changes.outputs.python == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 45
permissions:
id-token: write
runs-on: ubuntu-24.04
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -72,38 +48,43 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: ./.github/actions/setup-backend/
if: steps.check.outputs.python == 'true'
- name: Setup Postgres
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: setup-postgres
run: |
echo "${{ steps.check.outputs.python }}"
setup-postgres
- name: Start Celery worker
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: celery-worker
- name: Python unit tests (PostgreSQL)
if: steps.check.outputs.python
run: |
./scripts/python_tests.sh -m 'chart_data_flow or sql_json_flow'
- name: Upload code coverage
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
with:
flags: python,presto
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset
test-postgres-hive:
needs: changes
if: needs.changes.outputs.python == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 45
permissions:
id-token: write
runs-on: ubuntu-24.04
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -127,45 +108,45 @@ jobs:
- 16379:6379
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Create csv upload directory
if: steps.check.outputs.python
run: sudo mkdir -p /tmp/.superset/uploads
- name: Give write access to the csv upload directory
if: steps.check.outputs.python
run: sudo chown -R $USER:$USER /tmp/.superset
- name: Start hadoop and hive
if: steps.check.outputs.python
run: docker compose -f scripts/databases/hive/docker-compose.yml up -d
- name: Setup Python
uses: ./.github/actions/setup-backend/
if: steps.check.outputs.python
- name: Setup Postgres
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: setup-postgres
- name: Start Celery worker
if: steps.check.outputs.python
uses: ./.github/actions/cached-dependencies
with:
run: celery-worker
- name: Python unit tests (PostgreSQL)
if: steps.check.outputs.python
run: |
uv pip install --system -e .[hive]
pip install -e .[hive]
./scripts/python_tests.sh -m 'chart_data_flow or sql_json_flow'
- name: Upload code coverage
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
with:
flags: python,hive
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset
actions-timeline:
needs: [test-postgres-presto, test-postgres-hive]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+15 -75
View File
@@ -1,11 +1,6 @@
# Python unit tests
name: Python-Unit
# Least-privilege default for GITHUB_TOKEN. Jobs that need more (e.g. OIDC for
# codecov uploads) opt in via their own job-level `permissions:` block.
permissions:
contents: read
on:
push:
branches:
@@ -20,101 +15,46 @@ concurrency:
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-26.04
timeout-minutes: 10
permissions:
contents: read
pull-requests: read
outputs:
python: ${{ steps.check.outputs.python }}
unit-tests:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["previous", "current", "next"]
env:
PYTHONPATH: ${{ github.workspace }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
unit-tests:
needs: changes
if: needs.changes.outputs.python == 'true'
runs-on: ubuntu-26.04
timeout-minutes: 30
permissions:
id-token: write
strategy:
matrix:
# Full version spread on push (master/release) + nightly; current only
# on PRs to cut runner cost (cross-version breaks are caught at merge).
python-version: ${{ github.event_name == 'pull_request' && fromJSON('["current"]') || fromJSON('["current", "next"]') }}
env:
PYTHONPATH: ${{ github.workspace }}
# Promotes the SQLAlchemy 2.0 deprecation warnings already locked in as
# errors via pytest.ini's `filterwarnings` to actually run in CI, so a
# regression on those fails the build instead of relying on a
# contributor remembering to set this locally. See the migration
# battleplan: https://github.com/apache/superset/discussions/40273
SQLALCHEMY_WARN_20: "1"
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
submodules: recursive
- name: Setup Python
uses: ./.github/actions/setup-backend/
if: steps.check.outputs.python
with:
python-version: ${{ matrix.python-version }}
- name: Python unit tests
if: steps.check.outputs.python
env:
SUPERSET_TESTENV: true
SUPERSET_SECRET_KEY: not-a-secret
run: |
pytest --durations-min=0.5 --cov-report= --cov=superset ./tests/common ./tests/unit_tests --cache-clear --maxfail=50
- name: Python 100% coverage unit tests
if: steps.check.outputs.python
env:
SUPERSET_TESTENV: true
SUPERSET_SECRET_KEY: not-a-secret
run: |
pytest --durations-min=0.5 --cov=superset/sql/ ./tests/unit_tests/sql/ --cache-clear --cov-fail-under=100
pytest --durations-min=0.5 --cov=superset/semantic_layers/ ./tests/unit_tests/semantic_layers/ --cache-clear --cov-fail-under=100
- name: Upload code coverage
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
with:
flags: python,unit
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
use_oidc: true
slug: apache/superset
# Stable required-status-check anchor. `unit-tests` is a matrix job gated on
# change detection, so on non-Python PRs it is skipped and never produces its
# `unit-tests (current)` context (a job-level skip happens before matrix
# expansion). This always-running job reports a single context that branch
# protection can require: it passes when unit-tests succeeded or was skipped,
# and fails only on a real failure.
unit-tests-required:
needs: [changes, unit-tests]
if: always()
runs-on: ubuntu-26.04
timeout-minutes: 5
permissions:
contents: read
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: Check unit-tests result
env:
RESULT: ${{ needs.unit-tests.result }}
run: |
if [ "$RESULT" != "success" ] && [ "$RESULT" != "skipped" ]; then
echo "unit-tests did not pass (result: $RESULT)"
exit 1
fi
echo "unit-tests result: $RESULT"
@@ -1,88 +0,0 @@
name: Translation Regression Comment
on:
# zizmor: ignore[dangerous-triggers] - runs in base-branch context and only consumes the uploaded artifact; never checks out PR code (see note below)
workflow_run:
workflows: ["Translations"]
types: [completed]
# This workflow posts a PR comment when the Translations workflow detects a
# regression. It uses the workflow_run trigger so that it always runs in the
# base-branch context and can safely be granted write permissions, even for
# PRs from forks.
#
# IMPORTANT: This workflow must NEVER check out code from the PR branch.
# All data comes from the artifact uploaded by the Translations workflow.
permissions:
pull-requests: write
actions: read
jobs:
post-comment:
runs-on: ubuntu-26.04
# Only act when the Translations workflow failed (which means a regression
# was detected — the workflow exits 1 on regression).
if: github.event.workflow_run.conclusion == 'failure'
steps:
- name: Download regression artifact
id: download
continue-on-error: true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: translation-regression
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
path: /tmp/translation-regression
- name: Post or update PR comment
if: steps.download.outcome == 'success'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const fs = require('fs');
const prNumberFile = '/tmp/translation-regression/pr-number.txt';
const reportFile = '/tmp/translation-regression/regression-report.md';
if (!fs.existsSync(prNumberFile) || !fs.existsSync(reportFile)) {
console.log('Artifact files not found, skipping comment.');
return;
}
const prNumber = parseInt(fs.readFileSync(prNumberFile, 'utf8').trim(), 10);
if (!prNumber) {
console.log('Could not parse PR number, skipping comment.');
return;
}
const report = fs.readFileSync(reportFile, 'utf8');
const marker = '<!-- translation-regression-bot -->';
const body = `${marker}\n${report}`;
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const existing = comments.find(c => c.body && c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
console.log(`Updated existing comment ${existing.id} on PR #${prNumber}`);
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
console.log(`Created new comment on PR #${prNumber}`);
}
+11 -106
View File
@@ -8,10 +8,6 @@ on:
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
permissions:
contents: read
pull-requests: read
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
@@ -19,13 +15,10 @@ concurrency:
jobs:
frontend-check-translations:
runs-on: ubuntu-26.04
permissions:
contents: read
pull-requests: read
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
@@ -38,11 +31,9 @@ jobs:
- name: Setup Node.js
if: steps.check.outputs.frontend
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: "./superset-frontend/.nvmrc"
cache: "npm"
cache-dependency-path: "superset-frontend/package-lock.json"
node-version-file: './superset-frontend/.nvmrc'
- name: Install dependencies
if: steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
@@ -55,17 +46,13 @@ jobs:
npm run build-translation
babel-extract:
runs-on: ubuntu-26.04
permissions:
contents: read
pull-requests: read
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
submodules: recursive
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
@@ -73,94 +60,12 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
if: steps.check.outputs.python == 'true' || steps.check.outputs.frontend == 'true'
if: steps.check.outputs.python
uses: ./.github/actions/setup-backend/
- name: Install gettext tools
if: steps.check.outputs.python == 'true' || steps.check.outputs.frontend == 'true'
run: sudo apt-get update && sudo apt-get install -y gettext
- name: Install msgcat
run: sudo apt update && sudo apt install gettext
# Fetch the base ref so we can compare PR-introduced regressions
# against a fair baseline (also runs babel_update against the base
# source) — this isolates the PR's contribution from any pre-existing
# drift on the base branch.
- name: Fetch base ref and create comparison worktree
if: steps.check.outputs.python == 'true' || steps.check.outputs.frontend == 'true'
env:
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
# For PRs use the base branch; for direct pushes compare against the previous commit.
BASE_REF="$PR_BASE_REF"
if [ -n "$BASE_REF" ]; then
git fetch --depth=1 origin "$BASE_REF"
else
git fetch --depth=2 origin "$GITHUB_REF"
fi
git worktree add /tmp/base-worktree FETCH_HEAD
# Run babel_update against BASE source + BASE translations. Any drift
# already present on the base branch (source strings that have changed
# without .po updates) shows up here as fuzzies — and will also show
# up in the PR run, so it cancels out in the comparison.
- name: Baseline — run babel_update against BASE source
if: steps.check.outputs.python == 'true' || steps.check.outputs.frontend == 'true'
working-directory: /tmp/base-worktree
- name: Test babel extraction
if: steps.check.outputs.python
run: ./scripts/translations/babel_update.sh
- name: Record baseline translation counts
if: steps.check.outputs.python == 'true' || steps.check.outputs.frontend == 'true'
run: |
python scripts/translations/check_translation_regression.py \
--count \
--translations-dir /tmp/base-worktree/superset/translations \
> /tmp/before.json
# Run babel_update against the PR source and PR translations. This keeps
# committed .po fixes in play while the base babel_update above still
# cancels out translation drift already present on the base branch.
- name: Run babel_update against PR source
if: steps.check.outputs.python == 'true' || steps.check.outputs.frontend == 'true'
run: ./scripts/translations/babel_update.sh
- name: Check for translation regression
id: regression
if: steps.check.outputs.python == 'true' || steps.check.outputs.frontend == 'true'
continue-on-error: true
run: |
python scripts/translations/check_translation_regression.py \
--compare /tmp/before.json \
--report /tmp/regression-report.md
# Save the PR number so the comment workflow can post the report without
# needing write permissions on this pull_request-triggered job.
- name: Save PR number for comment workflow
if: >-
github.event_name == 'pull_request' &&
steps.regression.outcome == 'failure'
run: echo "${{ github.event.pull_request.number }}" > /tmp/pr-number.txt
- name: Upload regression artifact
if: >-
github.event_name == 'pull_request' &&
steps.regression.outcome == 'failure'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: translation-regression
path: |
/tmp/regression-report.md
/tmp/pr-number.txt
- name: Fail if regression detected
if: steps.regression.outcome == 'failure'
run: exit 1
actions-timeline:
needs: [frontend-check-translations, babel-extract]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+4 -12
View File
@@ -11,9 +11,6 @@ on:
- "superset-websocket/**"
types: [synchronize, opened, reopened, ready_for_review]
permissions:
contents: read
# cancel previous workflow jobs for PRs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
@@ -21,17 +18,12 @@ concurrency:
jobs:
app-checks:
runs-on: ubuntu-slim
timeout-minutes: 20
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: './superset-websocket/.nvmrc'
- name: Install dependencies
working-directory: ./superset-websocket
run: npm ci
@@ -41,9 +33,9 @@ jobs:
- name: typescript checks
working-directory: ./superset-websocket
run: npm run type
- name: code format check
- name: prettier
working-directory: ./superset-websocket
run: npm run format-check
run: npm run prettier-check
- name: unit tests
working-directory: ./superset-websocket
run: npm run test
+4 -4
View File
@@ -9,13 +9,13 @@ on:
workflow_dispatch:
inputs:
comment_body:
description: "Comment Body"
description: 'Comment Body'
required: true
type: string
jobs:
supersetbot:
runs-on: ubuntu-26.04
runs-on: ubuntu-24.04
if: >
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@supersetbot'))
@@ -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@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
@@ -38,7 +38,7 @@ jobs:
});
- name: "Checkout ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
@@ -1,60 +0,0 @@
name: Sync requirements for Python dependency PRs
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: write
pull-requests: read
jobs:
sync-python-dep-requirements:
# This action is limited for (1) PRs authored by Dependabot and (2) upstream repo due to write back to remote
if: github.repository == 'apache/superset' && github.event.pull_request.user.login == 'dependabot[bot]' && github.event.pull_request.head.repo.fork == false
runs-on: ubuntu-26.04
steps:
- name: Fetch Dependabot metadata
id: dependabot-metadata
shell: bash
env:
BRANCH_NAME: ${{ github.head_ref }}
run: |
# Get current branch name, extract the package ecosystem and return as GHA step output
packageEcosystem=$(echo "$BRANCH_NAME" | cut -d'/' -f2)
echo "package-ecosystem=$packageEcosystem" >> $GITHUB_OUTPUT
# zizmor: ignore[artipacked] - required persisted credentials to push synced requirement changes back to remote
- name: Checkout source code
if: ${{ steps.dependabot-metadata.outputs.package-ecosystem == 'pip' }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: true
# Authenticate the Docker daemon so the python:slim pull in
# uv-pip-compile.sh uses our (much higher) authenticated rate limit
# instead of the shared-runner anonymous one.
- name: Login to Docker Hub
if: ${{ steps.dependabot-metadata.outputs.package-ecosystem == 'pip' }}
continue-on-error: true
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Sync requirements in containerized environment
if: ${{ steps.dependabot-metadata.outputs.package-ecosystem == 'pip' }}
run: ./scripts/uv-pip-compile.sh
- name: Push changes to remote PRs
if: ${{ steps.dependabot-metadata.outputs.package-ecosystem == 'pip' }}
run: |
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
git add requirements
git diff --cached --quiet && exit 0
git commit --signoff --message "build(deps): sync pinned requirements for Dependabot pip PRs"
git push origin "HEAD:refs/heads/${GITHUB_EVENT_PULL_REQUEST_HEAD_REF}"
env:
GITHUB_EVENT_PULL_REQUEST_HEAD_REF: ${{ github.event.pull_request.head.ref }}
+20 -44
View File
@@ -16,23 +16,14 @@ on:
force-latest:
required: true
type: choice
default: "false"
default: 'false'
description: Whether to force a latest tag on the release
options:
- "true"
- "false"
permissions:
contents: read
# Serialize with the scheduled Docker image refresh — both workflows push
# to the same Docker Hub tags and must not race on apache/superset:latest.
concurrency:
group: docker-publish-latest-release
cancel-in-progress: false
- 'true'
- 'false'
jobs:
config:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
@@ -40,29 +31,24 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${DOCKERHUB_USER}" ]; then
if [ -n "${{ (secrets.DOCKERHUB_USER != '' && secrets.DOCKERHUB_TOKEN != '') || '' }}" ]; 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
name: docker-release
runs-on: ubuntu-26.04
permissions:
contents: write
runs-on: ubuntu-24.04
strategy:
matrix:
build_preset:
["dev", "lean", "websocket", "dockerize", "py311", "py312"]
build_preset: ["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"]
fail-fast: false
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 0
- name: Setup Docker Environment
@@ -74,11 +60,9 @@ jobs:
build: "true"
- name: Use Node.js 20
# zizmor: ignore[cache-poisoning] - node only runs the supersetbot CLI; no dependency cache is enabled
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: 20
package-manager-cache: false
- name: Setup supersetbot
uses: ./.github/actions/setup-supersetbot/
@@ -88,21 +72,17 @@ 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 }}
GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
run: |
RELEASE="${GITHUB_EVENT_RELEASE_TAG_NAME}"
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="${INPUT_RELEASE}"
if [ "${INPUT_FORCE_LATEST}" = "true" ]; then
RELEASE="${{ github.event.inputs.release }}"
if [ "${{ github.event.inputs.force-latest }}" = "true" ]; then
FORCE_LATEST="--force-latest"
fi
git checkout "${INPUT_GIT_REF}"
git checkout "${{ github.event.inputs.git-ref }}"
EVENT="release"
fi
@@ -120,23 +100,21 @@ jobs:
update-prs-with-release-info:
needs: config
if: needs.config.outputs.has-secrets
runs-on: ubuntu-26.04
runs-on: ubuntu-24.04
permissions:
contents: read
pull-requests: write
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 0
- name: Use Node.js 20
# zizmor: ignore[cache-poisoning] - node only runs the supersetbot CLI; no dependency cache is enabled
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: 20
package-manager-cache: false
- name: Setup supersetbot
uses: ./.github/actions/setup-supersetbot/
@@ -144,15 +122,13 @@ jobs:
- name: Label the PRs with the right release-related labels
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INPUT_RELEASE: ${{ github.event.inputs.release }}
GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
run: |
export GITHUB_ACTOR=""
git fetch --all --tags
git checkout master
RELEASE="${GITHUB_EVENT_RELEASE_TAG_NAME}"
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="${INPUT_RELEASE}"
RELEASE="${{ github.event.inputs.release }}"
fi
supersetbot release-label $RELEASE
+6 -10
View File
@@ -11,7 +11,7 @@ permissions:
jobs:
config:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
@@ -19,27 +19,23 @@ jobs:
id: check
shell: bash
run: |
if [ -n "${GSHEET_KEY}" ]; then
if [ -n "${{ (secrets.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
runs-on: ubuntu-slim
runs-on: ubuntu-24.04
name: Generate Reports
steps:
- name: Checkout Repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: "./superset-frontend/.nvmrc"
node-version-file: './superset-frontend/.nvmrc'
- name: Install Dependencies
run: npm ci
+5 -12
View File
@@ -1,29 +1,22 @@
name: Welcome New Contributor
on:
# zizmor: ignore[dangerous-triggers] - posts a welcome comment only; does not check out or execute PR-provided code
pull_request_target:
types: [opened]
jobs:
welcome:
runs-on: ubuntu-slim
if: github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
runs-on: ubuntu-24.04
permissions:
pull-requests: write
steps:
- name: Welcome Message
uses: actions/first-interaction@1c4688942c71f71d4f5502a26ea67c331730fa4d # v3.1.0
uses: actions/first-interaction@v3
continue-on-error: true
with:
repo_token: ${{ github.token }}
issue_message: |-
Congrats on opening your first issue and thank you for contributing to Superset! :tada: :heart:
Please read our [New Contributor Welcome & Expectations](https://github.com/apache/superset/wiki/New-Contributor-Welcome-&-Expectations) guide.
pr_message: |-
repo-token: ${{ github.token }}
pr-message: |-
Congrats on making your first PR and thank you for contributing to Superset! :tada: :heart:
Please read our [New Contributor Welcome & Expectations](https://github.com/apache/superset/wiki/New-Contributor-Welcome-&-Expectations) guide.
We hope to see you in our [Slack](https://apache-superset.slack.com/) community too! Not signed up? Use our [Slack App](http://bit.ly/join-superset-slack) to self-register.
-5
View File
@@ -57,13 +57,11 @@ local_config.py
/superset_text.yml
superset.egg-info/
superset/bin/supersetc
superset/extensions/.reload_trigger
tmp
rat-results.txt
superset/app/
superset-websocket/config.json
.direnv
*.log
# Node.js, webpack artifacts, storybook
*.entry.js
@@ -116,8 +114,6 @@ release.json
superset/translations/**/messages.json
# these mo binary files are generated by `pybabel compile`
superset/translations/**/messages.mo
# cross-language index generated by scripts/translations/build_translation_index.py
superset/translations/translation_index.json
docker/requirements-local.txt
@@ -138,7 +134,6 @@ PROJECT.md
.aider*
.claude_rc*
.claude/settings.local.json
.claude/worktrees/
.env.local
oxc-custom-build/
*.code-workspace
+6
View File
@@ -21,6 +21,9 @@
[submodule ".github/actions/pr-lint-action"]
path = .github/actions/pr-lint-action
url = https://github.com/morrisoncole/pr-lint-action
[submodule ".github/actions/file-changes-action"]
path = .github/actions/file-changes-action
url = https://github.com/trilom/file-changes-action
[submodule ".github/actions/cached-dependencies"]
path = .github/actions/cached-dependencies
url = https://github.com/apache-superset/cached-dependencies
@@ -30,6 +33,9 @@
[submodule ".github/actions/chart-testing-action"]
path = .github/actions/chart-testing-action
url = https://github.com/helm/chart-testing-action
[submodule ".github/actions/chart-releaser-action"]
path = .github/actions/chart-releaser-action
url = https://github.com/helm/chart-releaser-action
[submodule ".github/actions/github-action-push-to-another-repository"]
path = .github/actions/github-action-push-to-another-repository
url = https://github.com/cpina/github-action-push-to-another-repository
Executable → Regular
+8 -26
View File
@@ -31,10 +31,9 @@ repos:
types-simplejson,
types-python-dateutil,
types-requests,
# types-redis is intentionally absent: redis-py ships its own
# bundled types (py.typed, since 4.6+/5.x), while the stub
# package is unmaintained (frozen at the 4.6.0.x API surface).
# Installing the stub would shadow the accurate inline types.
# types-redis 4.6.0.5 is failing mypy
# because of https://github.com/python/typeshed/pull/10531
types-redis==4.6.0.4,
types-pytz,
types-croniter,
types-PyYAML,
@@ -51,7 +50,7 @@ repos:
hooks:
- id: check-docstring-first
- id: check-added-large-files
exclude: ^.*\.(geojson)$|^docs/static/img/screenshots/.*|^superset-frontend/CHANGELOG\.md$|^superset/examples/.*/data\.parquet$|^superset/translations/.*\.po$
exclude: ^.*\.(geojson)$|^docs/static/img/screenshots/.*|^superset-frontend/CHANGELOG\.md$|^superset/examples/.*/data\.parquet$
- id: check-yaml
exclude: ^helm/superset/templates/
- id: debug-statements
@@ -62,9 +61,9 @@ repos:
args: ["--markdown-linebreak-ext=md"]
- repo: local
hooks:
- id: oxfmt-frontend
name: oxfmt (frontend)
entry: bash -c 'cd superset-frontend && files=(); for f in "$@"; do files+=("${f#superset-frontend/}"); done; npx oxfmt --write --no-error-on-unmatched-pattern -- "${files[@]}"' --
- id: prettier-frontend
name: prettier (frontend)
entry: bash -c 'cd superset-frontend && for file in "$@"; do npx prettier --write "${file#superset-frontend/}"; done'
language: system
pass_filenames: true
files: ^superset-frontend/.*\.(js|jsx|ts|tsx|css|scss|sass|json)$
@@ -82,12 +81,6 @@ repos:
language: system
pass_filenames: true
files: ^superset-frontend/.*\.(js|jsx|ts|tsx)$
- id: stylelint-frontend
name: stylelint (frontend css-in-js)
entry: ./scripts/stylelint.sh
language: system
pass_filenames: true
files: ^superset-frontend/.*\.(js|jsx|ts|tsx)$
- id: eslint-docs
name: eslint (docs)
entry: bash -c 'cd docs && FILES=$(printf "%s\n" "$@" | sed "s|^docs/||" | tr "\n" " ") && yarn eslint --fix --quiet $FILES'
@@ -144,7 +137,7 @@ repos:
git fetch --no-recurse-submodules origin "$TARGET_BRANCH" 2>/dev/null || true
fi
BASE=$(git merge-base origin/"$TARGET_BRANCH" HEAD 2>/dev/null) || BASE="HEAD"
files=$(git diff --name-only --diff-filter=ACM "$BASE"..HEAD 2>/dev/null | grep '^superset/.*\.py$' | grep -v '^superset/migrations/' || true)
files=$(git diff --name-only --diff-filter=ACM "$BASE"..HEAD 2>/dev/null | grep '^superset/.*\.py$' || true)
if [ -n "$files" ]; then
pylint --rcfile=.pylintrc --load-plugins=superset.extensions.pylint --reports=no $files
else
@@ -165,14 +158,3 @@ repos:
language: system
files: ^superset/config\.py$
pass_filenames: false
- id: zizmor
name: zizmor (GHA security audit)
entry: zizmor
language: python
additional_dependencies: [zizmor==1.25.2]
files: ^\.github/
types: [yaml]
pass_filenames: false
# Advisory until pre-existing findings are resolved; remove
# --no-exit-codes to make this hook blocking.
args: [--no-exit-codes, .github/]
+2 -4
View File
@@ -7,9 +7,9 @@
.codecov.yml
.eslintrc
.eslintignore
.stylelintignore
.flake8
.nvmrc
.prettierrc
.rat-excludes
.swcrc
.*log
@@ -43,9 +43,6 @@ _build/*
_static/*
.buildinfo
searchindex.js
# auto-generated by docs/scripts/convert-api-sidebar.mjs from openapi.json
sidebar.js
sidebar.ts
# auto generated
requirements/*
# vendorized
@@ -63,6 +60,7 @@ tsconfig.tsbuildinfo
.*yml
.*iml
.esprintrc
.prettierignore
generator-superset/*
temporary_superset_ui/*
+6 -51
View File
@@ -2,31 +2,24 @@
Apache Superset is a data visualization platform with Flask/Python backend and React/TypeScript frontend.
## Run Pre-commit Before Pushing
## ⚠️ CRITICAL: Always Run Pre-commit Before Pushing
Always run pre-commit against the files changed by the current branch before
pushing. This matches CI and keeps unrelated failures already present on
`master` from blocking otherwise independent work.
**ALWAYS run `pre-commit run --all-files` before pushing commits.** CI will fail if pre-commit checks don't pass. This is non-negotiable.
```bash
# Stage your changes first
git add .
# Run pre-commit on staged files
pre-commit run
# Run pre-commit on all files
pre-commit run --all-files
# If there are auto-fixes, stage them and commit
git add .
git commit --amend # or new commit
```
Use `pre-commit run --all-files` when auditing or repairing the repository-wide
baseline. If that check finds failures in files untouched by the current branch,
fix them in a separate branch rather than adding unrelated changes to the
current pull request.
Common pre-commit failures:
- **Formatting** - black, oxfmt, eslint will auto-fix
- **Formatting** - black, prettier, eslint will auto-fix
- **Type errors** - mypy failures need manual fixes
- **Linting** - ruff, pylint issues need manual fixes
@@ -59,43 +52,6 @@ Common pre-commit failures:
- **External API exposure** - Use UUIDs in public APIs instead of internal integer IDs
- **Existing models** - Add UUID fields alongside integer IDs for gradual migration
## Security and Threat Model
Before evaluating any code path for security issues, read [`SECURITY.md`](SECURITY.md). It is the canonical, authoritative source for Apache Superset's security model and is referenced by both human reporters and automated scanners.
In short, the test for whether a finding is in scope is one question:
> *Does it let a principal perform an action the role and capability matrix in `SECURITY.md` does not entitle them to?*
If yes, it is in scope. If no, it is not.
The three trust boundaries are:
1. **The Admin role** is a fully trusted operational principal. Anything an Admin can do through documented configuration, API, or UI is an intended capability, not a vulnerability.
2. **The operator** owns deployment-time decisions (secrets, network exposure, feature-flag selection, connector and codec choices, notification destinations, third-party plugins). Misconfiguration at this layer is a deployment defect, not a Superset vulnerability.
3. **The codebase** is responsible for enforcing the role and capability matrix wherever it exposes functionality to a principal: API routes, command and DAO layers, UI handlers, background jobs, and any other entry point. A missing or incorrect enforcement check is in scope no matter where it lives.
The security model assumes that operator-controlled infrastructure, including the metadata database, cache backends, message brokers, secret stores, and deployment environment, remains within the operator's trust boundary. Vulnerabilities must demonstrate a security boundary violation by an attacker who does not already control those systems.
Route-level authorization in this codebase uses one of three Flask-AppBuilder decorators depending on the route type:
- `@protect()` for REST API routes (`ModelRestApi` / `BaseApi`)
- `@has_access_api` for legacy view routes
- `@has_access` for legacy HTML view routes
Object-level authorization via `security_manager.raise_for_access(...)` applies to data-bearing resources: dashboards, charts, datasets and datasources, queries, database and table access, and query contexts. Other resources (annotations, tags, CSS templates, reports, RLS rules, and similar) rely on the route-level decorator plus DAO `base_filters` for ownership scoping; the absence of `raise_for_access` on these resources is by design, not a finding. Code that omits the per-object gate on a route that returns or mutates a specific data-bearing object is in scope; code that follows the correct pattern for its resource class can still contain injection, SSRF, XSS, or other classes of finding unrelated to authorization, which are evaluated separately.
The full role and capability matrix, in-scope and out-of-scope class lists, and CVE aggregation rules are in [`SECURITY.md`](SECURITY.md). Defer to that document for any specifics.
**Requirements for findings filed by automated tooling**
Automated scanners (LLM-based code scanners, static analyzers, dependency tools) that file findings against this codebase must, in each finding, name:
1. The specific role and capability matrix row in [`SECURITY.md`](SECURITY.md) the finding believes is violated.
2. The principal the finding assumes the attacker holds (Public, Gamma, sql_lab, Alpha, Admin, Embedded guest token, or a custom role with explicit capability grants).
Findings that cannot identify both should be filed as questions, not vulnerabilities. This requirement exists to ensure every reported issue is testable against the published security model and to keep speculative or pattern-match-only reports out of the triage queue.
## Key Directories
```
@@ -172,7 +128,6 @@ The Developer Portal auto-generates MDX documentation from Storybook stories. **
## Architecture Patterns
### Security & Features
- **Security model**: see the top-level [Security and Threat Model](#security-and-threat-model) section and [`SECURITY.md`](SECURITY.md)
- **RBAC**: Role-based access via Flask-AppBuilder
- **Feature flags**: Control feature rollouts
- **Row-level security**: SQL-based data access control
@@ -270,7 +225,7 @@ git add . # Pre-commit only checks staged files
# Quick validation (faster than --all-files)
pre-commit run # Staged files only
pre-commit run mypy # Python type checking
pre-commit run format # Code formatting
pre-commit run prettier # Code formatting
pre-commit run eslint # Frontend linting
```
+1
View File
@@ -365,6 +365,7 @@ under the License.
- [#38745](https://github.com/apache/superset/pull/38745) fix(dashboard): larger JSON metadata editor for better editing UX (#38728) (@Mayankaggarwal8055)
- [#38647](https://github.com/apache/superset/pull/38647) fix(datasource): align access validation in legacy views (@sha174n)
- [#38675](https://github.com/apache/superset/pull/38675) fix(echarts): prevent plain legend clipping in dashboards (@richardfogaca)
- [#38846](https://github.com/apache/superset/pull/38846) fix(embedded-sdk): wire `hideTab` to actually hide the dashboard tab (@michael-s-molina)
- [#38837](https://github.com/apache/superset/pull/38837) fix(models): correct TabState.latest_query_id column type to match FK target (@sadpandajoe)
- [#38676](https://github.com/apache/superset/pull/38676) fix(report): raise warning when filter type not recognized (@alexandrusoare)
- [#38823](https://github.com/apache/superset/pull/38823) fix(extensions-cli): remove publisher prefix from bundle filename (@michael-s-molina)
+2 -11
View File
@@ -29,7 +29,7 @@ ARG BUILD_TRANSLATIONS="false"
######################################################################
# superset-node-ci used as a base for building frontend assets and CI
######################################################################
FROM --platform=${BUILDPLATFORM} node:24-trixie-slim AS superset-node-ci
FROM --platform=${BUILDPLATFORM} node:20-trixie-slim AS superset-node-ci
ARG BUILD_TRANSLATIONS
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
ARG DEV_MODE="false" # Skip frontend build in dev mode
@@ -55,13 +55,6 @@ WORKDIR /app/superset-frontend
RUN mkdir -p /app/superset/static/assets \
/app/superset/translations
# Harden `npm ci` against transient npm-registry network blips (e.g. ECONNRESET),
# which otherwise fail the entire multi-platform image build with no retry.
ENV npm_config_fetch_retries=5 \
npm_config_fetch_retry_mintimeout=20000 \
npm_config_fetch_retry_maxtimeout=120000 \
npm_config_fetch_timeout=600000
# Mount package files and install dependencies if not in dev mode
# NOTE: we mount packages and plugins as they are referenced in package.json as workspaces
# ideally we'd COPY only their package.json. Here npm ci will be cached as long
@@ -141,7 +134,7 @@ RUN --mount=type=cache,target=/root/.cache/uv \
COPY superset/translations/ /app/translations_mo/
RUN if [ "${BUILD_TRANSLATIONS}" = "true" ]; then \
pybabel compile --use-fuzzy -d /app/translations_mo || true; \
pybabel compile -d /app/translations_mo | true; \
fi; \
rm -f /app/translations_mo/*/*/*.[po,json]
@@ -209,8 +202,6 @@ RUN mkdir -p /app/data && chown -R superset:superset /app/data
# Copy compiled things from previous stages
COPY --from=superset-node /app/superset/static/assets superset/static/assets
# Copy service.worker.js optionall as it doesn't exist when DEV_MODE=true
COPY --from=superset-node /app/superset/static/service-worker.j[s] superset/static/service-worker.js
# TODO, when the next version comes out, use --exclude superset/translations
COPY superset superset
+9 -16
View File
@@ -15,22 +15,19 @@
# limitations under the License.
#
# Python version installed; we need 3.11-3.12
PYTHON=`command -v python3.11 || command -v python3.12`
# Python version installed; we need 3.10-3.11
PYTHON=`command -v python3.11 || command -v python3.10`
.PHONY: install superset venv pre-commit up down logs ps nuke ports open
install: superset pre-commit
superset:
# Bootstrap uv (the project's installer) into the active environment
pip install uv
# Install external dependencies
uv pip install -r requirements/development.txt
pip install -r requirements/development.txt
# Install Superset in editable (development) mode
uv pip install -e .
pip install -e .
# Create an admin user in your metadata database
superset fab create-admin \
@@ -55,14 +52,11 @@ superset:
update: update-py update-js
update-py:
# Bootstrap uv (the project's installer) into the active environment
pip install uv
# Install external dependencies
uv pip install -r requirements/development.txt
pip install -r requirements/development.txt
# Install Superset in editable (development) mode
uv pip install -e .
pip install -e .
# Initialize the database
superset db upgrade
@@ -76,7 +70,7 @@ update-js:
venv:
# Create a virtual environment and activate it (recommended)
if ! [ -x "${PYTHON}" ]; then echo "You need Python 3.11 or 3.12 installed"; exit 1; fi
if ! [ -x "${PYTHON}" ]; then echo "You need Python 3.10 or 3.11 installed"; exit 1; fi
test -d venv || ${PYTHON} -m venv venv # setup a python3 virtualenv
. venv/bin/activate
@@ -85,8 +79,7 @@ activate:
pre-commit:
# setup pre commit dependencies
pip install uv
uv pip install -r requirements/development.txt
pip3 install -r requirements/development.txt
pre-commit install
format: py-format js-format
@@ -95,7 +88,7 @@ py-format: pre-commit
pre-commit run black --all-files
js-format:
cd superset-frontend; npm run format
cd superset-frontend; npm run prettier
flask-app:
flask run -p 8088 --reload --debugger
+12 -14
View File
@@ -29,7 +29,7 @@ under the License.
[![Last Commit](https://img.shields.io/github/last-commit/apache/superset)](https://github.com/apache/superset/commits/master)
[![Open Issues](https://img.shields.io/github/issues/apache/superset)](https://github.com/apache/superset/issues)
[![Open PRs](https://img.shields.io/github/issues-pr/apache/superset)](https://github.com/apache/superset/pulls)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://bit.ly/join-superset-slack)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](http://bit.ly/join-superset-slack)
[![Documentation](https://img.shields.io/badge/docs-apache.org-blue.svg)](https://superset.apache.org)
<picture width="500">
@@ -186,14 +186,9 @@ Try out Superset's [quickstart](https://superset.apache.org/docs/quickstart/) gu
## Get Involved
- Ask and answer questions on [StackOverflow](https://stackoverflow.com/questions/tagged/apache-superset) using the **apache-superset** tag
- [Join our community's Slack](https://bit.ly/join-superset-slack)
- [Join our community's Slack](http://bit.ly/join-superset-slack)
and please read our [Slack Community Guidelines](https://github.com/apache/superset/blob/master/CODE_OF_CONDUCT.md#slack-community-guidelines)
- [Join our dev@superset.apache.org Mailing list](https://lists.apache.org/list.html?dev@superset.apache.org). To join, simply send an email to [dev-subscribe@superset.apache.org](mailto:dev-subscribe@superset.apache.org)
- Follow us on social media:
[X](https://x.com/apachesuperset) |
[LinkedIn](https://www.linkedin.com/company/apache-superset) |
[Bluesky](https://bsky.app/profile/apachesuperset.bsky.social) |
[Reddit](https://reddit.com/r/apache-superset)
- If you want to help troubleshoot GitHub Issues involving the numerous database drivers that Superset supports, please consider adding your name and the databases you have access to on the [Superset Database Familiarity Rolodex](https://docs.google.com/spreadsheets/d/1U1qxiLvOX0kBTUGME1AHHi6Ywel6ECF8xk_Qy-V9R8c/edit#gid=0)
- Join Superset's Town Hall and [Operational Model](https://preset.io/blog/the-superset-operational-model-wants-you/) recurring meetings. Meeting info is available on the [Superset Community Calendar](https://superset.apache.org/community)
@@ -247,13 +242,16 @@ Understanding the Superset Points of View
- [Superset API](https://superset.apache.org/docs/rest-api)
<!--
The OSS Insight "Repo Activity" widget (https://next.ossinsight.io/) was
intentionally removed. This README is rendered on the ASF-hosted website
(superset.apache.org), so its contents are subject to ASF's third-party
content and CSP rules. OSS Insight has no Data Processing Agreement (DPA)
with the ASF, so we cannot embed its images/widgets here. Do not re-add it.
-->
## Repo Activity
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=39464018" target="_blank" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=39464018&image_size=auto&color_scheme=dark" width="655" height="auto" />
<img alt="Performance Stats of apache/superset - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=39464018&image_size=auto&color_scheme=light" width="655" height="auto" />
</picture>
</a>
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
<!-- telemetry/analytics pixel: -->
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=bc1c90cd-bc04-4e11-8c7b-289fb2839492" />
+1 -1
View File
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
FROM python:3.11-slim-trixie
FROM python:3.10-slim-trixie
RUN useradd --user-group --create-home --no-log-init --shell /bin/bash superset
+1 -1
View File
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
FROM python:3.11-slim-trixie
FROM python:3.10-slim-trixie
RUN useradd --user-group --create-home --no-log-init --shell /bin/bash superset
+1 -1
View File
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
FROM python:3.11-slim-trixie
FROM python:3.10-slim-trixie
ARG VERSION
RUN git clone --depth 1 --branch ${VERSION} https://github.com/apache/superset.git /superset
+1 -1
View File
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
FROM python:3.11-slim-trixie
FROM python:3.10-slim-trixie
RUN apt-get update -y
RUN apt-get install -y \
+2 -2
View File
@@ -423,7 +423,7 @@ git push origin ${SUPERSET_VERSION}
### Publishing a Convenience Release to PyPI
Extract the release to the `/tmp` folder to build the PyPI release. Files in the `/tmp` folder will be automatically deleted by the OS.
Extract the release to the `/tmp` folder to build the PiPY release. Files in the `/tmp` folder will be automatically deleted by the OS.
```bash
mkdir -p /tmp/superset && cd /tmp/superset
@@ -458,7 +458,7 @@ cd ../
sed -i '' "s/version_string = .*/version_string = \"$SUPERSET_VERSION\"/" setup.py
# build the python distribution
python -m build
python setup.py sdist
```
Publish to PyPI
+2 -2
View File
@@ -1,5 +1,3 @@
#!/usr/bin/env bash
# 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
@@ -17,6 +15,8 @@
# specific language governing permissions and limitations
# under the License.
#!/bin/bash
# Function to determine Python command
get_python_command() {
if command -v python3 &>/dev/null; then
+6 -56
View File
@@ -56,33 +56,8 @@ def verify_sha512(filename: str) -> str:
# Part 2: Verify RSA key - this is the same as running `gpg --verify {release}.asc {release}` and comparing the RSA key and email address against the KEYS file # noqa: E501
KEYS_URL = "https://downloads.apache.org/superset/KEYS"
def ensure_keys_imported() -> None:
"""Import the Apache Superset KEYS file into the local GPG keyring.
Without this, `gpg --verify` returns "No public key" and the signature
cannot actually be verified only the key ID in the signature metadata
is visible.
"""
try:
keys = requests.get(KEYS_URL, timeout=30)
except requests.RequestException as exc:
print(f"Warning: could not fetch KEYS file for import: {exc}")
return
if keys.status_code != 200:
print(f"Warning: could not fetch KEYS file (HTTP {keys.status_code})")
return
subprocess.run( # noqa: S603
["gpg", "--import"], # noqa: S607
input=keys.content,
capture_output=True,
)
def get_gpg_info(filename: str) -> tuple[Optional[str], Optional[str]]:
"""Run the GPG verify command and extract RSA/EDDSA key and email address."""
"""Run the GPG verify command and extract RSA key and email address."""
asc_filename = filename + ".asc"
result = subprocess.run( # noqa: S603
["gpg", "--verify", asc_filename, filename], # noqa: S607
@@ -90,50 +65,25 @@ def get_gpg_info(filename: str) -> tuple[Optional[str], Optional[str]]:
)
output = result.stderr.decode()
# If no public key was available, import KEYS and retry so that
# `Good signature from "Name <email>"` appears in the output.
if "No public key" in output:
ensure_keys_imported()
result = subprocess.run( # noqa: S603
["gpg", "--verify", asc_filename, filename], # noqa: S607
capture_output=True, # noqa: S607
)
output = result.stderr.decode()
rsa_key = re.search(r"RSA key ([0-9A-F]+)", output)
eddsa_key = re.search(r"EDDSA key ([0-9A-F]+)", output)
# Try multiple patterns — `Good signature from` is the most reliable
# source of the email; `issuer` is a fallback for older gpg output.
email_patterns = (
r'Good signature from ".*?<([^>]+)>"',
r'aka ".*?<([^>]+)>"',
r'issuer "([^"]+)"',
)
email_result: Optional[str] = None
for pattern in email_patterns:
match = re.search(pattern, output)
if match:
email_result = match.group(1)
break
email = re.search(r'issuer "([^"]+)"', output)
rsa_key_result = rsa_key.group(1) if rsa_key else None
eddsa_key_result = eddsa_key.group(1) if eddsa_key else None
email_result = email.group(1) if email else None
key_result = rsa_key_result or eddsa_key_result
# Debugging:
if key_result:
print("RSA or EDDSA Key found")
else:
print("Warning: No RSA or EDDSA key found in GPG verification output.")
if email_result:
print(f"Email found: {email_result}")
print("email found")
else:
print("Warning: No email address found in GPG verification output.")
if "No public key" in output:
print(
"Hint: public key is not in your keyring. Import it with:\n"
f" curl -s {KEYS_URL} | gpg --import"
)
return key_result, email_result
+26 -97
View File
@@ -58,10 +58,6 @@ categories:
url: https://www.ontruck.com/
Financial Services:
- name: Aadhar Housing Finance Limited
url: https://www.aadharhousing.com
contributors: ["@thakerhardiks"]
- name: Aktia Bank plc
url: https://www.aktia.com
@@ -83,9 +79,6 @@ categories:
- name: Clark.de
url: https://clark.de/
- name: Cover Genius
url: https://covergenius.com/
- name: EnquiryLabs
url: https://www.enquirylabs.co.uk
@@ -95,10 +88,6 @@ categories:
- name: KarrotPay
url: https://www.daangnpay.com/
- name: NICE Actimize
url: https://www.niceactimize.com/
contributors: ["@stevensuting"]
- name: Remita
url: https://remita.net
contributors: ["@mujibishola"]
@@ -119,6 +108,9 @@ categories:
url: https://xendit.co/
contributors: ["@LieAlbertTriAdrian"]
- name: Cover Genius
url: https://covergenius.com/
Gaming:
- name: Popoko VM Games Studio
url: https://popoko.live
@@ -168,11 +160,6 @@ categories:
url: https://www.now.vn/
contributors: ["@davidkohcw"]
- name: Pattern
url: https://www.pattern.com
contributors: ["@alephys26", "@hladush", "@sanketjadhavSF"]
logo: pattern_logo.png
- name: Qunar
url: https://www.qunar.com/
contributors: ["@flametest"]
@@ -300,11 +287,7 @@ 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
logo: hpe.png
@@ -404,10 +387,6 @@ categories:
url: https://www.techaudit.info
contributors: ["@ETselikov"]
- name: Tech Solution
url: https://www.tech-solution.com.ar/
contributors: ["@danteGiuliano", "@LeandroVallejos", "@McJaben", "@xJeree", "@zeo-return-null"]
- name: Tenable
url: https://www.tenable.com
contributors: ["@dflionis"]
@@ -437,10 +416,6 @@ categories:
logo: userguiding.svg
contributors: ["@tzercin"]
- name: Value Ad
url: https://bestpair.info/
contributors: ["@stevensuting"]
- name: Virtuoso QA
url: https://www.virtuosoqa.com
@@ -525,6 +500,10 @@ categories:
url: https://www.sunbird.org/
contributors: ["@eksteporg"]
- name: The GRAPH Network
url: https://thegraphnetwork.org/
contributors: ["@fccoelho"]
- name: Udemy
url: https://www.udemy.com/
contributors: ["@sungjuly"]
@@ -533,24 +512,7 @@ categories:
url: https://www.vipkid.com.cn/
contributors: ["@illpanda"]
Social Organization:
- name: Living Goods
url: https://www.livinggoods.org
contributors: ["@chelule"]
- name: One Acre Fund
url: https://oneacrefund.org/
contributors: ["@stevensuting"]
- name: Quest Alliance
url: https://www.questalliance.net/
contributors: ["@stevensuting"]
- name: The GRAPH Network
url: https://thegraphnetwork.org/
contributors: ["@fccoelho"]
- name: Wikimedia Foundation
- name: WikiMedia Foundation
url: https://wikimediafoundation.org
contributors: ["@vg"]
@@ -563,10 +525,6 @@ categories:
url: https://www.douroeci.com/
contributors: ["@nunohelibeires"]
- name: Rogow
url: https://rogow.com.br/
contributors: ["@nilmonto"]
- name: Safaricom
url: https://www.safaricom.co.ke/
contributors: ["@mmutiso"]
@@ -579,10 +537,11 @@ categories:
url: https://wattbewerb.de/
contributors: ["@wattbewerb"]
Healthcare:
- name: 2070Health
url: https://2070health.com/
- name: Rogow
url: https://rogow.com.br/
contributors: ["@nilmonto"]
Healthcare:
- name: Amino
url: https://amino.com
contributors: ["@shkr"]
@@ -595,6 +554,10 @@ categories:
url: https://www.getcare.io/
contributors: ["@alandao2021"]
- name: Living Goods
url: https://www.livinggoods.org
contributors: ["@chelule"]
- name: Maieutical Labs
url: https://maieuticallabs.it
contributors: ["@xrmx"]
@@ -613,10 +576,10 @@ categories:
- name: WeSure
url: https://www.wesure.cn/
HR / Staffing:
- name: bluquist
url: https://bluquist.com/
- name: 2070Health
url: https://2070health.com/
HR / Staffing:
- name: Swile
url: https://www.swile.co/
contributors: ["@PaoloTerzi"]
@@ -624,38 +587,21 @@ categories:
- name: Symmetrics
url: https://www.symmetrics.fyi
Government / Public authority:
- name: Centre Régional Auvergnat de l'Information Géographique (France)
url: https://www.craig.fr/
logo: craig.png
- name: bluquist
url: https://bluquist.com/
Government:
- name: City of Ann Arbor, MI
url: https://www.a2gov.org/
contributors: ["@sfirke"]
- name: Métropole Européenne de Lille (France)
url: https://data.lillemetropole.fr/accueil/
logo: mel.jpg
- name: NRLM - Sarathi, India
url: https://pib.gov.in/PressReleasePage.aspx?PRID=1999586
- name: Région Bretagne (France)
url: https://geobretagne.fr/
logo: geobretagne.svg
- name: Région Hauts-de-France (France)
url: https://www.geo2france.fr/
logo: geo2france.png
- name: Rennes Métropole (France)
url: https://metropole.rennes.fr/
logo: rennes-ville-metropole_noir.svg
- name: RIS3 Strategy of CZ, MIT CR
url: https://www.ris3.cz/
contributors: ["@RIS3CZ"]
- name: NRLM - Sarathi, India
url: https://pib.gov.in/PressReleasePage.aspx?PRID=1999586
Mobile Software:
- name: VLMedia
url: https://www.vlmedia.com.tr
@@ -707,10 +653,6 @@ categories:
url: https://automattic.com/
contributors: ["@Khrol", "@Usiel"]
- name: CamptoCamp
url: https://camptocamp.com/
logo: camptocamp.svg
- name: Dropbox
url: https://www.dropbox.com/
contributors: ["@bkyryliuk"]
@@ -719,10 +661,6 @@ categories:
url: https://flowbird.com
contributors: ["@EmmanuelCbd"]
- name: geOrchestra
url: https://www.georchestra.org
logo: georchestra.svg
- name: GEOTAB
url: https://www.geotab.com
contributors: ["@JZ6"]
@@ -739,10 +677,6 @@ categories:
url: https://www.increff.com/
contributors: ["@ishansinghania"]
- name: jDev
url: https://jdev.fr/
logo: jDev.svg
- name: Let's Roam
url: https://www.letsroam.com/
@@ -753,11 +687,6 @@ categories:
url: https://1beat.com/
contributors: ["@GuyAttia"]
- name: pi-Geosolutions
url: https://www.pi-geosolutions.fr/
logo: pi-Geosolutions.png
contributors: ["@jeanpommier"]
- name: X
url: https://x.com/
-145
View File
@@ -1,145 +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.
-->
# Security Policy
This is a project of the [Apache Software Foundation](https://apache.org) and follows the
ASF [vulnerability handling process](https://apache.org/security/#vulnerability-handling).
## Reporting Vulnerabilities
**⚠️ Please do not file GitHub issues for security vulnerabilities as they are public! ⚠️**
Apache Software Foundation takes a rigorous standpoint in resolving the security issues
in its software projects. Apache Superset is highly sensitive and forthcoming to issues
pertaining to its features and functionality.
If you have any concern or believe you have found a vulnerability in Apache Superset,
please get in touch with the Apache Superset Security Team privately at
e-mail address [security@superset.apache.org](mailto:security@superset.apache.org).
More details can be found on the ASF website at
[ASF vulnerability reporting process](https://apache.org/security/#reporting-a-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.
## Security Model
This section defines what Apache Superset considers a security issue and what it does not. It is the canonical reference for reporters, the Apache Superset Security Team, and any automated tool (LLM-based scanner, static analyzer, dependency tool) that needs to constrain its hypotheses to behaviors that genuinely violate the project's security policy.
The model is intentionally written in terms of principals, trust boundaries, and capability surface rather than in terms of specific files, functions, or libraries. New code paths inherit the model automatically.
### Trust Boundaries
Apache Superset's threat model assumes three trust boundaries.
1. *The Admin role* is a fully trusted operational principal. Anything an Admin can do through the documented user interface, REST API, or configuration system is an intended capability, not a vulnerability, even if individually powerful or destructive. The Admin role is, by policy, equivalent to operating-system-level trust over the Apache Superset application. This is unavoidable rather than aspirational: an Admin can, for example, register new database connections of arbitrary type, execute arbitrary SQL through SQL Lab, render Jinja templates that resolve to SQL or rendered HTML, and override application configuration. Granting Admin is functionally equivalent to granting shell access on the host, which is the reasoning behind treating it as a trust boundary in the sense of MITRE CNA Operational Rules 4.1.
2. *The operator* is whoever deploys, configures, and runs Apache Superset. Behaviors that depend on deployment-time decisions are the operator's responsibility, not Apache Superset's. This includes the values of secrets, the network reachability of the application and its data sources, the choice of database connectors and cache backends, the selection of feature flags, the destinations of notifications, and the trust placed in third-party plugins. Defaults that fail closed are the responsibility of the Apache Superset codebase. Defaults that fail open must be accompanied by a documented hardening requirement; applying that hardening is the operator's responsibility, while shipping an undocumented or unflagged fail-open default is a codebase issue.
3. *The Apache Superset codebase* is responsible for enforcing the role and capability matrix below across its product surface. A failure to enforce, anywhere in that surface, is in scope. The codebase's commitments are limited to the role and capability matrix and to controls Apache Superset's own documentation (this file and the linked Security documentation) explicitly positions as security boundaries; configurable hardening that operators can layer on top is treated separately under *Vulnerability Scope* below.
### Roles and Capabilities
Apache Superset ships with the following first-class principals. Detailed permission definitions live in the [Security documentation](https://superset.apache.org/docs/security).
| Principal | Read data | Write objects | Execute SQL | Manage databases | Manage users, roles, RLS |
|---|---|---|---|---|---|
| Public (anonymous) | none by default | no | no | no | no |
| Gamma | only granted datasets | own charts and dashboards on granted datasets | no by default (requires the `sql_lab` role) | no | no |
| Alpha | all data sources | own charts, dashboards, and datasets | no by default (requires the `sql_lab` role) | data upload to existing databases only | no |
| Admin | all | all | yes | yes | yes |
| Embedded guest token | data sources reachable through the embedded dashboards the token authorizes | no | no | no | no |
The `sql_lab` role is *additive*: it grants the SQL Lab permission set on top of the base role above, and is the only path by which Gamma or Alpha gain SQL execution capability. Database access is still scoped per the base role's grants. Admin includes SQL Lab access by default.
Deployments may grant or revoke individual view-menu permissions, which shifts the boundary for that deployment but does not redefine the model. Any custom role created by an operator inherits the same principle: its capabilities are whatever the operator has explicitly granted it. The Public principal follows the same rule: operators may grant the Public role read access to specific datasets or dashboards (typically for anonymous reporting use cases), which shifts the boundary for that deployment without redefining the model.
### Vulnerability Scope
The test for whether a finding is in scope is a single question:
> *Does this finding let a principal perform an action the role and capability matrix above does not entitle them to?*
If yes, it is in scope. If no, it is out of scope. The lists below apply that test to the classes Apache Superset most commonly receives reports about; they are illustrative, not exhaustive.
*In Scope*
- A user, embedded guest, or anonymous visitor reads, modifies, or deletes data outside their granted set. Includes object-level access bypass on charts, dashboards, datasets, saved queries, tags, annotations, and similar per-object endpoints, and row-level-security rule bypass.
- A user supplies input that the codebase should sanitize or parameterize but does not, causing arbitrary SQL, template code, or scripts to execute. Includes injection through Jinja templates, SQL-construction paths, and any field the codebase passes to a query engine or template engine.
- A user bypasses authentication, fixates or reuses another user's session, or reaches an authenticated endpoint without logging in.
- An embedded guest token authorizes actions outside the dashboard it was issued for, or can be forged, replayed, or escalated to a higher principal.
- Apache Superset, acting on behalf of an unprivileged user, fetches an outbound URL the user controls in a feature where Apache Superset itself, not the operator, controls the outbound destination set (server-side request forgery).
- An Apache Superset default fails open without an accompanying documented hardening requirement. The codebase is responsible for shipping fail-closed defaults or for documenting the hardening required when a default fails open; failures of that responsibility are in scope (see *Trust Boundaries*).
- A user bypasses a control Apache Superset documents specifically as a security boundary. This includes row-level security, the access checks tied to the role and capability matrix above, and any feature whose documentation positions it as security-relevant. The codebase commits to enforcing those controls; bypasses are in scope regardless of which principal triggers them.
- A user causes a script to execute in another user's browser through a field the codebase renders to that other user (cross-site scripting), or causes cross-origin leakage of authenticated session state or data.
- A user reaches a route, page, or API endpoint that requires a role they do not have.
*Out of Scope*
- Any action an Admin role can perform through documented configuration, API, or UI. The Admin role is a trusted operational principal by policy. Per MITRE CNA Operational Rules 4.1, a qualifying vulnerability must violate a security policy; behavior within a documented trust boundary does not.
- Deployment or operator decisions: the values of secrets and tokens, whether internal networks are reachable from the server, which database connectors or cache backends are enabled, which feature flags are set, where notifications are delivered, and which third-party plugins are loaded.
- Compromise, modification, or malicious control of trusted backend infrastructure. Apache Superset assumes the integrity of its metastore, cache backends (for example Redis or Memcached), message brokers, secret stores, and other operator-managed infrastructure. Findings that require an attacker to read from, write to, or otherwise tamper with these systems, including injecting malicious state, serialized objects, cache entries, task metadata, configuration, or database records, are post-compromise scenarios and do not constitute vulnerabilities in Apache Superset itself. A finding remains in scope only if an unprivileged user can cause such modification through a vulnerability in Apache Superset.
- The continued presence of expired key-value or metastore-cache entries that have not yet been deleted from the metadata database. Such entries are excluded from reads once expired, are purged opportunistically on write, and are removed in bulk by the scheduled `prune_key_value` maintenance task; their lingering until purged is an eventual-cleanup property, not a security boundary, and does not constitute a vulnerability.
- How a downstream application (spreadsheet program, email client, browser handling user-downloaded files) interprets output Apache Superset produced for it.
- Findings without a reproducible proof of concept against a supported release. The burden of demonstrating exploitability rests with the reporter; findings closed for lack of a proof of concept may be refiled if one is later produced.
- Brute force, rate limiting, denial of service, or resource exhaustion that does not bypass a documented control.
- Missing security headers, banner or version disclosure, user or object enumeration through error messages or timing, and similar low-impact information disclosure that does not enable a further concrete exploit.
- Bypasses of configurable defense-in-depth hardening that Apache Superset does not document as a security boundary. Apache Superset is not a SQL or database firewall: operator-deployable filters such as SQL function or table denylists, URI restrictions on already-authorized database connectors, and similar belt-and-braces controls are provided to let operators layer hardening on top of the role and capability matrix, not as firewall-grade guarantees the codebase commits to. Findings against such hardening are improvements, not vulnerabilities, unless the documentation positions the specific control as security-relevant.
- Hardening suggestions that improve defense in depth but do not violate the security model.
Findings in third-party dependencies fall into two cases. A finding in a transitive dependency, or in an operator-selected dependency that Apache Superset does not ship, is out of scope and should be reported to the dependency's maintainers. A finding caused by Apache Superset pinning a known-vulnerable version of a direct dependency it ships, or using a dependency in a way that creates a vulnerability the dependency itself does not have, remains in scope. Dependency findings in the official Apache Superset Docker image that fall into the first case can be remediated by extending the image at release time.
When uncertain whether a finding falls in scope, please file it through the reporting process above. The triage team will classify it and explain the reasoning if it is closed as out of scope.
**Outcome of Reports**
Reports that are deemed out of scope for a CVE but represent valid security best practices or hardening opportunities are typically converted into public GitHub issues, where the community can contribute fixes alongside the maintainers. The triage decision and reasoning are communicated back to the reporter in either case.
**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
- [Apache Superset documentation](https://superset.apache.org/docs/security)
- [Common Vulnerabilities and Exposures by release](https://superset.apache.org/docs/security/cves)
- [How Security Vulnerabilities are Reported & Handled in Apache Superset (Blog)](https://preset.io/blog/how-security-vulnerabilities-are-reported-and-handled-in-apache-superset/)
**For LLM agents and automated scanners**
This file is the canonical source of truth for what Apache Superset considers a security vulnerability. Automated tooling (LLM-based code scanners, static analyzers, dependency tools) should treat the Security Model section as authoritative when classifying findings. The repository's [AGENTS.md](AGENTS.md) file contains a short pointer to this document for agents that read AGENTS.md as their entry point.
+77 -961
View File
File diff suppressed because it is too large Load Diff
+1 -7
View File
@@ -28,10 +28,8 @@ x-superset-image: &superset-image apachesuperset.docker.scarf.sh/apache/superset
x-superset-volumes:
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
- ./docker:/app/docker
- ./superset-core:/app/superset-core
- superset_home:/app/superset_home
x-superset-environment: &superset-environment
# Tagged images must use their bundled packages rather than host bind mounts.
DEV_MODE: "false"
services:
redis:
@@ -60,7 +58,6 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
environment: *superset-environment
image: *superset-image
container_name: superset_app
command: ["/app/docker/docker-bootstrap.sh", "app-gunicorn"]
@@ -82,7 +79,6 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
environment: *superset-environment
depends_on:
db:
condition: service_started
@@ -102,7 +98,6 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
environment: *superset-environment
restart: unless-stopped
depends_on:
superset-init:
@@ -125,7 +120,6 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
environment: *superset-environment
restart: unless-stopped
depends_on:
superset-init:
+1 -10
View File
@@ -71,7 +71,7 @@ x-common-build: &common-build
context: .
target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean`
cache_from:
- apache/superset-cache:3.11-slim-trixie
- apache/superset-cache:3.10-slim-trixie
args:
DEV_MODE: "true"
INCLUDE_CHROMIUM: ${INCLUDE_CHROMIUM:-false}
@@ -115,10 +115,6 @@ 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:-}
@@ -141,10 +137,6 @@ 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
@@ -165,7 +157,6 @@ 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
+1 -1
View File
@@ -33,7 +33,7 @@ x-common-build: &common-build
context: .
target: dev
cache_from:
- apache/superset-cache:3.11-slim-trixie
- apache/superset-cache:3.10-slim-trixie
services:
redis:
+1 -30
View File
@@ -34,12 +34,11 @@ x-superset-volumes: &superset-volumes
- superset_home:/app/superset_home
- ./tests:/app/tests
- superset_data:/app/data
- ./local_extensions:/app/local_extensions
x-common-build: &common-build
context: .
target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean`
cache_from:
- apache/superset-cache:3.11-slim-trixie
- apache/superset-cache:3.10-slim-trixie
args:
DEV_MODE: "true"
INCLUDE_CHROMIUM: ${INCLUDE_CHROMIUM:-false}
@@ -62,34 +61,6 @@ services:
volumes:
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./docker/nginx/templates:/etc/nginx/templates:ro
# Wait for the webpack dev server's manifest.json to be served before
# starting nginx. This prevents 404s on static assets at startup. The
# probe targets host.docker.internal so it works regardless of whether
# the dev server runs in the superset-node container
# (BUILD_SUPERSET_FRONTEND_IN_DOCKER=true, the default) or directly on
# the host (BUILD_SUPERSET_FRONTEND_IN_DOCKER=false).
command:
- /bin/bash
- -c
- |
url="http://host.docker.internal:9000/static/assets/manifest.json"
max_attempts=300 # ~10 minutes at 2s intervals; first build can be slow
echo "Waiting for webpack dev server at $$url..."
attempt=0
until curl -sf --max-time 5 -H "Host: localhost" -o /dev/null "$$url"; do
attempt=$$((attempt + 1))
if [ "$$attempt" -ge "$$max_attempts" ]; then
echo "ERROR: webpack dev server did not serve $$url after $$max_attempts attempts." >&2
echo "Is the dev server running? With BUILD_SUPERSET_FRONTEND_IN_DOCKER=false you must start it on the host (e.g. 'npm run dev' in superset-frontend)." >&2
exit 1
fi
if [ $$((attempt % 15)) -eq 0 ]; then
echo "Still waiting for webpack dev server... ($$attempt/$$max_attempts)"
fi
sleep 2
done
echo "Webpack dev server is ready; starting nginx."
exec /docker-entrypoint.sh nginx -g 'daemon off;'
redis:
image: redis:7
-2
View File
@@ -70,8 +70,6 @@ SUPERSET_LOG_LEVEL=info
SUPERSET_APP_ROOT="/"
SUPERSET_ENV=development
# Swagger UI is opt-in (off by default); enable it for local development.
SUPERSET_ENABLE_SWAGGER_UI=true
SUPERSET_LOAD_EXAMPLES=yes
CYPRESS_CONFIG=false
SUPERSET_PORT=8088
+1 -1
View File
@@ -38,7 +38,7 @@ RESET='\033[0m'
echo -e "${GREEN}Updating package lists...${RESET}"
apt-get update -qq
echo -e "${GREEN}Installing packages: $*${RESET}"
echo -e "${GREEN}Installing packages: $@${RESET}"
apt-get install -yqq --no-install-recommends "$@"
echo -e "${GREEN}Autoremoving unnecessary packages...${RESET}"
+3 -23
View File
@@ -71,36 +71,16 @@ case "${1}" in
worker)
echo "Starting Celery worker..."
# setting up only 2 workers by default to contain memory usage in dev environments
celery --app=superset.tasks.celery_app:app worker -O fair -l INFO --concurrency=${CELERYD_CONCURRENCY:-2} ${WORKER_LOG_FILE:+--logfile=$WORKER_LOG_FILE}
celery --app=superset.tasks.celery_app:app worker -O fair -l INFO --concurrency=${CELERYD_CONCURRENCY:-2}
;;
beat)
echo "Starting Celery beat..."
rm -f /tmp/celerybeat.pid
celery --app=superset.tasks.celery_app:app beat --pidfile /tmp/celerybeat.pid -l INFO -s "${SUPERSET_HOME}"/celerybeat-schedule ${BEAT_LOG_FILE:+--logfile=$BEAT_LOG_FILE}
celery --app=superset.tasks.celery_app:app beat --pidfile /tmp/celerybeat.pid -l INFO -s "${SUPERSET_HOME}"/celerybeat-schedule
;;
app)
echo "Starting web app (using development server)..."
# Default to Flask debug mode in this dev compose entrypoint so the Talisman
# dev CSP (which permits 'unsafe-eval' required by React Refresh / HMR) is
# served. Operators can still set FLASK_DEBUG=false in docker/.env-local
# to exercise the production-like CSP and error handling.
: "${FLASK_DEBUG:=1}"
export FLASK_DEBUG
# Werkzeug's interactive debugger (/console) is a separate, security-sensitive
# feature and must be opted into explicitly via SUPERSET_DEBUG_ENABLED=true.
if [[ "${SUPERSET_DEBUG_ENABLED:-}" == "true" ]]; then
DEBUGGER_FLAG="--debugger"
echo " ⚠️ Werkzeug debugger enabled (requires PIN for /console access)"
else
DEBUGGER_FLAG="--no-debugger"
echo " 🔒 Werkzeug debugger disabled (set SUPERSET_DEBUG_ENABLED=true to enable)"
fi
flask run -p $PORT --reload $DEBUGGER_FLAG --host=0.0.0.0 \
--extra-files "/app/superset/extensions/.reload_trigger" \
--exclude-patterns "*/node_modules/*:*/.venv/*:*/build/*:*/__pycache__/*:*/superset-frontend/*:*/superset/__init__.py"
flask run -p $PORT --reload --debugger --without-threads --host=0.0.0.0 --exclude-patterns "*/node_modules/*:*/.venv/*:*/build/*:*/__pycache__/*"
;;
app-gunicorn)
echo "Starting web app..."
+1 -1
View File
@@ -19,7 +19,7 @@
#
HYPHEN_SYMBOL='-'
exec gunicorn \
gunicorn \
--bind "${SUPERSET_BIND_ADDRESS:-0.0.0.0}:${SUPERSET_PORT:-8088}" \
--access-logfile "${ACCESS_LOG_FILE:-$HYPHEN_SYMBOL}" \
--error-logfile "${ERROR_LOG_FILE:-$HYPHEN_SYMBOL}" \
+2 -23
View File
@@ -84,11 +84,9 @@ class CeleryConfig:
broker_url = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB}"
imports = (
"superset.sql_lab",
"superset.tasks.deletion_retention",
"superset.tasks.scheduler",
"superset.tasks.thumbnails",
"superset.tasks.cache",
"superset.tasks.export_dashboard_excel",
)
result_backend = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_RESULTS_DB}"
worker_prefetch_multiplier = 1
@@ -102,33 +100,14 @@ class CeleryConfig:
"task": "reports.prune_log",
"schedule": crontab(minute=10, hour=0),
},
# Gated on the SOFT_DELETE feature flag, which is off by default: the
# task is scheduled either way, but purges nothing while the flag is
# unset. Enable it in FEATURE_FLAGS below to exercise retention locally.
"deletion_retention.purge_soft_deleted": {
"task": "deletion_retention.purge_soft_deleted",
"schedule": crontab(minute=0, hour=0),
},
}
CELERY_CONFIG = CeleryConfig
FEATURE_FLAGS = {
"ALERT_REPORTS": True,
"DATASET_FOLDERS": True,
"ENABLE_EXTENSIONS": True,
"SEMANTIC_LAYERS": True,
}
EXTENSIONS_PATH = "/app/docker/extensions"
FEATURE_FLAGS = {"ALERT_REPORTS": True, "DATASET_FOLDERS": True}
ALERT_REPORTS_NOTIFICATION_DRY_RUN = True
# The Docker Compose app service is named "superset" and listens on 8088. Report
# paths are root-relative, so urljoin drops the base path; only the scheme, host,
# and port must be correct here. SUPERSET_APP_ROOT is kept for consumers that
# concatenate paths directly (e.g. cache warm-up). For screenshots in the dev
# stack (unbuilt static assets) point this at the nginx service instead:
# http://nginx{SUPERSET_APP_ROOT}/
WEBDRIVER_BASEURL = f"http://superset:8088{os.environ.get('SUPERSET_APP_ROOT', '/')}/"
WEBDRIVER_BASEURL = f"http://superset_app{os.environ.get('SUPERSET_APP_ROOT', '/')}/" # When using docker compose baseurl should be http://superset_nginx{ENV{BASEPATH}}/ # noqa: E501
# The base URL for the email report hyperlinks.
WEBDRIVER_BASEURL_USER_FRIENDLY = (
f"http://localhost:8888/{os.environ.get('SUPERSET_APP_ROOT', '/')}/"
@@ -18,8 +18,6 @@
# Configuration for docker-compose-light.yml - disables Redis and uses minimal services
# Import all settings from the main config first
import os
from flask_caching.backends.filesystemcache import FileSystemCache
from superset_config import * # noqa: F403
@@ -38,32 +36,3 @@ THUMBNAIL_CACHE_CONFIG = CACHE_CONFIG
# Disable Celery entirely for lightweight mode
CELERY_CONFIG = None # type: ignore[assignment,misc]
# Honor SUPERSET_FEATURE_<NAME> env vars on top of any flags inherited from
# superset_config. Lets local dev/e2e enable features (e.g. EMBEDDED_SUPERSET)
# without editing shipped config files. Only the literal string "true"
# (case-insensitive) is treated as enabled — "1"/"yes"/"on" are not, matching
# the strict-string convention used elsewhere in Superset's env parsing.
FEATURE_FLAGS = {
**FEATURE_FLAGS, # noqa: F405
**{
name[len("SUPERSET_FEATURE_") :]: value.strip().lower() == "true"
for name, value in os.environ.items()
if name.startswith("SUPERSET_FEATURE_")
},
}
if os.environ.get("SUPERSET_FEATURE_EMBEDDED_SUPERSET", "").strip().lower() == "true":
# Disable Talisman so /embedded/<uuid> doesn't return X-Frame-Options:SAMEORIGIN.
# Without this, browsers refuse to render Superset inside an iframe from a
# different origin (i.e. the embedded SDK use case). Production/CI configures
# Talisman with explicit `frame-ancestors`; for the lightweight local stack we
# just turn it off.
TALISMAN_ENABLED = False
# Guest tokens (used by the embedded SDK) inherit the "Public" role's perms.
# Out of the box Public has zero perms, so embedded dashboards immediately fail
# their first call (`/api/v1/me/roles/`) with 403. Mirror Public to Gamma —
# the standard read-only viewer role — so the embedded flow can authenticate
# and load dashboard data in local dev.
PUBLIC_ROLE_LIKE = "Gamma"
+2 -2
View File
@@ -163,10 +163,10 @@ do
# Iterate through the components of the version strings
for (( j=0; j<${#THIS_TAG_NAME_ARRAY[@]}; j++ )); do
echo "Comparing ${THIS_TAG_NAME_ARRAY[$j]} to ${LATEST_RELEASE_TAG_ARRAY[$j]}"
if [[ $((THIS_TAG_NAME_ARRAY[$j])) -gt $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
if [[ $((THIS_TAG_NAME_ARRAY[$j])) > $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
compare_result="greater"
break
elif [[ $((THIS_TAG_NAME_ARRAY[$j])) -lt $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
elif [[ $((THIS_TAG_NAME_ARRAY[$j])) < $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
compare_result="lesser"
break
fi
+7 -16
View File
@@ -9,13 +9,11 @@ When working on the Storybook-to-MDX documentation system:
## Why This Matters
The generator (`scripts/generate-superset-components.mjs`) should be lightweight - it extracts data from stories and passes it through. When you add special cases to the generator:
- It becomes harder to maintain
- Stories diverge from their docs representation
- Future stories need to know about generator quirks
When you fix stories to match the expected patterns:
- Stories work identically in Storybook and Docs
- The generator stays simple and predictable
- Patterns are consistent and learnable
@@ -23,7 +21,6 @@ When you fix stories to match the expected patterns:
## Story Patterns for Docs Generation
### Required Structure
```tsx
// Use inline export default (NOT const meta = ...; export default meta)
export default {
@@ -48,7 +45,6 @@ export const InteractiveMyComponent: Story = {
```
### For Components with Variants (size × style grids)
```tsx
const sizes = ['small', 'medium', 'large'];
const variants = ['primary', 'secondary', 'danger'];
@@ -67,20 +63,16 @@ InteractiveButton.parameters = {
```
### For Components Requiring Children
```tsx
InteractiveIconTooltip.parameters = {
docs: {
// Component descriptors with dot notation for nested components
sampleChildren: [
{ component: 'Icons.InfoCircleOutlined', props: { iconSize: 'l' } },
],
sampleChildren: [{ component: 'Icons.InfoCircleOutlined', props: { iconSize: 'l' } }],
},
};
```
### For Custom Live Code Examples
```tsx
InteractiveMyComponent.parameters = {
docs: {
@@ -92,7 +84,6 @@ InteractiveMyComponent.parameters = {
```
### For Complex Props (objects, arrays)
```tsx
InteractiveMenu.parameters = {
docs: {
@@ -108,13 +99,13 @@ InteractiveMenu.parameters = {
## Common Issues and How to Fix Them (in the Story)
| Issue | Wrong Approach | Right Approach |
| --------------------------------------- | ----------------------------- | ------------------------------------------------- |
| Component not generated | Add pattern to generator | Change story to use inline `export default` |
| Issue | Wrong Approach | Right Approach |
|-------|---------------|----------------|
| Component not generated | Add pattern to generator | Change story to use inline `export default` |
| Control shows as text instead of select | Add special case in generator | Add `argTypes` with `control: { type: 'select' }` |
| Missing children/content | Modify StorybookWrapper | Add `parameters.docs.sampleChildren` |
| Gallery not showing | Add to generator output | Add `parameters.docs.gallery` config |
| Wrong live example | Hardcode in generator | Add `parameters.docs.liveExample` |
| Missing children/content | Modify StorybookWrapper | Add `parameters.docs.sampleChildren` |
| Gallery not showing | Add to generator output | Add `parameters.docs.gallery` config |
| Wrong live example | Hardcode in generator | Add `parameters.docs.liveExample` |
## Files
-1
View File
@@ -1 +0,0 @@
../superset-frontend/.nvmrc
+1
View File
@@ -0,0 +1 @@
v22.22.0

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