diff --git a/.github/workflows/superset-app-cli.yml b/.github/workflows/superset-app-cli.yml
index ea41e5da412c..3cc839eb285a 100644
--- a/.github/workflows/superset-app-cli.yml
+++ b/.github/workflows/superset-app-cli.yml
@@ -23,7 +23,7 @@ jobs:
SUPERSET__SQLALCHEMY_DATABASE_URI: postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
services:
postgres:
- image: postgres:16-alpine
+ image: postgres:17-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
diff --git a/.github/workflows/superset-docs-deploy.yml b/.github/workflows/superset-docs-deploy.yml
index 85dd4bae21f9..e4998a074a55 100644
--- a/.github/workflows/superset-docs-deploy.yml
+++ b/.github/workflows/superset-docs-deploy.yml
@@ -68,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@v14
+ uses: dawidd6/action-download-artifact@v15
continue-on-error: true
with:
workflow: superset-python-integrationtest.yml
@@ -77,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@v14
+ uses: dawidd6/action-download-artifact@v15
continue-on-error: true
with:
workflow: superset-python-integrationtest.yml
diff --git a/.github/workflows/superset-docs-verify.yml b/.github/workflows/superset-docs-verify.yml
index e745dfcfd7c9..4ef6f6274216 100644
--- a/.github/workflows/superset-docs-verify.yml
+++ b/.github/workflows/superset-docs-verify.yml
@@ -111,7 +111,7 @@ jobs:
run: |
yarn install --check-cache
- name: Download database diagnostics from integration tests
- uses: dawidd6/action-download-artifact@v14
+ uses: dawidd6/action-download-artifact@v15
with:
workflow: superset-python-integrationtest.yml
run_id: ${{ github.event.workflow_run.id }}
diff --git a/.github/workflows/superset-e2e.yml b/.github/workflows/superset-e2e.yml
index 655a3da7e278..e3046a973d24 100644
--- a/.github/workflows/superset-e2e.yml
+++ b/.github/workflows/superset-e2e.yml
@@ -54,7 +54,7 @@ jobs:
USE_DASHBOARD: ${{ github.event.inputs.use_dashboard == 'true' || 'false' }}
services:
postgres:
- image: postgres:16-alpine
+ image: postgres:17-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
@@ -171,7 +171,7 @@ jobs:
GITHUB_TOKEN: ${{ github.token }}
services:
postgres:
- image: postgres:16-alpine
+ image: postgres:17-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
diff --git a/.github/workflows/superset-playwright.yml b/.github/workflows/superset-playwright.yml
index b2e2dbf6a9b5..910b61c9c203 100644
--- a/.github/workflows/superset-playwright.yml
+++ b/.github/workflows/superset-playwright.yml
@@ -45,7 +45,7 @@ jobs:
GITHUB_TOKEN: ${{ github.token }}
services:
postgres:
- image: postgres:16-alpine
+ image: postgres:17-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
diff --git a/.github/workflows/superset-python-integrationtest.yml b/.github/workflows/superset-python-integrationtest.yml
index d8e73d066ae0..bb0dce85bbaf 100644
--- a/.github/workflows/superset-python-integrationtest.yml
+++ b/.github/workflows/superset-python-integrationtest.yml
@@ -115,7 +115,7 @@ jobs:
SUPERSET__SQLALCHEMY_DATABASE_URI: postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
services:
postgres:
- image: postgres:16-alpine
+ image: postgres:17-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
diff --git a/.github/workflows/superset-python-presto-hive.yml b/.github/workflows/superset-python-presto-hive.yml
index b4bb9d5432b1..762c1a19d45d 100644
--- a/.github/workflows/superset-python-presto-hive.yml
+++ b/.github/workflows/superset-python-presto-hive.yml
@@ -25,7 +25,7 @@ jobs:
SUPERSET__SQLALCHEMY_EXAMPLES_URI: presto://localhost:15433/memory/default
services:
postgres:
- image: postgres:16-alpine
+ image: postgres:17-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
@@ -94,7 +94,7 @@ jobs:
UPLOAD_FOLDER: /tmp/.superset/uploads/
services:
postgres:
- image: postgres:16-alpine
+ image: postgres:17-alpine
env:
POSTGRES_USER: superset
POSTGRES_PASSWORD: superset
diff --git a/docker-compose-image-tag.yml b/docker-compose-image-tag.yml
index f9c486869a62..fd76e68abcd7 100644
--- a/docker-compose-image-tag.yml
+++ b/docker-compose-image-tag.yml
@@ -45,7 +45,7 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
- image: postgres:16
+ image: postgres:17
container_name: superset_db
restart: unless-stopped
volumes:
diff --git a/docker-compose-light.yml b/docker-compose-light.yml
index b3b6f41fdd1d..1d0a4a90be7b 100644
--- a/docker-compose-light.yml
+++ b/docker-compose-light.yml
@@ -85,7 +85,7 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
- image: postgres:16
+ image: postgres:17
restart: unless-stopped
volumes:
- db_home_light:/var/lib/postgresql/data
diff --git a/docker-compose-non-dev.yml b/docker-compose-non-dev.yml
index 5d221ab602c1..cc80aea9d19a 100644
--- a/docker-compose-non-dev.yml
+++ b/docker-compose-non-dev.yml
@@ -49,7 +49,7 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
- image: postgres:16
+ image: postgres:17
container_name: superset_db
restart: unless-stopped
volumes:
diff --git a/docker-compose.yml b/docker-compose.yml
index 8ab4b117f239..bd474a83ef47 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -76,7 +76,7 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
- image: postgres:16
+ image: postgres:17
restart: unless-stopped
ports:
- "127.0.0.1:${DATABASE_PORT:-5432}:5432"
diff --git a/docs/docs/configuration/configuring-superset.mdx b/docs/docs/configuration/configuring-superset.mdx
index e44b533fa992..c0032f1727fb 100644
--- a/docs/docs/configuration/configuring-superset.mdx
+++ b/docs/docs/configuration/configuring-superset.mdx
@@ -141,10 +141,10 @@ database engine on a separate host or container.
Superset supports the following database engines/versions:
-| Database Engine | Supported Versions |
-| ----------------------------------------- | ---------------------------------------- |
-| [PostgreSQL](https://www.postgresql.org/) | 10.X, 11.X, 12.X, 13.X, 14.X, 15.X, 16.X |
-| [MySQL](https://www.mysql.com/) | 5.7, 8.X |
+| Database Engine | Supported Versions |
+| ----------------------------------------- | ---------------------------------------------- |
+| [PostgreSQL](https://www.postgresql.org/) | 10.X, 11.X, 12.X, 13.X, 14.X, 15.X, 16.X, 17.X |
+| [MySQL](https://www.mysql.com/) | 5.7, 8.X |
Use the following database drivers and connection strings:
diff --git a/helm/superset/Chart.lock b/helm/superset/Chart.lock
index cb82f4cd84b9..3b59d04183d3 100644
--- a/helm/superset/Chart.lock
+++ b/helm/superset/Chart.lock
@@ -1,9 +1,9 @@
dependencies:
- name: postgresql
repository: oci://registry-1.docker.io/bitnamicharts
- version: 13.4.4
+ version: 16.7.27
- name: redis
repository: oci://registry-1.docker.io/bitnamicharts
version: 17.9.4
-digest: sha256:c6290bb7e8ce9c694c06b3f5e9b9d01401943b0943c515d3a7a3a8dc1e6492ea
-generated: "2025-03-16T00:52:41.47139769+09:00"
+digest: sha256:fcae507ca24a20b9cc08b8bf0fcb0eba8ffa33126ab6f71cc3a6e1d5e997e9e3
+generated: "2026-02-08T14:11:58.8058368+01:00"
diff --git a/helm/superset/Chart.yaml b/helm/superset/Chart.yaml
index 0cab38e8fc8d..5ef4fb2e00f1 100644
--- a/helm/superset/Chart.yaml
+++ b/helm/superset/Chart.yaml
@@ -29,10 +29,10 @@ maintainers:
- name: craig-rueda
email: craig@craigrueda.com
url: https://github.com/craig-rueda
-version: 0.15.3 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
+version: 0.15.4 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
dependencies:
- name: postgresql
- version: 13.4.4
+ version: 16.7.27
repository: oci://registry-1.docker.io/bitnamicharts
condition: postgresql.enabled
- name: redis
diff --git a/helm/superset/README.md b/helm/superset/README.md
index e9b372c72c0c..29dbdeea8a6a 100644
--- a/helm/superset/README.md
+++ b/helm/superset/README.md
@@ -23,7 +23,7 @@ NOTE: This file is generated by helm-docs: https://github.com/norwoodj/helm-docs
# superset
-
+
Apache Superset is a modern, enterprise-ready business intelligence web application
@@ -50,7 +50,7 @@ On helm this can be set on `extraSecretEnv.SUPERSET_SECRET_KEY` or `configOverri
| Repository | Name | Version |
|------------|------|---------|
-| oci://registry-1.docker.io/bitnamicharts | postgresql | 13.4.4 |
+| oci://registry-1.docker.io/bitnamicharts | postgresql | 16.7.27 |
| oci://registry-1.docker.io/bitnamicharts | redis | 17.9.4 |
## Values
diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js
index a2c9b3ae5d73..bf6cb9b6fd61 100644
--- a/superset-frontend/.eslintrc.js
+++ b/superset-frontend/.eslintrc.js
@@ -245,6 +245,16 @@ module.exports = {
// Lodash
'lodash/import-scope': [2, 'member'],
+ // React effect best practices
+ 'react-you-might-not-need-an-effect/no-reset-all-state-on-prop-change':
+ 'error',
+ 'react-you-might-not-need-an-effect/no-chain-state-updates': 'error',
+ 'react-you-might-not-need-an-effect/no-event-handler': 'error',
+ 'react-you-might-not-need-an-effect/no-derived-state': 'error',
+
+ // Storybook
+ 'storybook/prefer-pascal-case': 'error',
+
// File progress
'file-progress/activate': 1,
diff --git a/superset-frontend/oxlint.json b/superset-frontend/oxlint.json
index 50e482ecedd4..942965a865df 100644
--- a/superset-frontend/oxlint.json
+++ b/superset-frontend/oxlint.json
@@ -34,7 +34,8 @@
"no-unused-vars": "off",
"no-undef": "error",
"no-prototype-builtins": "off",
- "no-unsafe-optional-chaining": "off",
+ "no-unsafe-optional-chaining": "error",
+ "no-constant-binary-expression": "error",
"no-import-assign": "off",
"no-promise-executor-return": "off",
@@ -254,6 +255,7 @@
// === Unicorn rules (bonus coverage) ===
"unicorn/no-new-array": "error",
"unicorn/no-invalid-remove-event-listener": "error",
+ "unicorn/no-useless-length-check": "error",
"unicorn/filename-case": "off",
"unicorn/prevent-abbreviations": "off",
"unicorn/no-null": "off",
diff --git a/superset-frontend/packages/superset-ui-core/src/components/Layout/Layout.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/Layout/Layout.test.tsx
index 88a70ff9e6e9..0b24bdbc3767 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/Layout/Layout.test.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/Layout/Layout.test.tsx
@@ -47,9 +47,10 @@ describe('Layout Component', () => {
});
test('hides Header when headerVisible is false', () => {
+ const headerVisible = false;
render(
- {false && Header}
+ {headerVisible && Header}
Content Area
Ant Design Layout Footer
,
@@ -59,11 +60,14 @@ describe('Layout Component', () => {
});
test('hides Footer when footerVisible is false', () => {
+ const footerVisible = false;
render(
Header
Content Area
- {false && Ant Design Layout Footer}
+ {footerVisible && (
+ Ant Design Layout Footer
+ )}
,
);
diff --git a/superset-frontend/packages/superset-ui-core/src/components/Modal/Modal.tsx b/superset-frontend/packages/superset-ui-core/src/components/Modal/Modal.tsx
index 021341808e07..173ab6f83a23 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/Modal/Modal.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/Modal/Modal.tsx
@@ -280,7 +280,7 @@ const CustomModal = ({
const shouldShowMask = !(resizable || draggable);
const onDragStart = (_: DraggableEvent, uiData: DraggableData) => {
- const { clientWidth, clientHeight } = window?.document?.documentElement;
+ const { clientWidth, clientHeight } = document.documentElement;
const targetRect = draggableRef?.current?.getBoundingClientRect();
if (targetRect) {
diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/buildQuery.ts b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/buildQuery.ts
index 9212936686b6..8122c86f825c 100644
--- a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/buildQuery.ts
+++ b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/buildQuery.ts
@@ -606,7 +606,7 @@ const buildQuery: BuildQuery = (
{
...queryObject,
time_offsets: [],
- row_limit: Number(formData?.row_limit) ?? 0,
+ row_limit: Number(formData?.row_limit ?? 0),
row_offset: 0,
post_processing: [],
is_rowcount: true,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/BigNumber/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/BigNumber/transformProps.test.ts
index 3c681f281b09..66933c4f8137 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/BigNumber/transformProps.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/BigNumber/transformProps.test.ts
@@ -196,7 +196,9 @@ describe('BigNumberWithTrendline', () => {
showXAxis: true,
},
});
- expect((transformed.echartOptions?.xAxis as any).show).toBe(true);
+ expect((transformed.echartOptions!.xAxis as { show: boolean }).show).toBe(
+ true,
+ );
});
test('should not show X axis when showXAxis is false', () => {
@@ -207,7 +209,9 @@ describe('BigNumberWithTrendline', () => {
showXAxis: false,
},
});
- expect((transformed.echartOptions?.xAxis as any).show).toBe(false);
+ expect((transformed.echartOptions!.xAxis as { show: boolean }).show).toBe(
+ false,
+ );
});
test('should show Y axis when showYAxis is true', () => {
@@ -218,7 +222,9 @@ describe('BigNumberWithTrendline', () => {
showYAxis: true,
},
});
- expect((transformed.echartOptions?.yAxis as any).show).toBe(true);
+ expect((transformed.echartOptions!.yAxis as { show: boolean }).show).toBe(
+ true,
+ );
});
test('should not show Y axis when showYAxis is false', () => {
@@ -229,7 +235,9 @@ describe('BigNumberWithTrendline', () => {
showYAxis: false,
},
});
- expect((transformed.echartOptions?.yAxis as any).show).toBe(false);
+ expect((transformed.echartOptions!.yAxis as { show: boolean }).show).toBe(
+ false,
+ );
});
});
diff --git a/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts b/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
index 7b3a952d8915..c23a8a49c565 100644
--- a/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
+++ b/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
@@ -347,7 +347,7 @@ const buildQuery: BuildQuery = (
{
...queryObject,
time_offsets: [],
- row_limit: Number(formData?.row_limit) ?? 0,
+ row_limit: Number(formData?.row_limit ?? 0),
row_offset: 0,
post_processing: [],
is_rowcount: true,
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/state.ts
index f95c1bae4efa..ecbb56e47a06 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/state.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/state.ts
@@ -210,10 +210,9 @@ export function useIsFilterInScope() {
if (hasChartsInScope) {
isChartInScope = filter.chartsInScope!.some((chartId: number) => {
const tabParents = selectChartTabParents(chartId);
+ // Note: every() returns true for empty arrays, so length check is unnecessary
return (
- !tabParents ||
- tabParents.length === 0 ||
- tabParents.every(tab => activeTabs.includes(tab))
+ !tabParents || tabParents.every(tab => activeTabs.includes(tab))
);
});
}
@@ -276,10 +275,9 @@ export function useIsCustomizationInScope() {
customization.chartsInScope.length > 0 &&
customization.chartsInScope.some((chartId: number) => {
const tabParents = selectChartTabParents(chartId);
+ // Note: every() returns true for empty arrays, so length check is unnecessary
return (
- !tabParents ||
- tabParents.length === 0 ||
- tabParents.every(tab => activeTabs.includes(tab))
+ !tabParents || tabParents.every(tab => activeTabs.includes(tab))
);
});