mirror of
https://github.com/apache/superset.git
synced 2026-07-17 04:05:37 +00:00
Compare commits
5 Commits
chore/drop
...
mcp-delete
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
468ac195f0 | ||
|
|
af2392d0f4 | ||
|
|
50985f89f1 | ||
|
|
4bfbdecd11 | ||
|
|
cfc0515931 |
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -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:
|
||||
|
||||
2
.github/actions/setup-backend/action.yml
vendored
2
.github/actions/setup-backend/action.yml
vendored
@@ -32,6 +32,8 @@ runs:
|
||||
elif [ "$INPUT_PYTHON_VERSION" = "next" ]; then
|
||||
# currently disabled in GHA matrixes because of library compatibility issues
|
||||
RESOLVED_VERSION="3.12"
|
||||
elif [ "$INPUT_PYTHON_VERSION" = "previous" ]; then
|
||||
RESOLVED_VERSION="3.10"
|
||||
elif printf '%s' "$INPUT_PYTHON_VERSION" | grep -Eq '^[0-9]+\.[0-9]+(\.[0-9]+)?$'; then
|
||||
RESOLVED_VERSION="$INPUT_PYTHON_VERSION"
|
||||
else
|
||||
|
||||
2
.github/workflows/bump-python-package.yml
vendored
2
.github/workflows/bump-python-package.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
- name: Set up Python ${{ inputs.python-version }}
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install uv
|
||||
run: pip install uv
|
||||
|
||||
2
.github/workflows/check-python-deps.yml
vendored
2
.github/workflows/check-python-deps.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
||||
- name: Login to Docker Hub
|
||||
if: steps.check.outputs.python
|
||||
continue-on-error: true
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USER }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
4
.github/workflows/codeql-analysis.yml
vendored
4
.github/workflows/codeql-analysis.yml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -75,6 +75,6 @@ jobs:
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
11
.github/workflows/docker.yml
vendored
11
.github/workflows/docker.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
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
|
||||
|
||||
@@ -123,20 +123,13 @@ jobs:
|
||||
# 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" \
|
||||
--extra-flags "--build-arg INCLUDE_CHROMIUM=false --tag $IMAGE_TAG" \
|
||||
$PLATFORM_ARG; then
|
||||
break
|
||||
fi
|
||||
|
||||
2
.github/workflows/embedded-sdk-release.yml
vendored
2
.github/workflows/embedded-sdk-release.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
# 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@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./superset-embedded-sdk/.nvmrc"
|
||||
- run: npm ci
|
||||
|
||||
2
.github/workflows/embedded-sdk-test.yml
vendored
2
.github/workflows/embedded-sdk-test.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./superset-embedded-sdk/.nvmrc"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
2
.github/workflows/generate-FOSSA-report.yml
vendored
2
.github/workflows/generate-FOSSA-report.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "11"
|
||||
|
||||
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0
|
||||
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
|
||||
with:
|
||||
sync-labels: true
|
||||
|
||||
|
||||
2
.github/workflows/license-check.yml
vendored
2
.github/workflows/license-check.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "11"
|
||||
|
||||
4
.github/workflows/pre-commit.yml
vendored
4
.github/workflows/pre-commit.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
# 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: ${{ github.event_name == 'pull_request' && fromJSON('["current"]') || fromJSON('["current", "previous", "next"]') }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
run: go install github.com/norwoodj/helm-docs/cmd/helm-docs@v1.14.2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "superset-frontend/.nvmrc"
|
||||
cache: "npm"
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
||||
|
||||
- name: Install Node.js
|
||||
if: env.HAS_TAGS
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./superset-frontend/.nvmrc"
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ jobs:
|
||||
# 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"]
|
||||
build_preset: ["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: "Checkout release tag: ${{ needs.config.outputs.latest-release }}"
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
build: "true"
|
||||
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
|
||||
4
.github/workflows/superset-docs-deploy.yml
vendored
4
.github/workflows/superset-docs-deploy.yml
vendored
@@ -66,12 +66,12 @@ jobs:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./docs/.nvmrc"
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
- uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: "21"
|
||||
|
||||
4
.github/workflows/superset-docs-verify.yml
vendored
4
.github/workflows/superset-docs-verify.yml
vendored
@@ -78,7 +78,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./docs/.nvmrc"
|
||||
- name: yarn install
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./docs/.nvmrc"
|
||||
- name: yarn install
|
||||
|
||||
4
.github/workflows/superset-e2e.yml
vendored
4
.github/workflows/superset-e2e.yml
vendored
@@ -128,7 +128,7 @@ jobs:
|
||||
with:
|
||||
run: testdata
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./superset-frontend/.nvmrc"
|
||||
cache: "npm"
|
||||
@@ -238,7 +238,7 @@ jobs:
|
||||
with:
|
||||
run: playwright_testdata
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./superset-frontend/.nvmrc"
|
||||
cache: "npm"
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
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: ${{ github.event_name == 'pull_request' && fromJSON('["current"]') || fromJSON('["previous", "current", "next"]') }}
|
||||
defaults:
|
||||
run:
|
||||
working-directory: superset-extensions-cli
|
||||
|
||||
2
.github/workflows/superset-frontend.yml
vendored
2
.github/workflows/superset-frontend.yml
vendored
@@ -51,7 +51,7 @@ 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 \
|
||||
.
|
||||
|
||||
|
||||
2
.github/workflows/superset-playwright.yml
vendored
2
.github/workflows/superset-playwright.yml
vendored
@@ -114,7 +114,7 @@ jobs:
|
||||
with:
|
||||
run: playwright_testdata
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./superset-frontend/.nvmrc"
|
||||
cache: "npm"
|
||||
|
||||
@@ -135,7 +135,7 @@ jobs:
|
||||
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: ${{ github.event_name == 'pull_request' && fromJSON('["current"]') || fromJSON('["current", "previous", "next"]') }}
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
|
||||
@@ -50,15 +50,9 @@ jobs:
|
||||
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: ${{ github.event_name == 'pull_request' && fromJSON('["current"]') || fromJSON('["previous", "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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
2
.github/workflows/superset-translations.yml
vendored
2
.github/workflows/superset-translations.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outputs.frontend
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./superset-frontend/.nvmrc"
|
||||
cache: "npm"
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
- name: Login to Docker Hub
|
||||
if: ${{ steps.dependabot-metadata.outputs.package-ecosystem == 'pip' }}
|
||||
continue-on-error: true
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USER }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
6
.github/workflows/tag-release.yml
vendored
6
.github/workflows/tag-release.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
build_preset:
|
||||
["dev", "lean", "websocket", "dockerize", "py311", "py312"]
|
||||
["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
|
||||
- name: Use Node.js 20
|
||||
# zizmor: ignore[cache-poisoning] - node only runs the supersetbot CLI; no dependency cache is enabled
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version: 20
|
||||
package-manager-cache: false
|
||||
@@ -133,7 +133,7 @@ jobs:
|
||||
|
||||
- name: Use Node.js 20
|
||||
# zizmor: ignore[cache-poisoning] - node only runs the supersetbot CLI; no dependency cache is enabled
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version: 20
|
||||
package-manager-cache: false
|
||||
|
||||
2
.github/workflows/tech-debt.yml
vendored
2
.github/workflows/tech-debt.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version-file: "./superset-frontend/.nvmrc"
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ repos:
|
||||
hooks:
|
||||
- id: prettier-frontend
|
||||
name: prettier (frontend)
|
||||
entry: bash -c 'cd superset-frontend && files=(); for f in "$@"; do files+=("${f#superset-frontend/}"); done; npx prettier --write -- "${files[@]}"' --
|
||||
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)$
|
||||
@@ -81,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'
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
.codecov.yml
|
||||
.eslintrc
|
||||
.eslintignore
|
||||
.stylelintignore
|
||||
.flake8
|
||||
.nvmrc
|
||||
.prettierrc
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -641,7 +641,7 @@ categories:
|
||||
|
||||
- name: Région Hauts-de-France (France)
|
||||
url: https://www.geo2france.fr/
|
||||
logo: geo2france.png
|
||||
logo: geo2france.svg
|
||||
|
||||
- name: Rennes Métropole (France)
|
||||
url: https://metropole.rennes.fr/
|
||||
|
||||
28
UPDATING.md
28
UPDATING.md
@@ -24,13 +24,6 @@ assists people when migrating to a new version.
|
||||
|
||||
## Next
|
||||
|
||||
### Python 3.10 support removed
|
||||
|
||||
Python 3.10 is no longer supported. Superset now requires **Python 3.11 or higher**.
|
||||
Update your environment (virtualenv, Docker base image, CI configuration, etc.) to
|
||||
Python 3.11+ before upgrading. The `apache/superset-cache:3.10-slim-trixie` and
|
||||
`py310` Docker image variants are no longer published.
|
||||
|
||||
### Owners, dashboard roles, and RLS roles replaced by Subjects
|
||||
|
||||
Superset now uses subject-based access assignments for dashboards, charts, datasets,
|
||||
@@ -160,16 +153,6 @@ virtual-dataset SQL) raises a parse error in SQL Lab and dashboard-generated
|
||||
queries. Deployments that legitimately run queries above this size should raise
|
||||
the value, and `SQL_MAX_PARSE_LENGTH = None` disables the check entirely.
|
||||
|
||||
### Ant Design upgraded from v5 to v6
|
||||
|
||||
The frontend now builds against Ant Design 6, and `@superset-ui/core` / `@apache-superset/core` peer-depend on `antd ^6`. Custom plugins, extensions, and themes that interact with Ant Design need review:
|
||||
|
||||
- **Internal DOM classes were renamed**, so any custom CSS targeting `.ant-*` internals silently stops matching. Notable renames: `.ant-tabs-content-holder` → `.ant-tabs-body-holder`, `.ant-tabs-content` → `.ant-tabs-body`, `.ant-tabs-tabpane` → `.ant-tabs-content`; `.ant-select-selector` → `.ant-select-content`, `.ant-select-selection-placeholder` → `.ant-select-placeholder`, `.ant-select-arrow` → `.ant-select-suffix`; `.ant-tooltip-inner` → `.ant-tooltip-container`; `.ant-popover-inner` → `.ant-popover-container`; `.ant-steps-item-tail` → `.ant-steps-item-rail`.
|
||||
- **Some component props changed or were removed** — e.g. `Select` no longer accepts `dropdownAlign`, `visible`/`onVisibleChange` are `open`/`onOpenChange`, `Dropdown` `overlay` is `menu`, `Steps.Step` children are the `items` prop, and `styles.body` on Tooltip/Popover is `styles.container`.
|
||||
- **CSS variables are on by default** in antd 6, and `ThemeConfig.cssVar` no longer accepts a boolean; Superset theme configs using `cssVar: true`/`false` are coerced (`true` → `{}`, `false` → omitted).
|
||||
|
||||
Theme tokens are unaffected — antd 6 removed none of the tokens Superset exposes, so existing theme configurations continue to work. See the [Ant Design v6 migration guide](https://ant.design/docs/react/migration-v6) for the complete upstream list.
|
||||
|
||||
### Guest-token RLS rules reject unknown fields
|
||||
|
||||
The `rls` rules passed to `POST /api/v1/security/guest_token/` are now validated strictly: a rule may only contain `dataset` and `clause`. Previously unknown fields were silently dropped, so a mistyped or legacy scope key (most commonly `datasource` instead of `dataset`) produced a rule with no `dataset`, which is treated as a *global* rule applied to every dataset the embedded resource can reach. Such a request now returns HTTP 400 identifying the offending field instead of issuing a token with an unintended global rule. Integrators that were sending extra fields in RLS rules must remove them; valid dataset-scoped (`{"dataset": 41, "clause": "..."}`) and global (`{"clause": "..."}`) rules are unaffected.
|
||||
@@ -230,17 +213,6 @@ ALTER TABLE tagged_object DROP CONSTRAINT <constraint_name>;
|
||||
-- MySQL: find names via `SHOW CREATE TABLE tagged_object;`
|
||||
ALTER TABLE tagged_object DROP FOREIGN KEY <constraint_name>;
|
||||
```
|
||||
### Entity version-history infrastructure (gated off by default)
|
||||
|
||||
Introduces the schema and SQLAlchemy-Continuum wiring that captures version history for charts, dashboards, and datasets, plus read-only `GET /api/v1/{chart,dashboard,dataset}/<uuid>/versions/` endpoints. This ships **inert**: a new config flag `ENABLE_VERSIONING_CAPTURE` defaults to `False`, so no save writes any version rows and the endpoints return empty. It is an operational kill-switch (a release toggle that becomes a permanent ops switch), not a feature flag — set it to `True` to enable capture once validated. The migration is additive; existing entity `PUT` responses gain `old_version_uuid` / `new_version_uuid` body fields and an `ETag` header (both null/absent when capture is off).
|
||||
|
||||
A few save- and import-path internals change **unconditionally** (independent of the flag), because the versioned mappers must behave correctly whether or not capture is enabled:
|
||||
|
||||
- `DatasetDAO` column/metric updates move from bulk operations to per-row ORM operations, and a metadata refresh now preserves column primary keys via a natural-key (`column_name`) upsert instead of delete-and-reinsert — so charts that reference dataset columns by id keep working across a refresh (previously such references could be invalidated).
|
||||
- `ImportExportMixin.reset_ownership` stamps the current user onto `created_by`/`changed_by` when a request context is present (previously left null for the column default to fill).
|
||||
- `UpdateDashboardCommand` runs its body under `no_autoflush`.
|
||||
|
||||
These are behavior changes that take effect on upgrade regardless of `ENABLE_VERSIONING_CAPTURE`; no operator action is required.
|
||||
|
||||
### Webhook alerts/reports block private/internal hosts by default
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -38,7 +38,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}
|
||||
|
||||
@@ -99,7 +99,7 @@ See [Connecting AI Clients](#connecting-ai-clients) for Claude Code, Claude Web,
|
||||
## Prerequisites
|
||||
|
||||
- Apache Superset 5.0+ running and accessible
|
||||
- Python 3.11+
|
||||
- Python 3.10+
|
||||
- The `fastmcp` package (`pip install fastmcp`)
|
||||
|
||||
---
|
||||
@@ -529,7 +529,6 @@ MCP_RESPONSE_SIZE_CONFIG = {
|
||||
"enabled": True,
|
||||
"token_limit": 25000,
|
||||
"warn_threshold_pct": 80,
|
||||
"max_list_items": 100,
|
||||
"excluded_tools": [
|
||||
"health_check",
|
||||
"get_chart_preview",
|
||||
@@ -544,7 +543,6 @@ MCP_RESPONSE_SIZE_CONFIG = {
|
||||
| `enabled` | `True` | Enable response size checking |
|
||||
| `token_limit` | `25000` | Maximum estimated token count per response |
|
||||
| `warn_threshold_pct` | `80` | Warn when response exceeds this percentage of the limit |
|
||||
| `max_list_items` | `100` | Cap on list-field length (e.g. `charts`, `native_filters`) applied to the `get_*_info` tools before falling back to more aggressive truncation. Raised from a hardcoded 30 in earlier versions; the higher default only keeps more data before the same token-budget fallback kicks in, so it's not a breaking change, but tenants that tuned workflows around the old 30-item cap should lower this value explicitly. |
|
||||
| `excluded_tools` | See above | Tools exempt from size checking (e.g., tools that return URLs, not data) |
|
||||
|
||||
### Caching
|
||||
|
||||
@@ -379,7 +379,7 @@ functioning across environments.
|
||||
Make sure your machine meets the [OS dependencies](https://superset.apache.org/docs/installation/pypi#os-dependencies) before following these steps.
|
||||
You also need to install MySQL.
|
||||
|
||||
Ensure that you are using Python version 3.11 or 3.12, then proceed with:
|
||||
Ensure that you are using Python version 3.9, 3.10 or 3.11, then proceed with:
|
||||
|
||||
```bash
|
||||
# Create a virtual environment and activate it (recommended)
|
||||
|
||||
@@ -82,7 +82,7 @@ If applicable, add screenshots or recordings.
|
||||
|
||||
### Environment
|
||||
- Superset version: [e.g., 3.0.0]
|
||||
- Python version: [e.g., 3.11.7]
|
||||
- Python version: [e.g., 3.9.7]
|
||||
- Node version: [e.g., 18.17.0]
|
||||
- Database: [e.g., PostgreSQL 14]
|
||||
- Browser: [e.g., Chrome 120]
|
||||
@@ -125,7 +125,7 @@ No error messages in browser console or server logs.
|
||||
|
||||
### Environment
|
||||
- Superset version: 3.0.0
|
||||
- Python version: 3.11.16
|
||||
- Python version: 3.9.16
|
||||
- Database: PostgreSQL 14.9
|
||||
- Browser: Chrome 120.0.6099.71
|
||||
- OS: macOS 14.2
|
||||
|
||||
@@ -52,7 +52,7 @@ Everything you need to contribute to the Apache Superset project. This section i
|
||||
## Development Resources
|
||||
|
||||
### Prerequisites
|
||||
- **Python**: 3.11 or 3.12
|
||||
- **Python**: 3.9, 3.10, or 3.11
|
||||
- **Node.js**: 18.x or 20.x
|
||||
- **npm**: 9.x or 10.x
|
||||
- **Git**: Basic understanding
|
||||
|
||||
@@ -181,23 +181,6 @@ value in milliseconds in the JSON Metadata field:
|
||||
Here, the entire dashboard will refresh at once if periodic refresh is on. The stagger time of 2.5
|
||||
seconds is ignored.
|
||||
|
||||
The manual **Refresh dashboard** button can also stagger its chart requests, controlled by the
|
||||
`SUPERSET_DASHBOARD_MANUAL_REFRESH_STAGGER_MS` server config in `superset_config.py`. This defaults
|
||||
to `0`, which preserves the original behavior where every chart request fires at the same time when
|
||||
the button is clicked. To opt in to staggering, set a positive number of milliseconds; the window
|
||||
then becomes the larger of this value and the per-dashboard `stagger_time` metadata, which itself
|
||||
defaults to `5000` milliseconds when it is not set explicitly. Setting `stagger_refresh` to `false`
|
||||
in a dashboard's JSON Metadata also disables staggering on the manual-refresh path, so its charts
|
||||
fire all at once even when the server config is positive. If the backend does not provide a value at
|
||||
all, for example an older backend that predates this config or a value explicitly set to `None`, the
|
||||
frontend falls back to a built-in default of `5000` milliseconds.
|
||||
|
||||
```python
|
||||
# superset_config.py
|
||||
# 0 (the default) fires every chart at once; set a positive value to stagger.
|
||||
SUPERSET_DASHBOARD_MANUAL_REFRESH_STAGGER_MS = 0
|
||||
```
|
||||
|
||||
**Why does ‘flask fab’ or superset freeze/hang/not responding when started (my home directory is
|
||||
NFS mounted)?**
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"@swc/core": "^1.15.43",
|
||||
"antd": "^6.5.0",
|
||||
"baseline-browser-mapping": "^2.10.40",
|
||||
"caniuse-lite": "^1.0.30001803",
|
||||
"caniuse-lite": "^1.0.30001799",
|
||||
"docusaurus-plugin-openapi-docs": "^5.1.0",
|
||||
"docusaurus-theme-openapi-docs": "^5.1.0",
|
||||
"js-yaml": "^5.2.0",
|
||||
@@ -90,7 +90,7 @@
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/react": "^19.1.8",
|
||||
"@typescript-eslint/eslint-plugin": "^8.59.3",
|
||||
"@typescript-eslint/parser": "^8.63.0",
|
||||
"@typescript-eslint/parser": "^8.61.0",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.6",
|
||||
@@ -98,7 +98,7 @@
|
||||
"globals": "^17.7.0",
|
||||
"prettier": "^3.9.1",
|
||||
"typescript": "~6.0.3",
|
||||
"typescript-eslint": "^8.63.0",
|
||||
"typescript-eslint": "^8.62.0",
|
||||
"webpack": "^5.108.2"
|
||||
},
|
||||
"browserslist": {
|
||||
|
||||
160
docs/yarn.lock
160
docs/yarn.lock
@@ -5504,110 +5504,100 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@8.63.0", "@typescript-eslint/eslint-plugin@^8.59.3":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.63.0.tgz#0d85d0ec1a28b0e35f484cc8220a8bf084019e71"
|
||||
integrity sha512-rvwSgqT+DHpWdzfSzPatRLm02a0GlESt++9iy3hLCDY4BgkaLcl8LBi9Yh7XGFBpwcBE/K3024QuXWTpbz4FfQ==
|
||||
"@typescript-eslint/eslint-plugin@8.62.1", "@typescript-eslint/eslint-plugin@^8.59.3":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.62.1.tgz#1736dcdca6cae3359d818456a47d18b674761f7f"
|
||||
integrity sha512-4EQM77WgVNxj7OkL/5b/D/xZsw00G577+UriYTC7JF5opcF3T2AuoeY7ueLaZgSVjSgCS6yOAJB5bRGLPSJUzA==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.12.2"
|
||||
"@typescript-eslint/scope-manager" "8.63.0"
|
||||
"@typescript-eslint/type-utils" "8.63.0"
|
||||
"@typescript-eslint/utils" "8.63.0"
|
||||
"@typescript-eslint/visitor-keys" "8.63.0"
|
||||
"@typescript-eslint/scope-manager" "8.62.1"
|
||||
"@typescript-eslint/type-utils" "8.62.1"
|
||||
"@typescript-eslint/utils" "8.62.1"
|
||||
"@typescript-eslint/visitor-keys" "8.62.1"
|
||||
ignore "^7.0.5"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/parser@8.63.0", "@typescript-eslint/parser@^8.63.0":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.63.0.tgz#2993338c379903e6afc72c3532ae6e15b97334d4"
|
||||
integrity sha512-gwh4gvvlaVDKKxyfxMG+Gnu1u9X0OQBwyGLkbwB65dIzBKnxeRiJlNFqlI3zwVhNXJIs6qV7mlFCn/BIajlVig==
|
||||
"@typescript-eslint/parser@8.62.1", "@typescript-eslint/parser@^8.61.0":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.62.1.tgz#d3f7ba18f1bf78bfb7256fea021d1927b48e7080"
|
||||
integrity sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.63.0"
|
||||
"@typescript-eslint/types" "8.63.0"
|
||||
"@typescript-eslint/typescript-estree" "8.63.0"
|
||||
"@typescript-eslint/visitor-keys" "8.63.0"
|
||||
"@typescript-eslint/scope-manager" "8.62.1"
|
||||
"@typescript-eslint/types" "8.62.1"
|
||||
"@typescript-eslint/typescript-estree" "8.62.1"
|
||||
"@typescript-eslint/visitor-keys" "8.62.1"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/project-service@8.63.0":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.63.0.tgz#01a3d0550a860127444a9939749ab434591cd71a"
|
||||
integrity sha512-e5dh0/UI0ok53AlZ5wRkXCB32z/f2jUZqPR/ygAw5WYaSw8j9EoJWlS7wQjr/dmOaqWjnPIn2m+HhVPCMWGZVQ==
|
||||
"@typescript-eslint/project-service@8.62.1":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.62.1.tgz#78d880eb1cf6859b5ec263d04f95403e9f90ae47"
|
||||
integrity sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==
|
||||
dependencies:
|
||||
"@typescript-eslint/tsconfig-utils" "^8.63.0"
|
||||
"@typescript-eslint/types" "^8.63.0"
|
||||
"@typescript-eslint/tsconfig-utils" "^8.62.1"
|
||||
"@typescript-eslint/types" "^8.62.1"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.63.0":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.63.0.tgz#c9cf7ecd234f7ec346f62e5c7d28dfaf4d507b4d"
|
||||
integrity sha512-uUyfMWCnDSN8bCpcrY8nGP2BLkQ9Xn0GsipcONcpIDWhwhO4ZSyHvyS14U3X75mzxWxL3I2UZIrenTzdzcJO8A==
|
||||
"@typescript-eslint/scope-manager@8.62.1":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.62.1.tgz#7ee65e9a6eb3ccdc4816593a4ff38840306de88a"
|
||||
integrity sha512-r4d249KbQ1SFdpeStvob8Ih6aPPIzfqllPVOtvhve6ZcpuVcYo5/7zUWckKpHE7StASX4kTKZTLf0WQm/wPkcg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.63.0"
|
||||
"@typescript-eslint/visitor-keys" "8.63.0"
|
||||
"@typescript-eslint/types" "8.62.1"
|
||||
"@typescript-eslint/visitor-keys" "8.62.1"
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@8.63.0":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.63.0.tgz#f7e1cf9a029bb71f4027ffa4194ba82afb564cd3"
|
||||
integrity sha512-sUAbkulqBAsncKnbRP3+7CtQFRKicexnj7ZwNC6ddCR7EmrXvjvdCYMJbUIqMd6lwoEriZjwLo08aS5tSjVMHg==
|
||||
"@typescript-eslint/tsconfig-utils@8.62.1", "@typescript-eslint/tsconfig-utils@^8.62.1":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.1.tgz#e2b5f24fe721044189cb7e81117c96d75979d627"
|
||||
integrity sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@^8.63.0":
|
||||
version "8.64.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.64.0.tgz#c62ac8ea9173c3cac8b38b8e66e30a046b548851"
|
||||
integrity sha512-2yo8rRNKuzbVWQp5kslhANqZ2uDAeROQHBRZNPu8JDsHmeFNj/XJJhX/FhNUWmkHHvoNsKa6+tHJiig87EzsQw==
|
||||
|
||||
"@typescript-eslint/type-utils@8.63.0":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.63.0.tgz#9c00f362140186c588da86b3e10c212800b64b85"
|
||||
integrity sha512-Nzzh/OGxVCOjObjaj1CQF2RUasyYy2Jfuh+zZ3PjLzG2fYRriAiZLib9UKtO+CpQAS3YHiAS+ckZDclwqI1TPA==
|
||||
"@typescript-eslint/type-utils@8.62.1":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.62.1.tgz#ebd30b13bacb13070917259a23309cf644121f9a"
|
||||
integrity sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.63.0"
|
||||
"@typescript-eslint/typescript-estree" "8.63.0"
|
||||
"@typescript-eslint/utils" "8.63.0"
|
||||
"@typescript-eslint/types" "8.62.1"
|
||||
"@typescript-eslint/typescript-estree" "8.62.1"
|
||||
"@typescript-eslint/utils" "8.62.1"
|
||||
debug "^4.4.3"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/types@8.63.0":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.63.0.tgz#6b32b0a5913520554d81a986acfffba2d32b6963"
|
||||
integrity sha512-xyLtl9DUBBFrcJS4x2pIqGLH68/tC2uOa4Z7pUteW09D3bXnnXUom4dyPikzWgB7llmIc1zoeI3aoUdC4rPK/Q==
|
||||
"@typescript-eslint/types@8.62.1", "@typescript-eslint/types@^8.62.1":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.62.1.tgz#c58be954e483b2fc98275374d5bcb40b99842dc1"
|
||||
integrity sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q==
|
||||
|
||||
"@typescript-eslint/types@^8.63.0":
|
||||
version "8.64.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.64.0.tgz#b41f8ef5dd40616908658b991197a9d486cda60b"
|
||||
integrity sha512-qjhfuTfLXjA4IOzXvz0rTjT01BqEiIgPoUeMwiEjnaHKJMTNo8rH5pYW1a2L/0Dnux2fPC85AeyJoWaGa8WxTA==
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.63.0":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.63.0.tgz#a6f9c9cd290e98203ad29850b0d72529dc83be73"
|
||||
integrity sha512-ygBkU+B7ex5UI/gKhaqexWev79uISfIv7XQCRNYO/jmD8rGLPyWLAb3KMRT6nd8Gt9bmUBi9+iX6tBdYfOY81Q==
|
||||
"@typescript-eslint/typescript-estree@8.62.1":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.1.tgz#98c1bb17635d5b026b24193a8d29188ac64380ff"
|
||||
integrity sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==
|
||||
dependencies:
|
||||
"@typescript-eslint/project-service" "8.63.0"
|
||||
"@typescript-eslint/tsconfig-utils" "8.63.0"
|
||||
"@typescript-eslint/types" "8.63.0"
|
||||
"@typescript-eslint/visitor-keys" "8.63.0"
|
||||
"@typescript-eslint/project-service" "8.62.1"
|
||||
"@typescript-eslint/tsconfig-utils" "8.62.1"
|
||||
"@typescript-eslint/types" "8.62.1"
|
||||
"@typescript-eslint/visitor-keys" "8.62.1"
|
||||
debug "^4.4.3"
|
||||
minimatch "^10.2.2"
|
||||
semver "^7.7.3"
|
||||
tinyglobby "^0.2.15"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/utils@8.63.0":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.63.0.tgz#b6a6c8aff1cebd1de4410b3a42b7ec9ba6703f23"
|
||||
integrity sha512-fUKaeAvrTuQg/Tgt3nliAUSZHJM6DlCcfyEmxCvlX8kieWSStBX+5O5Fnidtc3i2JrH+9c/GL4RY2iasd/GPTA==
|
||||
"@typescript-eslint/utils@8.62.1":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.62.1.tgz#1622b75c7e6df308181dd0b44855dc4228da0457"
|
||||
integrity sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.9.1"
|
||||
"@typescript-eslint/scope-manager" "8.63.0"
|
||||
"@typescript-eslint/types" "8.63.0"
|
||||
"@typescript-eslint/typescript-estree" "8.63.0"
|
||||
"@typescript-eslint/scope-manager" "8.62.1"
|
||||
"@typescript-eslint/types" "8.62.1"
|
||||
"@typescript-eslint/typescript-estree" "8.62.1"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.63.0":
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.63.0.tgz#2853a8e33b52f23570338f96cc89cb223daabd44"
|
||||
integrity sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==
|
||||
"@typescript-eslint/visitor-keys@8.62.1":
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.1.tgz#499657d77ffafb8a99eb1d6c97847ca430234722"
|
||||
integrity sha512-4g3BLxfdTMy8iZG0MaBkadnlRrCJ74cQiFbyEVMrkwIoqdyaXXQM22cotDvrl4x28wgIZ9rEJRoM+mmhSJpJ1g==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.63.0"
|
||||
"@typescript-eslint/types" "8.62.1"
|
||||
eslint-visitor-keys "^5.0.0"
|
||||
|
||||
"@ungap/structured-clone@^1.0.0":
|
||||
@@ -6577,10 +6567,10 @@ caniuse-api@^3.0.0:
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001799, caniuse-lite@^1.0.30001803:
|
||||
version "1.0.30001803"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001803.tgz#b2a5d696e042bc8304dcd4942c39fe330fbbcb24"
|
||||
integrity sha512-g/uHREV2ZpK9qMalCsWaxmA6ol+DX8GYhuf3T40RKoP+oL7vhRJh8LNt73PCjpnR6l14FzfPrB5Yux4PKm2meg==
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001799:
|
||||
version "1.0.30001800"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001800.tgz#b896c773e1c39400809415162bb5320371291b36"
|
||||
integrity sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==
|
||||
|
||||
ccount@^2.0.0:
|
||||
version "2.0.1"
|
||||
@@ -15272,15 +15262,15 @@ types-ramda@^0.30.1:
|
||||
dependencies:
|
||||
ts-toolbelt "^9.6.0"
|
||||
|
||||
typescript-eslint@^8.63.0:
|
||||
version "8.63.0"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.63.0.tgz#1c2b65c989572af7113fbae7f54c7ffab0fbeb12"
|
||||
integrity sha512-xgwXyzG4sK9ALkBxbyGkTMMOS+imnW65iPhxCQMK83KhxyoDNW7l+IDqEf9vMdoUidHpOoS967RCq4eMiTexwQ==
|
||||
typescript-eslint@^8.62.0:
|
||||
version "8.62.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.62.1.tgz#eb93fd94d527aa04ec5b844fb0b4ada613cc7d3f"
|
||||
integrity sha512-vymnnM5g0AKQDSAyfP12nMIBvgwgA42syg74kkuZ4x1VuTzwQKwc5h9rGxeShCjny5o+zWAb6OEoz7XLgrIkIw==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "8.63.0"
|
||||
"@typescript-eslint/parser" "8.63.0"
|
||||
"@typescript-eslint/typescript-estree" "8.63.0"
|
||||
"@typescript-eslint/utils" "8.63.0"
|
||||
"@typescript-eslint/eslint-plugin" "8.62.1"
|
||||
"@typescript-eslint/parser" "8.62.1"
|
||||
"@typescript-eslint/typescript-estree" "8.62.1"
|
||||
"@typescript-eslint/utils" "8.62.1"
|
||||
|
||||
typescript@~6.0.3:
|
||||
version "6.0.3"
|
||||
|
||||
@@ -29,7 +29,7 @@ maintainers:
|
||||
- name: craig-rueda
|
||||
email: craig@craigrueda.com
|
||||
url: https://github.com/craig-rueda
|
||||
version: 0.20.0 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
|
||||
version: 0.19.0 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: 16.7.27
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -74,42 +74,10 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
|
||||
|-----|------|---------|-------------|
|
||||
| affinity | object | `{}` | |
|
||||
| bootstrapScript | string | see `values.yaml` | Install additional packages and do any other bootstrap configuration in this script For production clusters it's recommended to build own image with this step done in CI |
|
||||
| cache | object | `{"asyncQueries":{"keyPrefix":"qc-","timeout":86400},"cacheDb":null,"cacheUrl":null,"celeryDb":null,"celeryUrl":null,"defaultTimeout":86400,"driver":"","enabled":true,"host":null,"keyPrefix":"superset_","password":null,"port":null,"resultsBackendKeyPrefix":"superset_results","sentinel":null,"ssl":{"ca_certs":null,"certfile":null,"enabled":false,"keyfile":null,"ssl_cert_reqs":"required"},"user":""}` | Redis cache configuration for Superset Redis is optional but recommended for caching and Celery. If redis.enabled (chart dependency) is true, defaults point to the chart's Redis instance. |
|
||||
| cache.asyncQueries | object | `{"keyPrefix":"qc-","timeout":86400}` | Async queries configuration |
|
||||
| cache.cacheDb | string | `nil` | Redis database number for cache (default: 1 when unset; legacy redis_cache_db is honored) |
|
||||
| cache.cacheUrl | string | `nil` | Full Redis cache URL (overrides host/port/user/pass if set) |
|
||||
| cache.celeryDb | string | `nil` | Redis database number for Celery (default: 0 when unset; legacy redis_celery_db is honored) |
|
||||
| cache.celeryUrl | string | `nil` | Full Redis Celery URL (overrides host/port/user/pass if set) |
|
||||
| cache.defaultTimeout | int | `86400` | Default cache timeout in seconds |
|
||||
| cache.driver | string | `""` | Custom Redis driver (e.g. TLS/managed variants); overrides the redis proto in URLs when set. Ports the legacy supersetNode.connections.redis_driver escape hatch. |
|
||||
| cache.enabled | bool | `true` | Enable Redis-based features (cache, Celery). Set to false to disable Redis usage entirely. |
|
||||
| cache.host | string | `nil` | Redis host (default: {{ .Release.Name }}-redis-headless) |
|
||||
| cache.keyPrefix | string | `"superset_"` | Cache key prefix |
|
||||
| cache.password | string | `nil` | Redis password |
|
||||
| cache.port | string | `nil` | Redis port (default: 6379 when unset; legacy supersetNode.connections.redis_port is honored) |
|
||||
| cache.resultsBackendKeyPrefix | string | `"superset_results"` | Results backend key prefix |
|
||||
| cache.sentinel | string | `nil` | Redis Sentinel configuration (optional) |
|
||||
| cache.ssl | object | `{"ca_certs":null,"certfile":null,"enabled":false,"keyfile":null,"ssl_cert_reqs":"required"}` | Redis SSL configuration |
|
||||
| cache.user | string | `""` | Redis user (optional, for Redis ACL) |
|
||||
| cluster | object | `{"databaseServiceName":null,"domain":".svc.cluster.local","redisServiceName":null,"websocketServiceName":null}` | Kubernetes cluster configuration Used for constructing service URLs between chart components |
|
||||
| cluster.databaseServiceName | string | `nil` | Database service name (default: {{ .Release.Name }}-postgresql) Override if using a different service name for the database |
|
||||
| cluster.domain | string | `".svc.cluster.local"` | Kubernetes cluster domain (default: .svc.cluster.local) Override if using a custom cluster domain |
|
||||
| cluster.redisServiceName | string | `nil` | Redis service name (default: {{ .Release.Name }}-redis-headless) Override if using a different service name for Redis |
|
||||
| cluster.websocketServiceName | string | `nil` | WebSocket service name (default: {{ .Release.Name }}-ws) Override if using a different service name for the WebSocket service |
|
||||
| config | object | `{}` | Superset configuration properties Set any configuration property from superset/config.py here See https://github.com/apache/superset/blob/master/superset/config.py for all available options |
|
||||
| configFromSecret | string | `"{{ template \"superset.fullname\" . }}-config"` | The name of the secret which we will use to generate a superset_config.py file Note: this secret must have the key superset_config.py in it and can include other files as well |
|
||||
| configMountPath | string | `"/app/pythonpath"` | |
|
||||
| configOverrides | object | `{}` | A dictionary of overrides to append at the end of superset_config.py - the name does not matter WARNING: the order is not guaranteed Files can be passed as helm --set-file configOverrides.my-override=my-file.py |
|
||||
| configOverridesFiles | object | `{}` | Same as above but the values are files |
|
||||
| database | object | `{"driver":null,"host":null,"name":null,"password":null,"port":null,"ssl":{"enabled":false,"mode":"require"},"uri":null,"user":null}` | Database connection configuration for the Superset metadata database |
|
||||
| database.driver | string | `nil` | Database driver used when uri is not set (default: postgresql+psycopg2 when unset; legacy supersetNode.connections.db_type is honored when this is unset) |
|
||||
| database.host | string | `nil` | Database host (default: {{ .Release.Name }}-postgresql) |
|
||||
| database.name | string | `nil` | Database name (default: superset, resolved via superset.db.name) |
|
||||
| database.password | string | `nil` | Database password (default: superset, resolved via superset.db.password) ⚠️ CHANGE THIS for production |
|
||||
| database.port | string | `nil` | Database port (default: 5432 when unset; legacy supersetNode.connections.db_port is honored) |
|
||||
| database.ssl | object | `{"enabled":false,"mode":"require"}` | Database SSL configuration |
|
||||
| database.uri | string | `nil` | Full database URI (overrides host/port/user/pass/name if set) Example: "postgresql+psycopg2://user:pass@host:5432/dbname" |
|
||||
| database.user | string | `nil` | Database user (default: superset, resolved via superset.db.user) |
|
||||
| envFromSecret | string | `"{{ template \"superset.fullname\" . }}-env"` | The name of the secret which we will use to populate env vars in deployed pods This can be useful for secret keys, etc. |
|
||||
| envFromSecrets | list | `[]` | This can be a list of templated strings |
|
||||
| extraConfigMountPath | string | `"/app/configs"` | |
|
||||
@@ -121,9 +89,7 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
|
||||
| extraSecrets | object | `{}` | Extra files to be mounted as Secrets on the path specified in `configMountPath` |
|
||||
| extraVolumeMounts | list | `[]` | |
|
||||
| extraVolumes | list | `[]` | |
|
||||
| featureFlags | object | `{}` | Feature flags configuration See https://github.com/apache/superset/blob/master/RESOURCES/FEATURE_FLAGS.md |
|
||||
| fullnameOverride | string | `nil` | Provide a name to override the full names of resources |
|
||||
| globalPodAnnotations | object | `{}` | Global pod annotations to be added to all pods Use this to set annotations that apply to all Superset components Component-specific podAnnotations will be merged with these global annotations |
|
||||
| hostAliases | list | `[]` | Custom hostAliases for all superset pods # https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ |
|
||||
| image.pullPolicy | string | `"IfNotPresent"` | |
|
||||
| image.repository | string | `"apachesuperset.docker.scarf.sh/apache/superset"` | |
|
||||
@@ -150,7 +116,7 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
|
||||
| init.enabled | bool | `true` | |
|
||||
| init.extraContainers | list | `[]` | Launch additional containers into init job pod |
|
||||
| init.initContainers | list | a container waiting for postgres | List of initContainers |
|
||||
| init.initscript | string | unused; kept for backwards-compatibility only | DEPRECATED: this field is no longer used by the chart. The init script is rendered entirely from the internal `superset.initScript` template (which runs `superset db upgrade`, `superset init`, admin creation, and examples). Any customization placed here is silently ignored. See UPGRADING.md. |
|
||||
| init.initscript | string | a script to create admin user and initialize roles | A Superset init script |
|
||||
| init.jobAnnotations."helm.sh/hook" | string | `"post-install,post-upgrade"` | |
|
||||
| init.jobAnnotations."helm.sh/hook-delete-policy" | string | `"before-hook-creation"` | |
|
||||
| init.loadExamples | bool | `false` | |
|
||||
@@ -177,7 +143,6 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
|
||||
| service.type | string | `"ClusterIP"` | |
|
||||
| serviceAccount.annotations | object | `{}` | |
|
||||
| serviceAccount.create | bool | `false` | Create custom service account for Superset. If create: true and serviceAccountName is not provided, `superset.fullname` will be used. |
|
||||
| serviceAccount.name | string | `""` | Service account name to use (if not specified, defaults to release name + chart name) |
|
||||
| serviceAccountName | string | `nil` | Specify service account name to be used |
|
||||
| supersetCeleryBeat.affinity | object | `{}` | Affinity to be added to supersetCeleryBeat deployment |
|
||||
| supersetCeleryBeat.command | list | a `celery beat` command | Command |
|
||||
@@ -249,7 +214,20 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
|
||||
| supersetNode.autoscaling.minReplicas | int | `1` | |
|
||||
| supersetNode.autoscaling.targetCPUUtilizationPercentage | int | `80` | |
|
||||
| supersetNode.command | list | See `values.yaml` | Startup command |
|
||||
| supersetNode.connections | object | `{}` | |
|
||||
| supersetNode.connections.db_host | string | `"{{ .Release.Name }}-postgresql"` | |
|
||||
| supersetNode.connections.db_name | string | `"superset"` | |
|
||||
| supersetNode.connections.db_pass | string | `"superset"` | |
|
||||
| supersetNode.connections.db_port | string | `"5432"` | |
|
||||
| supersetNode.connections.db_type | string | `"postgresql"` | Database type for Superset metadata (Supported types: "postgresql", "mysql") |
|
||||
| supersetNode.connections.db_user | string | `"superset"` | |
|
||||
| supersetNode.connections.redis_cache_db | string | `"1"` | |
|
||||
| supersetNode.connections.redis_celery_db | string | `"0"` | |
|
||||
| supersetNode.connections.redis_driver | string | `""` | |
|
||||
| supersetNode.connections.redis_host | string | `"{{ .Release.Name }}-redis-headless"` | Change in case of bringing your own redis and then also set redis.enabled:false |
|
||||
| supersetNode.connections.redis_port | string | `"6379"` | |
|
||||
| supersetNode.connections.redis_ssl.enabled | bool | `false` | |
|
||||
| supersetNode.connections.redis_ssl.ssl_cert_reqs | string | `"CERT_NONE"` | |
|
||||
| supersetNode.connections.redis_user | string | `""` | |
|
||||
| supersetNode.containerSecurityContext | object | `{}` | |
|
||||
| supersetNode.deploymentAdditionalPodSpec | object | `{}` | Custom pod spec to be added to supersetNode deployment |
|
||||
| supersetNode.deploymentAnnotations | object | `{}` | Annotations to be added to supersetNode deployment |
|
||||
@@ -356,11 +334,6 @@ Alternatively, perform a fresh install. This is a one-time migration; subsequent
|
||||
| supersetWorker.deploymentLabels | object | `{}` | Labels to be added to supersetWorker deployment |
|
||||
| supersetWorker.extraContainers | list | `[]` | Launch additional containers into supersetWorker pod |
|
||||
| supersetWorker.forceReload | bool | `false` | If true, forces deployment to reload on each upgrade |
|
||||
| supersetWorker.healthCheck | object | `{"enabled":false,"livenessFile":"/tmp/celery_worker_alive","livenessHeartbeatInterval":10,"readinessFile":"/tmp/celery_worker_ready"}` | Celery worker file-based health check (worker writes readiness/liveness files via signals; point supersetWorker.readinessProbe/livenessProbe at these files to use them) |
|
||||
| supersetWorker.healthCheck.enabled | bool | `false` | Enable the file-based Celery worker health check |
|
||||
| supersetWorker.healthCheck.livenessFile | string | `"/tmp/celery_worker_alive"` | Liveness file (touched periodically by a heartbeat thread) |
|
||||
| supersetWorker.healthCheck.livenessHeartbeatInterval | int | `10` | Seconds between liveness heartbeats |
|
||||
| supersetWorker.healthCheck.readinessFile | string | `"/tmp/celery_worker_ready"` | Readiness file (created when the worker is ready, removed on shutdown) |
|
||||
| supersetWorker.initContainers | list | a container waiting for postgres and redis | Init container |
|
||||
| supersetWorker.lifecycle | object | `{}` | Container lifecycle hooks for the worker pod |
|
||||
| supersetWorker.livenessProbe.exec.command | list | a `celery inspect ping` command | Liveness probe command |
|
||||
|
||||
@@ -1,161 +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.
|
||||
-->
|
||||
|
||||
# Upgrading the Superset Helm Chart
|
||||
|
||||
## Upgrading to chart 0.20.0
|
||||
|
||||
Chart 0.20.0 introduces a structured connection schema. The old keys listed below are **DEPRECATED** — they still work (auto-mapped to the new keys at render time) and a deprecation warning is printed in `helm install`/`helm upgrade` NOTES, but they will be removed in a future release. Migrate as soon as possible.
|
||||
|
||||
### 1. Connection schema: `supersetNode.connections.*` → `database.*` / `cache.*`
|
||||
|
||||
**Before (deprecated — still honored):**
|
||||
|
||||
```yaml
|
||||
supersetNode:
|
||||
connections:
|
||||
db_host: "pg-host"
|
||||
db_port: "5432"
|
||||
db_user: "superset"
|
||||
db_pass: "superset"
|
||||
db_name: "superset"
|
||||
redis_host: "redis-host"
|
||||
redis_port: "6379"
|
||||
redis_cache_db: "1"
|
||||
redis_celery_db: "0"
|
||||
redis_driver: "rediss"
|
||||
```
|
||||
|
||||
**After (new structured keys — recommended):**
|
||||
|
||||
```yaml
|
||||
database:
|
||||
host: "pg-host"
|
||||
port: 5432
|
||||
user: "superset"
|
||||
password: "superset"
|
||||
name: "superset"
|
||||
|
||||
cache:
|
||||
host: "redis-host"
|
||||
port: 6379
|
||||
cacheDb: 1
|
||||
celeryDb: 0
|
||||
driver: "rediss" # optional: custom Redis driver / TLS variant
|
||||
```
|
||||
|
||||
Key-by-key mapping summary:
|
||||
|
||||
| Old key | New key |
|
||||
|---|---|
|
||||
| `supersetNode.connections.db_host` | `database.host` |
|
||||
| `supersetNode.connections.db_port` | `database.port` |
|
||||
| `supersetNode.connections.db_user` | `database.user` |
|
||||
| `supersetNode.connections.db_pass` | `database.password` |
|
||||
| `supersetNode.connections.db_name` | `database.name` |
|
||||
| `supersetNode.connections.redis_host` | `cache.host` |
|
||||
| `supersetNode.connections.redis_port` | `cache.port` |
|
||||
| `supersetNode.connections.redis_cache_db` | `cache.cacheDb` |
|
||||
| `supersetNode.connections.redis_celery_db` | `cache.celeryDb` |
|
||||
| `supersetNode.connections.redis_driver` | `cache.driver` |
|
||||
|
||||
### 2. Service account: root `serviceAccountName` → `serviceAccount.name`
|
||||
|
||||
**Before (deprecated — still honored):**
|
||||
|
||||
```yaml
|
||||
serviceAccountName: my-sa
|
||||
```
|
||||
|
||||
**After (new key — recommended):**
|
||||
|
||||
```yaml
|
||||
serviceAccount:
|
||||
name: my-sa
|
||||
```
|
||||
|
||||
### 3. Init script: `init.initscript` is deprecated and replaced by the built-in template
|
||||
|
||||
> **This is a behavior change.** The chart no longer uses `init.initscript`. The init script is rendered
|
||||
> entirely from an internal chart template (`superset.initScript`), which runs the full initialization
|
||||
> sequence:
|
||||
>
|
||||
> 1. `superset db upgrade` — applies all pending database schema migrations
|
||||
> 2. `superset init` — initializes roles and permissions
|
||||
> 3. Admin user creation (when `init.createAdmin: true`)
|
||||
> 4. Example data loading (when `init.loadExamples: true`)
|
||||
> 5. Datasource import (when `import_datasources.yaml` is present)
|
||||
>
|
||||
> A future PR will optionally split the database migration step into a dedicated upgrade Job for
|
||||
> zero-downtime deployments. Until that PR lands, migrations run as part of the init Job above.
|
||||
|
||||
If you customized `init.initscript` in your `values.yaml`, that customization is silently ignored.
|
||||
Move any customizations to `config` or `configOverrides`:
|
||||
|
||||
```yaml
|
||||
# Move custom Python config here:
|
||||
config:
|
||||
MY_SETTING: "value"
|
||||
|
||||
configOverrides:
|
||||
my_custom_override: |
|
||||
# Python snippet appended to superset_config.py
|
||||
MY_SETTING = "value"
|
||||
```
|
||||
|
||||
If your use case cannot be covered by `config` or `configOverrides`, please open an issue so the maintainers
|
||||
can evaluate extending the template.
|
||||
|
||||
### 4. New top-level sections: `config.*` and `featureFlags.*`
|
||||
|
||||
Two new sections provide direct Superset configuration passthrough without needing raw `configOverrides`.
|
||||
|
||||
**`config.*` — direct Superset config properties:**
|
||||
|
||||
```yaml
|
||||
config:
|
||||
SECRET_KEY: "$(SUPERSET_SECRET_KEY)"
|
||||
ROW_LIMIT: 50000
|
||||
WTF_CSRF_ENABLED: true
|
||||
SQLALCHEMY_POOL_SIZE: 10
|
||||
```
|
||||
|
||||
Each key is injected verbatim into `superset_config.py`. String values are quoted; non-string values
|
||||
(integers, booleans) are rendered as-is.
|
||||
|
||||
**`featureFlags.*` — feature flag overrides:**
|
||||
|
||||
```yaml
|
||||
featureFlags:
|
||||
ALERT_REPORTS: true
|
||||
DASHBOARD_RBAC: true
|
||||
ENABLE_TEMPLATE_PROCESSING: false
|
||||
```
|
||||
|
||||
This is equivalent to setting `FEATURE_FLAGS = {...}` in `superset_config.py`, but is more readable and
|
||||
schema-validated.
|
||||
|
||||
### 5. `values.schema.json` — early validation
|
||||
|
||||
The chart now ships a `values.schema.json` that validates the values you provide. Wrong types (e.g., a string
|
||||
where an integer is expected) or unknown keys in structured sections will cause `helm install`/`helm upgrade`
|
||||
to fail immediately with a descriptive error instead of producing a broken deployment.
|
||||
|
||||
If you get a validation error after upgrading, check that your overridden values match the types documented in
|
||||
`values.yaml` and the schema.
|
||||
@@ -35,9 +35,3 @@
|
||||
echo "Visit http://127.0.0.1:8088 to use your application"
|
||||
kubectl port-forward service/superset 8088:8088 --namespace {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
{{- $warnings := include "superset.deprecationWarnings" . }}
|
||||
{{- if trim $warnings }}
|
||||
|
||||
⚠️ DEPRECATION WARNINGS
|
||||
{{ $warnings }}
|
||||
{{- end }}
|
||||
|
||||
@@ -47,12 +47,11 @@ If release name contains chart name it will be used as a full name.
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "superset.serviceAccountName" -}}
|
||||
{{- $name := coalesce .Values.serviceAccount.name .Values.serviceAccountName -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{- default (include "superset.fullname" .) $name -}}
|
||||
{{- else -}}
|
||||
{{- default "default" $name -}}
|
||||
{{- end -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{- default (include "superset.fullname" .) .Values.serviceAccountName -}}
|
||||
{{- else -}}
|
||||
{{- default "default" .Values.serviceAccountName -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
@@ -106,572 +105,80 @@ app.kubernetes.io/component: {{ .component }}
|
||||
{{- end -}}
|
||||
|
||||
|
||||
{{/*
|
||||
Coalescing resolvers for DB and Redis connection parameters.
|
||||
Each resolver checks (in order):
|
||||
1. New top-level database.* / cache.* values
|
||||
2. Legacy supersetNode.connections.* keys (deprecation path, using safe index to avoid errors on absent maps)
|
||||
3. cluster.* service name overrides
|
||||
4. Hard-coded defaults derived from the release name
|
||||
Call with root context: {{ include "superset.db.host" . }}
|
||||
*/}}
|
||||
|
||||
{{/*
|
||||
Helper to safely read .Values.supersetNode.connections.<key> without erroring when maps are absent.
|
||||
*/}}
|
||||
{{- define "_superset.legacyConn" -}}
|
||||
{{- $sn := index .Values "supersetNode" | default dict -}}
|
||||
{{- $conn := index $sn "connections" | default dict -}}
|
||||
{{- $conn | toJson -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.db.host" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- tpl (coalesce .Values.database.host (index $conn "db_host") .Values.cluster.databaseServiceName (printf "%s-postgresql" .Release.Name)) $ -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.db.port" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- if .Values.database.port -}}
|
||||
{{- .Values.database.port | toString -}}
|
||||
{{- else -}}
|
||||
{{- coalesce (index $conn "db_port") "5432" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.db.user" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- coalesce .Values.database.user (index $conn "db_user") "superset" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.db.password" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- coalesce .Values.database.password (index $conn "db_pass") "superset" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.db.name" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- coalesce .Values.database.name (index $conn "db_name") "superset" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.db.driver" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- coalesce .Values.database.driver (index $conn "db_type") "postgresql+psycopg2" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.redis.host" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- tpl (coalesce .Values.cache.host (index $conn "redis_host") .Values.cluster.redisServiceName (printf "%s-redis-headless" .Release.Name)) $ -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.redis.port" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- if .Values.cache.port -}}
|
||||
{{- .Values.cache.port | toString -}}
|
||||
{{- else -}}
|
||||
{{- coalesce (index $conn "redis_port") "6379" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.redis.user" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- coalesce .Values.cache.user (index $conn "redis_user") "" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.redis.password" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- coalesce .Values.cache.password (index $conn "redis_password") "" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.redis.cacheDb" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- if not (kindIs "invalid" .Values.cache.cacheDb) -}}
|
||||
{{- .Values.cache.cacheDb | toString -}}
|
||||
{{- else -}}
|
||||
{{- coalesce (index $conn "redis_cache_db") "1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.redis.celeryDb" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- if not (kindIs "invalid" .Values.cache.celeryDb) -}}
|
||||
{{- .Values.cache.celeryDb | toString -}}
|
||||
{{- else -}}
|
||||
{{- coalesce (index $conn "redis_celery_db") "0" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.redis.proto" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- if .Values.cache.driver }}{{ .Values.cache.driver }}{{- else if index $conn "redis_driver" }}{{ index $conn "redis_driver" }}{{- else if .Values.cache.ssl.enabled }}rediss{{- else }}redis{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.config" }}
|
||||
{{- /* SECURITY: Validate admin password is set if admin creation is enabled */}}
|
||||
{{- if and .Values.init.createAdmin (or (not .Values.init.adminUser.password) (eq .Values.init.adminUser.password "")) }}
|
||||
{{- fail "SECURITY ERROR: init.createAdmin is true but init.adminUser.password is empty. You must set a secure password using --set init.adminUser.password='your-password' or via external secret." }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "superset-config" }}
|
||||
import os
|
||||
import json
|
||||
from urllib.parse import quote
|
||||
{{- if or .Values.config.cacheConfig .Values.config.dataCacheConfig .Values.config.resultsBackend .Values.config.celeryConfig .Values.cache.enabled }}
|
||||
from flask_caching.backends.rediscache import RedisCache
|
||||
{{- end }}
|
||||
|
||||
def env(key, default=None):
|
||||
return os.getenv(key, default)
|
||||
|
||||
{{- /* Database Configuration - Superset always requires a database */}}
|
||||
{{- if .Values.database.uri }}
|
||||
SQLALCHEMY_DATABASE_URI = {{ .Values.database.uri | quote }}
|
||||
# Redis Base URL
|
||||
{{- if .Values.supersetNode.connections.redis_password }}
|
||||
REDIS_BASE_URL=f"{env('REDIS_DRIVER') or env('REDIS_PROTO')}://{env('REDIS_USER', '')}:{env('REDIS_PASSWORD')}@{env('REDIS_HOST')}:{env('REDIS_PORT')}"
|
||||
{{- else }}
|
||||
{{- $driver := include "superset.db.driver" . }}
|
||||
{{- $sslParams := "" }}
|
||||
{{- if and (hasKey .Values.database "ssl") .Values.database.ssl.enabled }}
|
||||
{{- $sslMode := .Values.database.ssl.mode | default "require" }}
|
||||
{{- $sslParams = printf "?sslmode=%s" $sslMode }}
|
||||
{{- end }}
|
||||
SQLALCHEMY_DATABASE_URI = f"{{ $driver }}://{quote(env('DB_USER', ''), safe='')}:{quote(env('DB_PASS', ''), safe='')}@{env('DB_HOST')}:{env('DB_PORT')}/{env('DB_NAME')}{{ $sslParams }}"
|
||||
{{- end }}
|
||||
{{- if hasKey .Values.config "SQLALCHEMY_TRACK_MODIFICATIONS" }}
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = {{ .Values.config.SQLALCHEMY_TRACK_MODIFICATIONS | toString | title }}
|
||||
{{- else }}
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
REDIS_BASE_URL=f"{env('REDIS_DRIVER') or env('REDIS_PROTO')}://{env('REDIS_HOST')}:{env('REDIS_PORT')}"
|
||||
{{- end }}
|
||||
|
||||
{{- /* Redis Configuration - only if Redis cache is configured */}}
|
||||
{{- if .Values.cache.enabled }}
|
||||
{{- if .Values.cache.cacheUrl }}
|
||||
CACHE_REDIS_URL = {{ .Values.cache.cacheUrl | quote }}
|
||||
{{- else }}
|
||||
{{- $useSSL := and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
|
||||
_redis_user = quote(env('REDIS_USER', ''), safe='')
|
||||
_redis_password = quote(env('REDIS_PASSWORD', ''), safe='')
|
||||
_redis_auth = f"{_redis_user}:{_redis_password}@" if (_redis_user or _redis_password) else ""
|
||||
REDIS_BASE_URL = f"{{ include "superset.redis.proto" . }}://{_redis_auth}{env('REDIS_HOST')}:{env('REDIS_PORT')}"
|
||||
{{- if $useSSL }}
|
||||
{{- $sslCertReqs := .Values.cache.ssl.ssl_cert_reqs | default "required" }}
|
||||
REDIS_URL_PARAMS = f"?ssl_cert_reqs={{ $sslCertReqs }}"
|
||||
# Redis URL Params
|
||||
{{- if .Values.supersetNode.connections.redis_ssl.enabled }}
|
||||
REDIS_URL_PARAMS = f"?ssl_cert_reqs={env('REDIS_SSL_CERT_REQS')}"
|
||||
{{- else }}
|
||||
REDIS_URL_PARAMS = ""
|
||||
{{- end }}
|
||||
{{- $cacheDb := include "superset.redis.cacheDb" . }}
|
||||
CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{{ $cacheDb }}{REDIS_URL_PARAMS}"
|
||||
{{- end }}
|
||||
{{- if .Values.cache.celeryUrl }}
|
||||
CELERY_REDIS_URL = {{ .Values.cache.celeryUrl | quote }}
|
||||
{{- else if not .Values.cache.cacheUrl }}
|
||||
{{- $celeryDb := include "superset.redis.celeryDb" . }}
|
||||
CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{{ $celeryDb }}{REDIS_URL_PARAMS}"
|
||||
{{- else }}
|
||||
{{- if or .Values.config.celeryConfig (not .Values.cache.enabled) }}
|
||||
{{- /* Custom celeryConfig provided or cache disabled - OK */}}
|
||||
{{- else }}
|
||||
{{- fail "CONFIGURATION ERROR: cache.cacheUrl is set but cache.celeryUrl is not set. When using cacheUrl, you must also set celeryUrl for Celery to work. Alternatively, set config.celeryConfig to provide a custom Celery configuration." }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
|
||||
{{- /* Cache Configuration */}}
|
||||
{{- if .Values.config.cacheConfig }}
|
||||
CACHE_CONFIG = json.loads({{ .Values.config.cacheConfig | toJson | quote }})
|
||||
{{- else if .Values.cache.enabled }}
|
||||
# Build Redis URLs
|
||||
CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_DB', 1)}{REDIS_URL_PARAMS}"
|
||||
CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_CELERY_DB', 0)}{REDIS_URL_PARAMS}"
|
||||
|
||||
MAPBOX_API_KEY = env('MAPBOX_API_KEY', '')
|
||||
CACHE_CONFIG = {
|
||||
'CACHE_TYPE': 'RedisCache',
|
||||
'CACHE_DEFAULT_TIMEOUT': {{ .Values.cache.defaultTimeout | default (.Values.config.cacheDefaultTimeout | default 86400) | int }},
|
||||
'CACHE_KEY_PREFIX': {{ .Values.cache.keyPrefix | default "superset_" | quote }},
|
||||
'CACHE_REDIS_URL': CACHE_REDIS_URL,
|
||||
'CACHE_TYPE': 'RedisCache',
|
||||
'CACHE_DEFAULT_TIMEOUT': 300,
|
||||
'CACHE_KEY_PREFIX': 'superset_',
|
||||
'CACHE_REDIS_URL': CACHE_REDIS_URL,
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.config.dataCacheConfig }}
|
||||
DATA_CACHE_CONFIG = json.loads({{ .Values.config.dataCacheConfig | toJson | quote }})
|
||||
{{- else if .Values.config.cacheConfig }}
|
||||
DATA_CACHE_CONFIG = CACHE_CONFIG
|
||||
{{- else if .Values.cache.enabled }}
|
||||
DATA_CACHE_CONFIG = CACHE_CONFIG
|
||||
{{- end }}
|
||||
|
||||
{{- /* SQLLAB_ASYNC_TIME_LIMIT_SEC - Required for async_queries module import (default: 6 hours) */}}
|
||||
{{- if .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC }}
|
||||
SQLLAB_ASYNC_TIME_LIMIT_SEC = {{ .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC | int }}
|
||||
{{- else }}
|
||||
from datetime import timedelta
|
||||
SQLLAB_ASYNC_TIME_LIMIT_SEC = int(timedelta(hours=6).total_seconds())
|
||||
{{- end }}
|
||||
|
||||
{{- /* Celery Configuration */}}
|
||||
{{- if .Values.config.celeryConfig }}
|
||||
{{- if kindIs "string" .Values.config.celeryConfig }}
|
||||
{{ .Values.config.celeryConfig }}
|
||||
{{- else }}
|
||||
class CeleryConfig:
|
||||
{{- range $key, $value := .Values.config.celeryConfig }}
|
||||
{{ $key }} = json.loads({{ $value | toJson | quote }})
|
||||
{{- end }}
|
||||
|
||||
{{- if hasKey .Values.config.celeryConfig "imports" }}
|
||||
CELERY_IMPORTS = CeleryConfig.imports
|
||||
{{- else }}
|
||||
CELERY_IMPORTS = ()
|
||||
{{- end }}
|
||||
CELERY_CONFIG = CeleryConfig
|
||||
{{- end }}
|
||||
{{- else if .Values.cache.enabled }}
|
||||
from celery.schedules import crontab
|
||||
from datetime import timedelta
|
||||
if os.getenv("SQLALCHEMY_DATABASE_URI"):
|
||||
SQLALCHEMY_DATABASE_URI = os.getenv("SQLALCHEMY_DATABASE_URI")
|
||||
else:
|
||||
{{- if eq .Values.supersetNode.connections.db_type "postgresql" }}
|
||||
SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
|
||||
{{- else if eq .Values.supersetNode.connections.db_type "mysql" }}
|
||||
SQLALCHEMY_DATABASE_URI = f"mysql+mysqldb://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
|
||||
{{- else }}
|
||||
{{ fail (printf "Unsupported database type: %s. Please use 'postgresql' or 'mysql'." .Values.supersetNode.connections.db_type) }}
|
||||
{{- end }}
|
||||
|
||||
class CeleryConfig:
|
||||
imports = (
|
||||
"superset.sql_lab",
|
||||
"superset.tasks.scheduler",
|
||||
"superset.tasks.thumbnails",
|
||||
"superset.tasks.cache",
|
||||
)
|
||||
broker_connection_retry_on_startup = True
|
||||
worker_prefetch_multiplier = 10
|
||||
task_acks_late = True
|
||||
broker_url = CELERY_REDIS_URL
|
||||
result_backend = CELERY_REDIS_URL
|
||||
task_annotations = {
|
||||
"sql_lab.get_sql_results": {
|
||||
"rate_limit": "100/s",
|
||||
},
|
||||
}
|
||||
beat_schedule = {
|
||||
"reports.scheduler": {
|
||||
"task": "reports.scheduler",
|
||||
"schedule": crontab(minute="*", hour="*"),
|
||||
"options": {"expires": int(timedelta(weeks=1).total_seconds())},
|
||||
},
|
||||
"reports.prune_log": {
|
||||
"task": "reports.prune_log",
|
||||
"schedule": crontab(minute=0, hour=0),
|
||||
},
|
||||
}
|
||||
imports = ("superset.sql_lab", )
|
||||
broker_url = CELERY_REDIS_URL
|
||||
result_backend = CELERY_REDIS_URL
|
||||
|
||||
CELERY_IMPORTS = CeleryConfig.imports
|
||||
CELERY_CONFIG = CeleryConfig
|
||||
{{- end }}
|
||||
|
||||
{{- /* Celery Worker Health Check - File-based health probes for Kubernetes */}}
|
||||
{{- if and .Values.supersetWorker.healthCheck .Values.supersetWorker.healthCheck.enabled }}
|
||||
# Celery Worker Health Check Configuration
|
||||
import threading
|
||||
from celery import bootsteps
|
||||
from celery.signals import worker_ready, worker_shutdown, worker_init
|
||||
|
||||
_readiness_file = {{ .Values.supersetWorker.healthCheck.readinessFile | default "/tmp/celery_worker_ready" | quote }}
|
||||
_liveness_file = {{ .Values.supersetWorker.healthCheck.livenessFile | default "/tmp/celery_worker_alive" | quote }}
|
||||
_heartbeat_interval = {{ .Values.supersetWorker.healthCheck.livenessHeartbeatInterval | default 10 | int }}
|
||||
_liveness_thread = None
|
||||
_liveness_stop_event = None
|
||||
|
||||
@worker_ready.connect
|
||||
def create_ready_file(sender, **kwargs):
|
||||
try:
|
||||
open(_readiness_file, 'w').close()
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not create readiness file: {e}")
|
||||
|
||||
@worker_shutdown.connect
|
||||
def remove_ready_file(sender, **kwargs):
|
||||
global _liveness_thread, _liveness_stop_event
|
||||
if _liveness_stop_event:
|
||||
_liveness_stop_event.set()
|
||||
if _liveness_thread:
|
||||
_liveness_thread.join(timeout=5)
|
||||
try:
|
||||
if os.path.exists(_readiness_file):
|
||||
os.remove(_readiness_file)
|
||||
if os.path.exists(_liveness_file):
|
||||
os.remove(_liveness_file)
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not remove health check files: {e}")
|
||||
|
||||
@worker_init.connect
|
||||
def start_liveness_heartbeat(sender, **kwargs):
|
||||
global _liveness_thread, _liveness_stop_event
|
||||
_liveness_stop_event = threading.Event()
|
||||
|
||||
def update_liveness():
|
||||
while not _liveness_stop_event.is_set():
|
||||
try:
|
||||
with open(_liveness_file, 'w') as f:
|
||||
f.write(str(os.getpid()))
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not update liveness file: {e}")
|
||||
_liveness_stop_event.wait(_heartbeat_interval)
|
||||
|
||||
_liveness_thread = threading.Thread(target=update_liveness, daemon=True)
|
||||
_liveness_thread.start()
|
||||
{{- else }}
|
||||
CELERY_WORKER_HEALTH_CHECK_ENABLED = False
|
||||
{{- end }}
|
||||
|
||||
{{- /* Results Backend */}}
|
||||
{{- $redisHostForBackend := include "superset.redis.host" . }}
|
||||
{{- $redisPortForBackend := include "superset.redis.port" . }}
|
||||
{{- $redisPasswordForBackend := include "superset.redis.password" . }}
|
||||
{{- if .Values.config.resultsBackend }}
|
||||
{{- if kindIs "string" .Values.config.resultsBackend }}
|
||||
RESULTS_BACKEND = {{ .Values.config.resultsBackend }}
|
||||
{{- else }}
|
||||
RESULTS_BACKEND = RedisCache(
|
||||
host={{ $redisHostForBackend | quote }},
|
||||
{{- if $redisPasswordForBackend }}
|
||||
password={{ $redisPasswordForBackend | quote }},
|
||||
{{- end }}
|
||||
port={{ $redisPortForBackend | int }},
|
||||
key_prefix={{ .Values.cache.resultsBackendKeyPrefix | default "superset_results" | quote }},
|
||||
{{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
|
||||
ssl=True,
|
||||
ssl_cert_reqs={{ .Values.cache.ssl.ssl_cert_reqs | default "required" | quote }},
|
||||
{{- end }}
|
||||
host=env('REDIS_HOST'),
|
||||
{{- if .Values.supersetNode.connections.redis_password }}
|
||||
password=env('REDIS_PASSWORD'),
|
||||
{{- end }}
|
||||
port=env('REDIS_PORT'),
|
||||
key_prefix='superset_results',
|
||||
{{- if .Values.supersetNode.connections.redis_ssl.enabled }}
|
||||
ssl=True,
|
||||
ssl_cert_reqs=env('REDIS_SSL_CERT_REQS'),
|
||||
{{- end }}
|
||||
)
|
||||
{{- end }}
|
||||
{{- else if .Values.cache.enabled }}
|
||||
RESULTS_BACKEND = RedisCache(
|
||||
host={{ $redisHostForBackend | quote }},
|
||||
{{- if $redisPasswordForBackend }}
|
||||
password={{ $redisPasswordForBackend | quote }},
|
||||
{{- end }}
|
||||
port={{ $redisPortForBackend | int }},
|
||||
key_prefix={{ .Values.cache.resultsBackendKeyPrefix | default "superset_results" | quote }},
|
||||
{{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
|
||||
ssl=True,
|
||||
ssl_cert_reqs={{ .Values.cache.ssl.ssl_cert_reqs | default "required" | quote }},
|
||||
{{- end }}
|
||||
)
|
||||
{{- end }}
|
||||
|
||||
{{- /* Global Async Queries Cache Backend */}}
|
||||
{{- $redisUserForGaq := include "superset.redis.user" . }}
|
||||
{{- if .Values.config.GLOBAL_ASYNC_QUERIES_CACHE_BACKEND }}
|
||||
GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = json.loads({{ .Values.config.GLOBAL_ASYNC_QUERIES_CACHE_BACKEND | toJson | quote }})
|
||||
{{- else if .Values.cache.enabled }}
|
||||
GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {
|
||||
"CACHE_TYPE": "RedisCache",
|
||||
"CACHE_REDIS_HOST": {{ $redisHostForBackend | quote }},
|
||||
"CACHE_REDIS_PORT": {{ $redisPortForBackend | int }},
|
||||
{{- if $redisUserForGaq }}
|
||||
"CACHE_REDIS_USER": {{ $redisUserForGaq | quote }},
|
||||
{{- end }}
|
||||
{{- if $redisPasswordForBackend }}
|
||||
"CACHE_REDIS_PASSWORD": {{ $redisPasswordForBackend | quote }},
|
||||
{{- else }}
|
||||
"CACHE_REDIS_PASSWORD": "",
|
||||
{{- end }}
|
||||
"CACHE_REDIS_DB": {{ .Values.cache.asyncQueries.db | default .Values.cache.cacheDb | default 0 | int }},
|
||||
"CACHE_KEY_PREFIX": {{ .Values.cache.asyncQueries.keyPrefix | default "qc-" | quote }},
|
||||
"CACHE_DEFAULT_TIMEOUT": {{ .Values.cache.asyncQueries.timeout | default 86400 | int }},
|
||||
{{- if and .Values.cache.sentinel .Values.cache.sentinel.enabled }}
|
||||
{{- if .Values.cache.sentinel.sentinels }}
|
||||
"CACHE_REDIS_SENTINELS": {{ .Values.cache.sentinel.sentinels | toJson }},
|
||||
{{- else }}
|
||||
{{- fail "CONFIGURATION ERROR: cache.sentinel.enabled is true but cache.sentinel.sentinels is not set. You must provide Sentinel host(s) in cache.sentinel.sentinels (e.g., [['sentinel-host', 26379]])." }}
|
||||
{{- end }}
|
||||
"CACHE_REDIS_SENTINEL_MASTER": {{ .Values.cache.sentinel.master | default "mymaster" | quote }},
|
||||
{{- if .Values.cache.sentinel.password }}
|
||||
"CACHE_REDIS_SENTINEL_PASSWORD": {{ .Values.cache.sentinel.password | quote }},
|
||||
{{- else }}
|
||||
"CACHE_REDIS_SENTINEL_PASSWORD": None,
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
|
||||
"CACHE_REDIS_SSL": True,
|
||||
"CACHE_REDIS_SSL_CERTFILE": {{ if .Values.cache.ssl.certfile }}{{ .Values.cache.ssl.certfile | quote }}{{ else }}None{{ end }},
|
||||
"CACHE_REDIS_SSL_KEYFILE": {{ if .Values.cache.ssl.keyfile }}{{ .Values.cache.ssl.keyfile | quote }}{{ else }}None{{ end }},
|
||||
"CACHE_REDIS_SSL_CERT_REQS": {{ .Values.cache.ssl.ssl_cert_reqs | default "required" | quote }},
|
||||
"CACHE_REDIS_SSL_CA_CERTS": {{ if .Values.cache.ssl.ca_certs }}{{ .Values.cache.ssl.ca_certs | quote }}{{ else }}None{{ end }},
|
||||
{{- else }}
|
||||
"CACHE_REDIS_SSL": False,
|
||||
"CACHE_REDIS_SSL_CERTFILE": None,
|
||||
"CACHE_REDIS_SSL_KEYFILE": None,
|
||||
"CACHE_REDIS_SSL_CERT_REQS": {{ .Values.cache.ssl.ssl_cert_reqs | default "required" | quote }},
|
||||
"CACHE_REDIS_SSL_CA_CERTS": None,
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- /* Global Async Queries Results Backend */}}
|
||||
{{- if .Values.config.GLOBAL_ASYNC_QUERIES_RESULTS_BACKEND }}
|
||||
GLOBAL_ASYNC_QUERIES_RESULTS_BACKEND = json.loads({{ .Values.config.GLOBAL_ASYNC_QUERIES_RESULTS_BACKEND | toJson | quote }})
|
||||
{{- else if .Values.cache.enabled }}
|
||||
GLOBAL_ASYNC_QUERIES_RESULTS_BACKEND = {
|
||||
"backend": "redis",
|
||||
"host": {{ $redisHostForBackend | quote }},
|
||||
"port": {{ $redisPortForBackend | int }},
|
||||
"prefix": {{ .Values.cache.asyncQueries.keyPrefix | default "qc-" | quote }},
|
||||
"db": {{ .Values.cache.asyncQueries.db | default .Values.cache.cacheDb | default 0 | int }},
|
||||
{{- if $redisPasswordForBackend }}
|
||||
"password": {{ $redisPasswordForBackend | quote }},
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- /* Feature Flags */}}
|
||||
{{- if .Values.featureFlags }}
|
||||
FEATURE_FLAGS = {
|
||||
{{- range $key, $value := .Values.featureFlags }}
|
||||
{{- if kindIs "bool" $value }}
|
||||
"{{ $key }}": {{ if $value }}True{{ else }}False{{ end }},
|
||||
{{- else if kindIs "string" $value }}
|
||||
"{{ $key }}": {{ $value | quote }},
|
||||
{{- else if kindIs "float64" $value }}
|
||||
"{{ $key }}": {{ $value }},
|
||||
{{- else if kindIs "int" $value }}
|
||||
"{{ $key }}": {{ $value }},
|
||||
{{- else if kindIs "invalid" $value }}
|
||||
"{{ $key }}": None,
|
||||
{{- else }}
|
||||
"{{ $key }}": json.loads({{ $value | toJson | quote }}),
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- /* FAB Security API - Required for List Roles view in 6.0.0+ */}}
|
||||
{{- if not (hasKey .Values.config "FAB_ADD_SECURITY_API") }}
|
||||
FAB_ADD_SECURITY_API = True
|
||||
{{- end }}
|
||||
{{- if not (hasKey .Values.config "FAB_ADD_SECURITY_VIEWS") }}
|
||||
FAB_ADD_SECURITY_VIEWS = True
|
||||
{{- end }}
|
||||
|
||||
{{- /* Global Async Queries Transport - Auto-configure for websockets if enabled */}}
|
||||
{{- if .Values.config.GLOBAL_ASYNC_QUERIES_TRANSPORT }}
|
||||
GLOBAL_ASYNC_QUERIES_TRANSPORT = {{ .Values.config.GLOBAL_ASYNC_QUERIES_TRANSPORT | quote }}
|
||||
{{- else if .Values.supersetWebsockets.enabled }}
|
||||
GLOBAL_ASYNC_QUERIES_TRANSPORT = "ws"
|
||||
{{- else }}
|
||||
GLOBAL_ASYNC_QUERIES_TRANSPORT = "polling"
|
||||
{{- end }}
|
||||
|
||||
{{- /* Global Async Queries WebSocket URL */}}
|
||||
{{- $wsUrl := "" }}
|
||||
{{- if .Values.config.GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL }}
|
||||
{{- $wsUrl = .Values.config.GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL }}
|
||||
GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL = {{ $wsUrl | quote }}
|
||||
{{- else if and .Values.supersetWebsockets.enabled .Values.supersetWebsockets.websocketUrl }}
|
||||
{{- $wsUrl = .Values.supersetWebsockets.websocketUrl }}
|
||||
GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL = {{ $wsUrl | quote }}
|
||||
{{- else if .Values.supersetWebsockets.enabled }}
|
||||
{{- $wsServiceName := .Values.cluster.websocketServiceName }}
|
||||
{{- if not $wsServiceName }}
|
||||
{{- $wsServiceName = printf "%s-ws" (include "superset.fullname" .) }}
|
||||
{{- end }}
|
||||
{{- $wsPort := .Values.supersetWebsockets.service.port | default 8080 }}
|
||||
{{- $wsPath := "/ws" }}
|
||||
{{- $clusterDomain := .Values.cluster.domain | default ".svc.cluster.local" }}
|
||||
{{- $wsUrl = printf "ws://%s.%s%s:%d%s" $wsServiceName .Release.Namespace $clusterDomain $wsPort $wsPath }}
|
||||
GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL = {{ $wsUrl | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{- /* Global Async Queries JWT Secret */}}
|
||||
{{- if .Values.config.GLOBAL_ASYNC_QUERIES_JWT_SECRET }}
|
||||
GLOBAL_ASYNC_QUERIES_JWT_SECRET = {{ .Values.config.GLOBAL_ASYNC_QUERIES_JWT_SECRET | quote }}
|
||||
{{- else if and .Values.supersetWebsockets.enabled .Values.supersetWebsockets.config.jwtSecret }}
|
||||
GLOBAL_ASYNC_QUERIES_JWT_SECRET = {{ .Values.supersetWebsockets.config.jwtSecret | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{- /* Global Async Queries JWT Cookie Settings */}}
|
||||
{{- if hasKey .Values.config "GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE" }}
|
||||
GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE = {{ .Values.config.GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE | toString | title }}
|
||||
{{- else if and .Values.supersetWebsockets.enabled (or (hasPrefix "wss://" $wsUrl) .Values.ingress.tls) }}
|
||||
GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE = True
|
||||
{{- else if .Values.supersetWebsockets.enabled }}
|
||||
GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE = False
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.config.GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SAMESITE }}
|
||||
GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SAMESITE = {{ .Values.config.GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SAMESITE | quote }}
|
||||
{{- else if .Values.supersetWebsockets.enabled }}
|
||||
GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SAMESITE = "Lax"
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.config.GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME }}
|
||||
GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME = {{ .Values.config.GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME | quote }}
|
||||
{{- else if and .Values.supersetWebsockets.enabled .Values.supersetWebsockets.config.jwtCookieName }}
|
||||
GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME = {{ .Values.supersetWebsockets.config.jwtCookieName | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{- /* Content Security Policy (CSP) */}}
|
||||
{{- if and .Values.supersetWebsockets.enabled $wsUrl (not (hasKey .Values.config "TALISMAN_CONFIG")) }}
|
||||
TALISMAN_CONFIG = {
|
||||
"content_security_policy": {
|
||||
"base-uri": ["'self'"],
|
||||
"default-src": ["'self'"],
|
||||
"img-src": [
|
||||
"'self'",
|
||||
"blob:",
|
||||
"data:",
|
||||
"https://apachesuperset.gateway.scarf.sh",
|
||||
"https://static.scarf.sh/",
|
||||
"ows.terrestris.de",
|
||||
"https://cdn.document360.io",
|
||||
],
|
||||
"worker-src": ["'self'", "blob:"],
|
||||
"connect-src": [
|
||||
"'self'",
|
||||
{{ $wsUrl | quote }},
|
||||
"https://api.mapbox.com",
|
||||
"https://events.mapbox.com",
|
||||
"https://tile.openstreetmap.org",
|
||||
"https://tile.osm.ch",
|
||||
],
|
||||
"object-src": "'none'",
|
||||
"style-src": [
|
||||
"'self'",
|
||||
"'unsafe-inline'",
|
||||
],
|
||||
"script-src": ["'self'", "'strict-dynamic'"],
|
||||
},
|
||||
"content_security_policy_nonce_in": ["script-src"],
|
||||
{{- if or (hasPrefix "wss://" $wsUrl) .Values.ingress.tls }}
|
||||
"force_https": True,
|
||||
"session_cookie_secure": True,
|
||||
{{- else }}
|
||||
"force_https": False,
|
||||
"session_cookie_secure": False,
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- /* General Configuration - iterate through all config values */}}
|
||||
{{- range $key, $value := .Values.config }}
|
||||
{{- if and (ne $key "cacheConfig") (ne $key "dataCacheConfig") (ne $key "celeryConfig") (ne $key "resultsBackend") (ne $key "GLOBAL_ASYNC_QUERIES_CACHE_BACKEND") (ne $key "GLOBAL_ASYNC_QUERIES_RESULTS_BACKEND") (ne $key "GLOBAL_ASYNC_QUERIES_TRANSPORT") (ne $key "GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL") (ne $key "GLOBAL_ASYNC_QUERIES_JWT_SECRET") (ne $key "GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE") (ne $key "GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SAMESITE") (ne $key "GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME") (ne $key "TALISMAN_CONFIG") (ne $key "SQLLAB_ASYNC_TIME_LIMIT_SEC") (ne $key "SQLALCHEMY_TRACK_MODIFICATIONS") }}
|
||||
{{- if kindIs "map" $value }}
|
||||
{{ $key }} = json.loads({{ $value | toJson | quote }})
|
||||
{{- else if kindIs "slice" $value }}
|
||||
{{ $key }} = json.loads({{ $value | toJson | quote }})
|
||||
{{- else if kindIs "bool" $value }}
|
||||
{{ $key }} = {{ if $value }}True{{ else }}False{{ end }}
|
||||
{{- else if kindIs "string" $value }}
|
||||
{{- if or (hasPrefix "f\"" $value) (hasPrefix "F\"" $value) (hasPrefix "r\"" $value) (hasPrefix "R\"" $value) (hasPrefix "b\"" $value) (hasPrefix "B\"" $value) }}
|
||||
{{ $key }} = {{ $value }}
|
||||
{{- else }}
|
||||
{{ $key }} = {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- else if kindIs "invalid" $value }}
|
||||
{{ $key }} = None
|
||||
{{- else }}
|
||||
{{ $key }} = {{ $value | toJson }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- /* Custom Config Overrides */}}
|
||||
{{- if .Values.configOverrides }}
|
||||
# Custom Overrides
|
||||
{{ if .Values.configOverrides }}
|
||||
# Overrides
|
||||
{{- range $key, $value := .Values.configOverrides }}
|
||||
# {{ $key }}
|
||||
{{ tpl $value $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.configOverridesFiles }}
|
||||
{{ if .Values.configOverridesFiles }}
|
||||
# Overrides from files
|
||||
{{- $files := .Files }}
|
||||
{{- range $key, $value := .Values.configOverridesFiles }}
|
||||
@@ -680,57 +187,7 @@ TALISMAN_CONFIG = {
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- end -}}
|
||||
|
||||
{{- define "superset.initScript" -}}
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
echo "Upgrading DB schema..."
|
||||
superset db upgrade
|
||||
echo "Initializing roles and permissions..."
|
||||
superset init
|
||||
echo "Init job: Creating admin user and loading initial data..."
|
||||
{{- if .Values.init.createAdmin }}
|
||||
echo "Creating admin user (if not present)..."
|
||||
if superset fab list-users 2>/dev/null | grep -qF {{ printf "username:%s" .Values.init.adminUser.username | squote }}; then
|
||||
echo "Admin user already exists, skipping."
|
||||
else
|
||||
superset fab create-admin \
|
||||
--username {{ .Values.init.adminUser.username | squote }} \
|
||||
--firstname {{ .Values.init.adminUser.firstname | squote }} \
|
||||
--lastname {{ .Values.init.adminUser.lastname | squote }} \
|
||||
--email {{ .Values.init.adminUser.email | squote }} \
|
||||
--password {{ .Values.init.adminUser.password | squote }}
|
||||
fi
|
||||
{{- else }}
|
||||
echo "Skipping admin creation (init.createAdmin=false)"
|
||||
{{- end }}
|
||||
{{- if .Values.init.loadExamples }}
|
||||
echo "Loading examples..."
|
||||
superset load_examples
|
||||
{{- else }}
|
||||
echo "Skipping examples (init.loadExamples=false)"
|
||||
{{- end }}
|
||||
if [ -f "{{ .Values.extraConfigMountPath }}/import_datasources.yaml" ]; then
|
||||
echo "Importing database connections..."
|
||||
superset import_datasources -p {{ .Values.extraConfigMountPath }}/import_datasources.yaml
|
||||
fi
|
||||
echo "Init job complete."
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Deprecation warnings — returns a newline-separated list of active deprecation messages,
|
||||
or empty string when no deprecated keys are set. Rendered in NOTES.txt after install/upgrade.
|
||||
*/}}
|
||||
{{- define "superset.deprecationWarnings" -}}
|
||||
{{- $conn := include "_superset.legacyConn" . | fromJson -}}
|
||||
{{- if gt (len (keys $conn)) 0 }}
|
||||
- supersetNode.connections.* is deprecated; use database.* and cache.* (auto-mapped for now). See UPGRADING.md
|
||||
{{- end }}
|
||||
{{- if .Values.serviceAccountName }}
|
||||
- root serviceAccountName is deprecated; use serviceAccount.name (auto-mapped for now). See UPGRADING.md
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "supersetNode.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "superset.name" . }}
|
||||
|
||||
@@ -37,12 +37,9 @@ spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/superset_config.py: {{ include "superset.config" . | sha256sum }}
|
||||
checksum/superset_config.py: {{ include "superset-config" . | sha256sum }}
|
||||
checksum/superset_bootstrap.sh: {{ tpl .Values.bootstrapScript . | sha256sum }}
|
||||
checksum/database: {{ .Values.database | toYaml | sha256sum }}
|
||||
checksum/redis: {{ .Values.cache | toYaml | sha256sum }}
|
||||
checksum/config: {{ .Values.config | toYaml | sha256sum }}
|
||||
checksum/featureFlags: {{ .Values.featureFlags | toYaml | sha256sum }}
|
||||
checksum/connections: {{ .Values.supersetNode.connections | toYaml | sha256sum }}
|
||||
checksum/extraConfigs: {{ .Values.extraConfigs | toYaml | sha256sum }}
|
||||
checksum/extraSecrets: {{ .Values.extraSecrets | toYaml | sha256sum }}
|
||||
checksum/extraSecretEnv: {{ .Values.extraSecretEnv | toYaml | sha256sum }}
|
||||
@@ -55,9 +52,6 @@ spec:
|
||||
{{- if .Values.supersetCeleryBeat.podAnnotations }}
|
||||
{{- toYaml .Values.supersetCeleryBeat.podAnnotations | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.globalPodAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "supersetCeleryBeat.selectorLabels" . | nindent 8 }}
|
||||
{{- if .Values.supersetCeleryBeat.podLabels }}
|
||||
|
||||
@@ -36,14 +36,11 @@ spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: {{ include "superset.config" . | sha256sum }}
|
||||
checksum/config: {{ include "superset-config" . | sha256sum }}
|
||||
checksum/secrets: {{ tpl (toJson .Values.extraSecretEnv) . | sha256sum }}
|
||||
{{- if .Values.supersetCeleryFlower.podAnnotations }}
|
||||
{{- toYaml .Values.supersetCeleryFlower.podAnnotations | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.globalPodAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "supersetCeleryFlower.selectorLabels" . | nindent 8 }}
|
||||
{{- if .Values.supersetCeleryFlower.podLabels }}
|
||||
|
||||
@@ -43,12 +43,9 @@ spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/superset_config.py: {{ include "superset.config" . | sha256sum }}
|
||||
checksum/superset_config.py: {{ include "superset-config" . | sha256sum }}
|
||||
checksum/superset_bootstrap.sh: {{ tpl .Values.bootstrapScript . | sha256sum }}
|
||||
checksum/database: {{ .Values.database | toYaml | sha256sum }}
|
||||
checksum/redis: {{ .Values.cache | toYaml | sha256sum }}
|
||||
checksum/config: {{ .Values.config | toYaml | sha256sum }}
|
||||
checksum/featureFlags: {{ .Values.featureFlags | toYaml | sha256sum }}
|
||||
checksum/connections: {{ .Values.supersetNode.connections | toYaml | sha256sum }}
|
||||
checksum/extraConfigs: {{ .Values.extraConfigs | toYaml | sha256sum }}
|
||||
checksum/extraSecrets: {{ .Values.extraSecrets | toYaml | sha256sum }}
|
||||
checksum/extraSecretEnv: {{ .Values.extraSecretEnv | toYaml | sha256sum }}
|
||||
@@ -61,9 +58,6 @@ spec:
|
||||
{{- if .Values.supersetWorker.podAnnotations }}
|
||||
{{- toYaml .Values.supersetWorker.podAnnotations | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.globalPodAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "supersetWorker.selectorLabels" . | nindent 8 }}
|
||||
{{- if .Values.supersetWorker.podLabels }}
|
||||
|
||||
@@ -44,9 +44,6 @@ spec:
|
||||
{{- if .Values.supersetWebsockets.podAnnotations }}
|
||||
{{- toYaml .Values.supersetWebsockets.podAnnotations | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.globalPodAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "supersetWebsockets.selectorLabels" . | nindent 8 }}
|
||||
{{- if .Values.supersetWebsockets.podLabels }}
|
||||
|
||||
@@ -44,13 +44,10 @@ spec:
|
||||
metadata:
|
||||
annotations:
|
||||
# Force reload on config changes
|
||||
checksum/superset_config.py: {{ include "superset.config" . | sha256sum }}
|
||||
checksum/superset_init.sh: {{ include "superset.initScript" . | sha256sum }}
|
||||
checksum/superset_config.py: {{ include "superset-config" . | sha256sum }}
|
||||
checksum/superset_init.sh: {{ tpl .Values.init.initscript . | sha256sum }}
|
||||
checksum/superset_bootstrap.sh: {{ tpl .Values.bootstrapScript . | sha256sum }}
|
||||
checksum/database: {{ .Values.database | toYaml | sha256sum }}
|
||||
checksum/redis: {{ .Values.cache | toYaml | sha256sum }}
|
||||
checksum/config: {{ .Values.config | toYaml | sha256sum }}
|
||||
checksum/featureFlags: {{ .Values.featureFlags | toYaml | sha256sum }}
|
||||
checksum/connections: {{ .Values.supersetNode.connections | toYaml | sha256sum }}
|
||||
checksum/extraConfigs: {{ .Values.extraConfigs | toYaml | sha256sum }}
|
||||
checksum/extraSecrets: {{ .Values.extraSecrets | toYaml | sha256sum }}
|
||||
checksum/extraSecretEnv: {{ .Values.extraSecretEnv | toYaml | sha256sum }}
|
||||
@@ -63,9 +60,6 @@ spec:
|
||||
{{- if .Values.supersetNode.podAnnotations }}
|
||||
{{- toYaml .Values.supersetNode.podAnnotations | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.globalPodAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "supersetNode.selectorLabels" . | nindent 8 }}
|
||||
{{- if .Values.supersetNode.podLabels }}
|
||||
|
||||
@@ -26,28 +26,24 @@ metadata:
|
||||
{{- include "superset.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_HOST: {{ include "superset.db.host" . | quote }}
|
||||
DB_PORT: {{ include "superset.db.port" . | quote }}
|
||||
DB_USER: {{ include "superset.db.user" . | quote }}
|
||||
DB_PASS: {{ include "superset.db.password" . | quote }}
|
||||
DB_NAME: {{ include "superset.db.name" . | quote }}
|
||||
{{- if .Values.database.ssl.enabled }}
|
||||
DB_SSL_MODE: {{ .Values.database.ssl.mode | default "require" | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.cache.enabled }}
|
||||
REDIS_HOST: {{ include "superset.redis.host" . | quote }}
|
||||
REDIS_PORT: {{ include "superset.redis.port" . | quote }}
|
||||
REDIS_USER: {{ include "superset.redis.user" . | quote }}
|
||||
{{- if include "superset.redis.password" . }}
|
||||
REDIS_PASSWORD: {{ include "superset.redis.password" . | quote }}
|
||||
{{- end }}
|
||||
REDIS_DB: {{ include "superset.redis.cacheDb" . | quote }}
|
||||
REDIS_CELERY_DB: {{ include "superset.redis.celeryDb" . | quote }}
|
||||
REDIS_PROTO: {{ include "superset.redis.proto" . | quote }}
|
||||
{{- if .Values.cache.driver }}
|
||||
REDIS_DRIVER: {{ .Values.cache.driver | quote }}
|
||||
REDIS_HOST: {{ tpl .Values.supersetNode.connections.redis_host . | quote }}
|
||||
REDIS_USER: {{ .Values.supersetNode.connections.redis_user | quote }}
|
||||
{{- if .Values.supersetNode.connections.redis_password }}
|
||||
REDIS_PASSWORD: {{ .Values.supersetNode.connections.redis_password | quote }}
|
||||
{{- end }}
|
||||
REDIS_PORT: {{ .Values.supersetNode.connections.redis_port | quote }}
|
||||
REDIS_PROTO: {{ if .Values.supersetNode.connections.redis_ssl.enabled }}"rediss"{{ else }}"redis"{{ end }}
|
||||
REDIS_DRIVER: {{ .Values.supersetNode.connections.redis_driver | quote }}
|
||||
REDIS_DB: {{ .Values.supersetNode.connections.redis_cache_db | quote }}
|
||||
REDIS_CELERY_DB: {{ .Values.supersetNode.connections.redis_celery_db | quote }}
|
||||
{{- if .Values.supersetNode.connections.redis_ssl.enabled }}
|
||||
REDIS_SSL_CERT_REQS: {{ .Values.supersetNode.connections.redis_ssl.ssl_cert_reqs | default "CERT_NONE" | quote }}
|
||||
{{- end }}
|
||||
DB_HOST: {{ tpl .Values.supersetNode.connections.db_host . | quote }}
|
||||
DB_PORT: {{ .Values.supersetNode.connections.db_port | quote }}
|
||||
DB_USER: {{ .Values.supersetNode.connections.db_user | quote }}
|
||||
DB_PASS: {{ .Values.supersetNode.connections.db_pass | quote }}
|
||||
DB_NAME: {{ .Values.supersetNode.connections.db_name | quote }}
|
||||
{{- if .Values.extraSecretEnv }}
|
||||
{{- range $key, $value := .Values.extraSecretEnv }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
|
||||
@@ -27,9 +27,9 @@ metadata:
|
||||
type: Opaque
|
||||
stringData:
|
||||
superset_config.py: |
|
||||
{{- include "superset.config" . | nindent 4 }}
|
||||
{{- include "superset-config" . | nindent 4 }}
|
||||
superset_init.sh: |
|
||||
{{- include "superset.initScript" . | nindent 4 }}
|
||||
{{- tpl .Values.init.initscript . | nindent 4 }}
|
||||
superset_bootstrap.sh: |
|
||||
{{- tpl .Values.bootstrapScript . | nindent 4 }}
|
||||
|
||||
|
||||
@@ -1,132 +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.
|
||||
#
|
||||
suite: config checksums + global pod annotations
|
||||
templates:
|
||||
- deployment.yaml
|
||||
- deployment-worker.yaml
|
||||
- deployment-beat.yaml
|
||||
- deployment-flower.yaml
|
||||
- deployment-ws.yaml
|
||||
tests:
|
||||
- it: main deployment has new config checksums, not the old connections checksum
|
||||
template: deployment.yaml
|
||||
asserts:
|
||||
- exists:
|
||||
path: 'spec.template.metadata.annotations["checksum/database"]'
|
||||
- exists:
|
||||
path: 'spec.template.metadata.annotations["checksum/config"]'
|
||||
- notExists:
|
||||
path: 'spec.template.metadata.annotations["checksum/connections"]'
|
||||
- it: main deployment applies globalPodAnnotations
|
||||
template: deployment.yaml
|
||||
set:
|
||||
globalPodAnnotations:
|
||||
team: data
|
||||
asserts:
|
||||
- equal:
|
||||
path: 'spec.template.metadata.annotations.team'
|
||||
value: data
|
||||
- it: globalPodAnnotations coexist with per-component podAnnotations on deployment.yaml
|
||||
template: deployment.yaml
|
||||
set:
|
||||
globalPodAnnotations:
|
||||
global: "yes"
|
||||
supersetNode:
|
||||
podAnnotations:
|
||||
component: "yes"
|
||||
asserts:
|
||||
- equal:
|
||||
path: 'spec.template.metadata.annotations.global'
|
||||
value: "yes"
|
||||
- equal:
|
||||
path: 'spec.template.metadata.annotations.component'
|
||||
value: "yes"
|
||||
- it: worker deployment has config and database checksums
|
||||
template: deployment-worker.yaml
|
||||
asserts:
|
||||
- exists:
|
||||
path: 'spec.template.metadata.annotations["checksum/database"]'
|
||||
- exists:
|
||||
path: 'spec.template.metadata.annotations["checksum/config"]'
|
||||
- it: worker deployment applies globalPodAnnotations
|
||||
template: deployment-worker.yaml
|
||||
set:
|
||||
globalPodAnnotations:
|
||||
team: data
|
||||
asserts:
|
||||
- equal:
|
||||
path: 'spec.template.metadata.annotations.team'
|
||||
value: data
|
||||
- it: beat deployment has config and database checksums
|
||||
template: deployment-beat.yaml
|
||||
set:
|
||||
supersetCeleryBeat:
|
||||
enabled: true
|
||||
asserts:
|
||||
- exists:
|
||||
path: 'spec.template.metadata.annotations["checksum/database"]'
|
||||
- exists:
|
||||
path: 'spec.template.metadata.annotations["checksum/config"]'
|
||||
- it: beat deployment applies globalPodAnnotations
|
||||
template: deployment-beat.yaml
|
||||
set:
|
||||
supersetCeleryBeat:
|
||||
enabled: true
|
||||
globalPodAnnotations:
|
||||
team: data
|
||||
asserts:
|
||||
- equal:
|
||||
path: 'spec.template.metadata.annotations.team'
|
||||
value: data
|
||||
- it: flower deployment has config checksum
|
||||
template: deployment-flower.yaml
|
||||
set:
|
||||
supersetCeleryFlower:
|
||||
enabled: true
|
||||
asserts:
|
||||
- exists:
|
||||
path: 'spec.template.metadata.annotations["checksum/config"]'
|
||||
- it: flower deployment applies globalPodAnnotations
|
||||
template: deployment-flower.yaml
|
||||
set:
|
||||
supersetCeleryFlower:
|
||||
enabled: true
|
||||
globalPodAnnotations:
|
||||
team: data
|
||||
asserts:
|
||||
- equal:
|
||||
path: 'spec.template.metadata.annotations.team'
|
||||
value: data
|
||||
- it: websockets deployment has wsconfig checksum
|
||||
template: deployment-ws.yaml
|
||||
set:
|
||||
supersetWebsockets:
|
||||
enabled: true
|
||||
asserts:
|
||||
- exists:
|
||||
path: 'spec.template.metadata.annotations["checksum/wsconfig"]'
|
||||
- it: websockets deployment applies globalPodAnnotations
|
||||
template: deployment-ws.yaml
|
||||
set:
|
||||
supersetWebsockets:
|
||||
enabled: true
|
||||
globalPodAnnotations:
|
||||
team: data
|
||||
asserts:
|
||||
- equal:
|
||||
path: 'spec.template.metadata.annotations.team'
|
||||
value: data
|
||||
@@ -1,94 +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.
|
||||
#
|
||||
suite: superset_config.py rendering
|
||||
templates:
|
||||
- secret-superset-config.yaml
|
||||
tests:
|
||||
- it: builds SQLALCHEMY_DATABASE_URI from env with percent-encoded creds
|
||||
set: {database: {host: pg.svc, port: 5432, user: su, password: pw, name: sset}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'SQLALCHEMY_DATABASE_URI = f"postgresql\+psycopg2://\{quote\(env\(.DB_USER'}
|
||||
- it: honors database.uri override
|
||||
set: {database.uri: "postgresql://x:y@h:5432/d"}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'SQLALCHEMY_DATABASE_URI = "postgresql://x:y@h:5432/d"'}
|
||||
- it: imports required for env/json handling are present
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'import json'}
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'from urllib\.parse import quote'}
|
||||
- it: redis creds are percent-encoded and read from env
|
||||
set: {cache: {enabled: true, password: "p@ss"}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'quote\(env\(.REDIS_PASSWORD'}
|
||||
- it: config map values render via json.loads
|
||||
set: {config: {MY_MAP: {enabled: true}}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'MY_MAP = json\.loads\('}
|
||||
- it: config nil values render as None
|
||||
set: {config: {MY_NIL: null}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'MY_NIL = None'}
|
||||
- it: supersetWorker healthCheck enabled renders readiness file path
|
||||
set: {supersetWorker: {healthCheck: {enabled: true}}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: '/tmp/celery_worker_ready'}
|
||||
- it: SQLALCHEMY_TRACK_MODIFICATIONS defaults False
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'SQLALCHEMY_TRACK_MODIFICATIONS = False'}
|
||||
- it: renders feature flags
|
||||
set: {featureFlags: {ALERT_REPORTS: true}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: '"ALERT_REPORTS": True'}
|
||||
- it: SQLALCHEMY_TRACK_MODIFICATIONS user-set true renders Python True
|
||||
set: {config: {SQLALCHEMY_TRACK_MODIFICATIONS: true}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'SQLALCHEMY_TRACK_MODIFICATIONS = True'}
|
||||
- it: celeryConfig without imports emits a safe empty CELERY_IMPORTS (no AttributeError)
|
||||
set: {config: {celeryConfig: {broker_url: "redis://x"}}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'CELERY_IMPORTS = \(\)'}
|
||||
- notMatchRegex: {path: 'stringData["superset_config.py"]', pattern: 'CELERY_IMPORTS = CeleryConfig\.imports'}
|
||||
- it: legacy db_type maps to the SQLAlchemy driver (deprecation path)
|
||||
set: {supersetNode: {connections: {db_type: "postgresql+pg8000"}}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'SQLALCHEMY_DATABASE_URI = f"postgresql\+pg8000://'}
|
||||
- it: init script single-quotes the admin username (no shell injection)
|
||||
set: {init: {createAdmin: true, adminUser: {password: "x"}}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_init.sh"]', pattern: "grep -qF 'username:"}
|
||||
- notMatchRegex: {path: 'stringData["superset_init.sh"]', pattern: 'create-admin[\s\S]*\|\| true'}
|
||||
- it: sentinel disabled does not fail render
|
||||
set: {cache: {enabled: true, sentinel: {enabled: false}}}
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- it: ssl certfile path is quoted
|
||||
set: {cache: {enabled: true, ssl: {enabled: true, certfile: "/etc/ssl/cert.pem"}}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: '"CACHE_REDIS_SSL_CERTFILE": "/etc/ssl/cert.pem"'}
|
||||
- it: explicit JWT cookie secure false is respected
|
||||
set: {supersetWebsockets: {enabled: true}, config: {GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE: false}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE = False'}
|
||||
- it: celeryConfig non-string values render as valid Python via json.loads
|
||||
set: {config: {celeryConfig: {broker_url: "redis://x", task_acks_late: true}}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: 'task_acks_late = json\.loads\('}
|
||||
- it: featureFlags non-scalar values render as valid Python via json.loads
|
||||
set: {featureFlags: {SOME_MAP: {nested: true}}}
|
||||
asserts:
|
||||
- matchRegex: {path: 'stringData["superset_config.py"]', pattern: '"SOME_MAP": json\.loads\('}
|
||||
@@ -1,28 +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.
|
||||
#
|
||||
suite: deprecation path does not fail render
|
||||
templates:
|
||||
- secret-superset-config.yaml
|
||||
tests:
|
||||
- it: legacy supersetNode.connections still renders (no fail)
|
||||
set: {supersetNode.connections.db_host: legacy}
|
||||
asserts:
|
||||
- hasDocuments: {count: 1}
|
||||
- it: legacy root serviceAccountName still renders (no fail)
|
||||
set: {serviceAccountName: my-sa}
|
||||
asserts:
|
||||
- hasDocuments: {count: 1}
|
||||
@@ -1,63 +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.
|
||||
#
|
||||
suite: superset_init.sh rendering
|
||||
templates:
|
||||
- secret-superset-config.yaml
|
||||
tests:
|
||||
- it: renders superset db upgrade in init script
|
||||
asserts:
|
||||
- matchRegex:
|
||||
path: 'stringData["superset_init.sh"]'
|
||||
pattern: 'superset db upgrade'
|
||||
- it: renders superset init in init script
|
||||
asserts:
|
||||
- matchRegex:
|
||||
path: 'stringData["superset_init.sh"]'
|
||||
pattern: 'superset init'
|
||||
- it: renders db upgrade before admin creation
|
||||
set:
|
||||
init:
|
||||
createAdmin: true
|
||||
adminUser:
|
||||
username: admin
|
||||
firstname: Admin
|
||||
lastname: User
|
||||
email: admin@example.com
|
||||
password: adminpass
|
||||
asserts:
|
||||
- matchRegex:
|
||||
path: 'stringData["superset_init.sh"]'
|
||||
pattern: 'superset db upgrade'
|
||||
- matchRegex:
|
||||
path: 'stringData["superset_init.sh"]'
|
||||
pattern: 'superset init'
|
||||
- matchRegex:
|
||||
path: 'stringData["superset_init.sh"]'
|
||||
pattern: 'fab create-admin'
|
||||
- it: admin creation is idempotent and does not swallow real failures
|
||||
set:
|
||||
init:
|
||||
createAdmin: true
|
||||
adminUser:
|
||||
password: "x"
|
||||
asserts:
|
||||
- matchRegex:
|
||||
path: 'stringData["superset_init.sh"]'
|
||||
pattern: 'superset fab list-users'
|
||||
- notMatchRegex:
|
||||
path: 'stringData["superset_init.sh"]'
|
||||
pattern: 'create-admin.*\|\| true'
|
||||
@@ -1,71 +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.
|
||||
#
|
||||
suite: secret-env schema + deprecation mapping
|
||||
templates:
|
||||
- secret-env.yaml
|
||||
tests:
|
||||
- it: emits DB_* and REDIS_* from new schema
|
||||
set:
|
||||
database: {host: pg.svc, port: 5432, user: su, password: pw, name: superset}
|
||||
cache: {enabled: true, host: rd.svc, port: 6379, cacheDb: 1, celeryDb: 0}
|
||||
asserts:
|
||||
- equal: {path: 'stringData.DB_HOST', value: pg.svc}
|
||||
- equal: {path: 'stringData.DB_PORT', value: "5432"}
|
||||
- equal: {path: 'stringData.REDIS_HOST', value: rd.svc}
|
||||
- it: maps ALL legacy supersetNode.connections.* keys (deprecation path, no fail)
|
||||
set:
|
||||
cache:
|
||||
enabled: true
|
||||
supersetNode:
|
||||
connections:
|
||||
db_host: legacy-pg
|
||||
db_port: "5555"
|
||||
db_user: legacy-user
|
||||
db_pass: legacy-pass
|
||||
db_name: legacy-name
|
||||
redis_host: legacy-rd
|
||||
redis_port: "6380"
|
||||
redis_cache_db: "7"
|
||||
redis_celery_db: "8"
|
||||
redis_driver: rediss
|
||||
asserts:
|
||||
- equal: {path: 'stringData.DB_HOST', value: legacy-pg}
|
||||
- equal: {path: 'stringData.DB_PORT', value: "5555"}
|
||||
- equal: {path: 'stringData.DB_USER', value: legacy-user}
|
||||
- equal: {path: 'stringData.DB_PASS', value: legacy-pass}
|
||||
- equal: {path: 'stringData.DB_NAME', value: legacy-name}
|
||||
- equal: {path: 'stringData.REDIS_HOST', value: legacy-rd}
|
||||
- equal: {path: 'stringData.REDIS_PORT', value: "6380"}
|
||||
- equal: {path: 'stringData.REDIS_DB', value: "7"}
|
||||
- equal: {path: 'stringData.REDIS_CELERY_DB', value: "8"}
|
||||
- equal: {path: 'stringData.REDIS_PROTO', value: rediss}
|
||||
- it: new-schema values still win over legacy when both are set
|
||||
set:
|
||||
database: {host: new-host, port: 1234}
|
||||
supersetNode:
|
||||
connections: {db_host: old-host, db_port: "9999"}
|
||||
asserts:
|
||||
- equal: {path: 'stringData.DB_HOST', value: new-host}
|
||||
- equal: {path: 'stringData.DB_PORT', value: "1234"}
|
||||
- it: emits REDIS_DRIVER when cache.driver set
|
||||
set: {cache: {enabled: true, driver: "rediss+managed"}}
|
||||
asserts:
|
||||
- equal: {path: 'stringData.REDIS_DRIVER', value: "rediss+managed"}
|
||||
- it: omits redis vars when cache disabled
|
||||
set: {cache.enabled: false}
|
||||
asserts:
|
||||
- notExists: {path: 'stringData.REDIS_HOST'}
|
||||
@@ -1,28 +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.
|
||||
#
|
||||
suite: serviceAccountName resolution
|
||||
templates:
|
||||
- serviceaccount.yaml
|
||||
tests:
|
||||
- it: uses serviceAccount.name when set
|
||||
set: {serviceAccount: {create: true, name: my-sa}}
|
||||
asserts:
|
||||
- equal: {path: 'metadata.name', value: my-sa}
|
||||
- it: falls back to legacy root serviceAccountName (deprecation path)
|
||||
set: {serviceAccount: {create: true}, serviceAccountName: legacy-sa}
|
||||
asserts:
|
||||
- equal: {path: 'metadata.name', value: legacy-sa}
|
||||
@@ -1,30 +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.
|
||||
#
|
||||
suite: values defaults
|
||||
templates:
|
||||
- secret-env.yaml
|
||||
tests:
|
||||
- it: renders with new database defaults
|
||||
set:
|
||||
database.host: db.example
|
||||
cache.enabled: true
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- equal:
|
||||
path: 'stringData.DB_HOST'
|
||||
value: db.example
|
||||
@@ -1,140 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"uri": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"driver": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"host": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"port": {
|
||||
"type": ["integer", "string", "null"]
|
||||
},
|
||||
"user": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"password": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"name": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"ssl": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"mode": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cache": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"driver": {
|
||||
"type": "string"
|
||||
},
|
||||
"host": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"port": {
|
||||
"type": ["integer", "string", "null"]
|
||||
},
|
||||
"cacheDb": {
|
||||
"type": ["integer", "string", "null"]
|
||||
},
|
||||
"celeryDb": {
|
||||
"type": ["integer", "string", "null"]
|
||||
},
|
||||
"ssl": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cluster": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"databaseServiceName": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"redisServiceName": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"websocketServiceName": {
|
||||
"type": ["string", "null"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"featureFlags": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"serviceAccount": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"create": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"annotations": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"globalPodAnnotations": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"image": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"repository": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"pullPolicy": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,30 +28,9 @@ nameOverride: ~
|
||||
# -- Provide a name to override the full names of resources
|
||||
fullnameOverride: ~
|
||||
|
||||
# -- Kubernetes cluster configuration
|
||||
# Used for constructing service URLs between chart components
|
||||
cluster:
|
||||
# -- Kubernetes cluster domain (default: .svc.cluster.local)
|
||||
# Override if using a custom cluster domain
|
||||
domain: ".svc.cluster.local"
|
||||
# -- Database service name (default: {{ .Release.Name }}-postgresql)
|
||||
# Override if using a different service name for the database
|
||||
databaseServiceName: ~
|
||||
# -- Redis service name (default: {{ .Release.Name }}-redis-headless)
|
||||
# Override if using a different service name for Redis
|
||||
redisServiceName: ~
|
||||
# -- WebSocket service name (default: {{ .Release.Name }}-ws)
|
||||
# Override if using a different service name for the WebSocket service
|
||||
websocketServiceName: ~
|
||||
|
||||
# -- Labels to be added to all resources
|
||||
extraLabels: {}
|
||||
|
||||
# -- Global pod annotations to be added to all pods
|
||||
# Use this to set annotations that apply to all Superset components
|
||||
# Component-specific podAnnotations will be merged with these global annotations
|
||||
globalPodAnnotations: {}
|
||||
|
||||
# -- User ID directive. This user must have enough permissions to run the bootstrap script
|
||||
# Running containers as root is not recommended in production. Change this to another UID - e.g. 1000 to be more secure
|
||||
runAsUser: 0
|
||||
@@ -67,8 +46,6 @@ serviceAccountName: ~
|
||||
serviceAccount:
|
||||
# -- Create custom service account for Superset. If create: true and serviceAccountName is not provided, `superset.fullname` will be used.
|
||||
create: false
|
||||
# -- Service account name to use (if not specified, defaults to release name + chart name)
|
||||
name: ""
|
||||
annotations: {}
|
||||
|
||||
# -- Install additional packages and do any other bootstrap configuration in this script
|
||||
@@ -267,89 +244,6 @@ hostAliases: []
|
||||
# - nodns.my.lan
|
||||
# ip: 18.27.36.45
|
||||
|
||||
# -- Database connection configuration for the Superset metadata database
|
||||
database:
|
||||
# -- Full database URI (overrides host/port/user/pass/name if set)
|
||||
# Example: "postgresql+psycopg2://user:pass@host:5432/dbname"
|
||||
uri: ~
|
||||
# -- Database driver used when uri is not set (default: postgresql+psycopg2 when unset;
|
||||
# legacy supersetNode.connections.db_type is honored when this is unset)
|
||||
driver: ~
|
||||
# -- Database host (default: {{ .Release.Name }}-postgresql)
|
||||
host: ~
|
||||
# -- Database port (default: 5432 when unset; legacy supersetNode.connections.db_port is honored)
|
||||
port: ~
|
||||
# -- Database user (default: superset, resolved via superset.db.user)
|
||||
user: ~
|
||||
# -- Database password (default: superset, resolved via superset.db.password)
|
||||
# ⚠️ CHANGE THIS for production
|
||||
password: ~
|
||||
# -- Database name (default: superset, resolved via superset.db.name)
|
||||
name: ~
|
||||
# -- Database SSL configuration
|
||||
ssl:
|
||||
enabled: false
|
||||
mode: require
|
||||
|
||||
# -- Redis cache configuration for Superset
|
||||
# Redis is optional but recommended for caching and Celery.
|
||||
# If redis.enabled (chart dependency) is true, defaults point to the chart's Redis instance.
|
||||
cache:
|
||||
# -- Enable Redis-based features (cache, Celery). Set to false to disable Redis usage entirely.
|
||||
enabled: true
|
||||
# -- Full Redis cache URL (overrides host/port/user/pass if set)
|
||||
cacheUrl: ~
|
||||
# -- Full Redis Celery URL (overrides host/port/user/pass if set)
|
||||
celeryUrl: ~
|
||||
# -- Redis host (default: {{ .Release.Name }}-redis-headless)
|
||||
host: ~
|
||||
# -- Redis port (default: 6379 when unset; legacy supersetNode.connections.redis_port is honored)
|
||||
port: ~
|
||||
# -- Redis user (optional, for Redis ACL)
|
||||
user: ""
|
||||
# -- Redis password
|
||||
password: ~
|
||||
# -- Redis database number for cache (default: 1 when unset; legacy redis_cache_db is honored)
|
||||
cacheDb: ~
|
||||
# -- Redis database number for Celery (default: 0 when unset; legacy redis_celery_db is honored)
|
||||
celeryDb: ~
|
||||
# -- Cache key prefix
|
||||
keyPrefix: "superset_"
|
||||
# -- Default cache timeout in seconds
|
||||
defaultTimeout: 86400
|
||||
# -- Results backend key prefix
|
||||
resultsBackendKeyPrefix: "superset_results"
|
||||
# -- Async queries configuration
|
||||
asyncQueries:
|
||||
keyPrefix: "qc-"
|
||||
timeout: 86400
|
||||
# -- Redis Sentinel configuration (optional)
|
||||
sentinel: ~
|
||||
# -- Redis SSL configuration
|
||||
ssl:
|
||||
enabled: false
|
||||
ssl_cert_reqs: required
|
||||
certfile: ~
|
||||
keyfile: ~
|
||||
ca_certs: ~
|
||||
# -- Custom Redis driver (e.g. TLS/managed variants); overrides the redis proto in URLs when set.
|
||||
# Ports the legacy supersetNode.connections.redis_driver escape hatch.
|
||||
driver: ""
|
||||
|
||||
# -- Superset configuration properties
|
||||
# Set any configuration property from superset/config.py here
|
||||
# See https://github.com/apache/superset/blob/master/superset/config.py for all available options
|
||||
config: {}
|
||||
# SECRET_KEY: "your-secret-key-here"
|
||||
# ROW_LIMIT: 50000
|
||||
# DEBUG: false
|
||||
|
||||
# -- Feature flags configuration
|
||||
# See https://github.com/apache/superset/blob/master/RESOURCES/FEATURE_FLAGS.md
|
||||
featureFlags: {}
|
||||
# ALERT_REPORTS: true
|
||||
# DASHBOARD_RBAC: true
|
||||
|
||||
# Superset node configuration
|
||||
supersetNode:
|
||||
replicas:
|
||||
@@ -376,8 +270,28 @@ supersetNode:
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
- ". {{ .Values.configMountPath }}/superset_bootstrap.sh; exec /usr/bin/run-server.sh"
|
||||
# DEPRECATED: use database.* and cache.* instead (still honored if set). See UPGRADING.md
|
||||
connections: {}
|
||||
connections:
|
||||
# -- Change in case of bringing your own redis and then also set redis.enabled:false
|
||||
redis_host: "{{ .Release.Name }}-redis-headless"
|
||||
redis_port: "6379"
|
||||
redis_user: ""
|
||||
# redis_password: superset
|
||||
redis_cache_db: "1"
|
||||
redis_celery_db: "0"
|
||||
# Or SSL port is usually 6380
|
||||
# Update following for using Redis with SSL
|
||||
redis_ssl:
|
||||
enabled: false
|
||||
ssl_cert_reqs: CERT_NONE
|
||||
redis_driver: ""
|
||||
# You need to change below configuration incase bringing own PostgresSQL instance and also set postgresql.enabled:false
|
||||
# -- Database type for Superset metadata (Supported types: "postgresql", "mysql")
|
||||
db_type: "postgresql"
|
||||
db_host: "{{ .Release.Name }}-postgresql"
|
||||
db_port: "5432"
|
||||
db_user: superset
|
||||
db_pass: superset
|
||||
db_name: superset
|
||||
env: {}
|
||||
# -- If true, forces deployment to reload on each upgrade
|
||||
forceReload: false
|
||||
@@ -594,17 +508,6 @@ supersetWorker:
|
||||
startupProbe: {}
|
||||
# -- No startup/readiness probes by default since we don't really care about its startup time (it doesn't serve traffic)
|
||||
readinessProbe: {}
|
||||
# -- Celery worker file-based health check (worker writes readiness/liveness files via signals;
|
||||
# point supersetWorker.readinessProbe/livenessProbe at these files to use them)
|
||||
healthCheck:
|
||||
# -- Enable the file-based Celery worker health check
|
||||
enabled: false
|
||||
# -- Readiness file (created when the worker is ready, removed on shutdown)
|
||||
readinessFile: "/tmp/celery_worker_ready"
|
||||
# -- Liveness file (touched periodically by a heartbeat thread)
|
||||
livenessFile: "/tmp/celery_worker_alive"
|
||||
# -- Seconds between liveness heartbeats
|
||||
livenessHeartbeatInterval: 10
|
||||
# -- Set priorityClassName for supersetWorker pods
|
||||
priorityClassName: ~
|
||||
|
||||
@@ -967,11 +870,8 @@ init:
|
||||
requests:
|
||||
cpu: "250m"
|
||||
memory: "128Mi"
|
||||
# -- DEPRECATED: this field is no longer used by the chart.
|
||||
# The init script is rendered entirely from the internal `superset.initScript` template
|
||||
# (which runs `superset db upgrade`, `superset init`, admin creation, and examples).
|
||||
# Any customization placed here is silently ignored. See UPGRADING.md.
|
||||
# @default -- unused; kept for backwards-compatibility only
|
||||
# -- A Superset init script
|
||||
# @default -- a script to create admin user and initialize roles
|
||||
initscript: |-
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
@@ -24,12 +24,13 @@ name = "apache_superset"
|
||||
description = "A modern, enterprise-ready business intelligence web application"
|
||||
readme = "README.md"
|
||||
dynamic = ["version", "scripts", "entry-points"]
|
||||
requires-python = ">=3.11"
|
||||
requires-python = ">=3.10"
|
||||
license = { file="LICENSE.txt" }
|
||||
authors = [
|
||||
{ name = "Apache Software Foundation", email = "dev@superset.apache.org" },
|
||||
]
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
]
|
||||
@@ -42,8 +43,8 @@ dependencies = [
|
||||
# ``google-auth`` 2.53+ dropped it, so Superset must declare it
|
||||
# explicitly to keep fresh ``pip install apache-superset`` working
|
||||
# without the ``base.txt`` lock file (#40962).
|
||||
"cachetools>=7.1.4, <8",
|
||||
"celery>=5.6.3, <6.0.0",
|
||||
"cachetools>=6.2.1, <7",
|
||||
"celery>=5.3.6, <6.0.0",
|
||||
"click>=8.4.0",
|
||||
"click-option-group",
|
||||
"colorama",
|
||||
@@ -66,7 +67,7 @@ dependencies = [
|
||||
"gunicorn>=26.0.0, <27; sys_platform != 'win32'",
|
||||
"hashids>=1.3.1, <2",
|
||||
# holidays>=0.45 required for security fix
|
||||
"holidays>=0.99, <1",
|
||||
"holidays>=0.45, <1",
|
||||
"humanize",
|
||||
"isodate",
|
||||
"jsonpath-ng>=1.8.0, <2",
|
||||
@@ -105,11 +106,10 @@ dependencies = [
|
||||
"shillelagh[gsheetsapi]>=1.4.4, <2.0",
|
||||
"sshtunnel>=0.4.0, <0.5",
|
||||
"simplejson>=4.1.1",
|
||||
"slack_sdk>=3.43.0, <4",
|
||||
"slack_sdk>=3.42.0, <4",
|
||||
"sqlalchemy>=1.4, <2",
|
||||
"sqlalchemy-continuum>=1.6.0, <2.0.0",
|
||||
"sqlalchemy-utils>=0.42.1, <0.43", # expanding lowerbound to work with pydoris
|
||||
"sqlglot>=30.12.0, <31",
|
||||
"sqlglot>=30.8.0, <31",
|
||||
# newer pandas needs 0.9+
|
||||
"tabulate>=0.10.0, <1.0",
|
||||
"typing-extensions>=4, <5",
|
||||
@@ -160,18 +160,19 @@ fastmcp = [
|
||||
# heuristic that under-counts JSON-heavy MCP responses.
|
||||
"tiktoken>=0.13.0,<1.0",
|
||||
]
|
||||
firebird = ["sqlalchemy-firebird>=0.8.0, <2.2"]
|
||||
firebird = ["sqlalchemy-firebird>=0.7.0, <2.2"]
|
||||
firebolt = ["firebolt-sqlalchemy>=1.0.0, <2"]
|
||||
gevent = ["gevent>=26.4.0"]
|
||||
gsheets = ["shillelagh[gsheetsapi]>=1.4.4, <2"]
|
||||
hana = ["hdbcli==2.28.21", "sqlalchemy_hana==3.0.3"]
|
||||
hana = ["hdbcli==2.28.21", "sqlalchemy_hana==0.4.0"]
|
||||
hive = [
|
||||
"pyhive[hive]>=0.6.5;python_version<'3.11'",
|
||||
"pyhive[hive_pure_sasl]>=0.7.0",
|
||||
"tableschema",
|
||||
"thrift>=0.23.0, <1.0.0",
|
||||
"thrift_sasl>=0.4.3, < 1.0.0",
|
||||
]
|
||||
impala = ["impyla>=0.24.0, <0.25"]
|
||||
impala = ["impyla>0.16.2, <0.23"]
|
||||
kusto = ["sqlalchemy-kusto>=3.1.2, <4"]
|
||||
kylin = ["kylinpy>=2.8.4, <2.9"]
|
||||
mssql = ["pymssql>=2.3.13, <3"]
|
||||
@@ -197,8 +198,9 @@ risingwave = ["sqlalchemy-risingwave"]
|
||||
shillelagh = ["shillelagh[all]>=1.4.4, <2"]
|
||||
singlestore = ["sqlalchemy-singlestoredb>=1.2.1, <2"]
|
||||
snowflake = ["snowflake-sqlalchemy>=1.10.2, <2"]
|
||||
sqlite = ["syntaqlite>=0.6.0,<0.7.0"]
|
||||
sqlite = ["syntaqlite>=0.1.0,<0.5.0"]
|
||||
spark = [
|
||||
"pyhive[hive]>=0.6.5;python_version<'3.11'",
|
||||
"pyhive[hive_pure_sasl]>=0.7",
|
||||
"tableschema",
|
||||
"thrift>=0.23.0, <1",
|
||||
@@ -207,7 +209,7 @@ tdengine = [
|
||||
"taospy>=2.8.9",
|
||||
"taos-ws-py>=0.6.9"
|
||||
]
|
||||
teradata = ["teradatasql>=20.0.0.62"]
|
||||
teradata = ["teradatasql>=16.20.0.23"]
|
||||
thumbnails = [] # deprecated, will be removed in 7.0
|
||||
vertica = ["sqlalchemy-vertica-python>= 0.6.3, < 0.7"]
|
||||
netezza = ["nzalchemy>=11.0.2, < 11.2"]
|
||||
@@ -233,7 +235,7 @@ development = [
|
||||
"pyfakefs",
|
||||
"pyinstrument>=5.1.2,<6",
|
||||
"pylint",
|
||||
"pytest<10.0.0", # cap below the next major until validated; the earlier <8 pin (current_app proxy timing) no longer reproduces
|
||||
"pytest<8.0.0", # hairy issue with pytest >=8 where current_app proxies are not set in time
|
||||
"pytest-asyncio",
|
||||
"pytest-cov",
|
||||
"pytest-mock",
|
||||
@@ -241,7 +243,7 @@ development = [
|
||||
"ruff",
|
||||
"sqloxide",
|
||||
"statsd",
|
||||
"syntaqlite>=0.6.0,<0.7.0",
|
||||
"syntaqlite>=0.4.2,<0.5.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
@@ -341,8 +343,8 @@ exclude = [
|
||||
line-length = 88
|
||||
indent-width = 4
|
||||
|
||||
# Assume Python 3.11
|
||||
target-version = "py311"
|
||||
# Assume Python 3.10
|
||||
target-version = "py310"
|
||||
|
||||
[tool.ruff.lint]
|
||||
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
||||
|
||||
@@ -35,13 +35,13 @@ filterwarnings =
|
||||
# error:"SqlMetric" object is being merged into a Session:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:"TableColumn" object is being merged into a Session:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:"TaggedObject" object is being merged into a Session:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:The ``as_declarative\(\)`` function is now available:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:The autoload parameter is deprecated:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:The connection.execute\(\) method:sqlalchemy.exc.RemovedIn20Warning
|
||||
error:The current statement is being autocommitted using implicit autocommit:sqlalchemy.exc.RemovedIn20Warning
|
||||
error:The connection.execute\(\) method:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:The current statement is being autocommitted using implicit autocommit:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:The `database` package is deprecated:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:The ``declarative_base\(\)`` function is now available:sqlalchemy.exc.RemovedIn20Warning
|
||||
error:The Engine.execute\(\) method is considered legacy:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:The Engine.execute\(\) method is considered legacy:sqlalchemy.exc.RemovedIn20Warning
|
||||
error:The legacy calling style of select\(\) is deprecated:sqlalchemy.exc.RemovedIn20Warning
|
||||
error:The "whens" argument to case:sqlalchemy.exc.RemovedIn20Warning
|
||||
# error:"User" object is being merged into a Session:sqlalchemy.exc.RemovedIn20Warning
|
||||
|
||||
@@ -44,11 +44,11 @@ cachelib==0.13.0
|
||||
# via
|
||||
# flask-caching
|
||||
# flask-session
|
||||
cachetools==7.1.4
|
||||
cachetools==6.2.1
|
||||
# via apache-superset (pyproject.toml)
|
||||
cattrs==25.1.1
|
||||
# via requests-cache
|
||||
celery==5.6.3
|
||||
celery==5.5.2
|
||||
# via apache-superset (pyproject.toml)
|
||||
certifi==2026.5.20
|
||||
# via
|
||||
@@ -175,7 +175,7 @@ h11==0.16.0
|
||||
# via wsproto
|
||||
hashids==1.3.1
|
||||
# via apache-superset (pyproject.toml)
|
||||
holidays==0.100
|
||||
holidays==0.82
|
||||
# via apache-superset (pyproject.toml)
|
||||
humanize==4.12.3
|
||||
# via apache-superset (pyproject.toml)
|
||||
@@ -207,7 +207,7 @@ jsonschema-specifications==2025.4.1
|
||||
# via
|
||||
# jsonschema
|
||||
# openapi-schema-validator
|
||||
kombu==5.6.2
|
||||
kombu==5.5.3
|
||||
# via celery
|
||||
limits==5.1.0
|
||||
# via flask-limiter
|
||||
@@ -272,7 +272,6 @@ packaging==25.0
|
||||
# apispec
|
||||
# deprecation
|
||||
# gunicorn
|
||||
# kombu
|
||||
# limits
|
||||
# shillelagh
|
||||
pandas==2.1.4
|
||||
@@ -390,7 +389,7 @@ six==1.17.0
|
||||
# python-dateutil
|
||||
# rfc3339-validator
|
||||
# wtforms-json
|
||||
slack-sdk==3.43.0
|
||||
slack-sdk==3.42.0
|
||||
# via apache-superset (pyproject.toml)
|
||||
sniffio==1.3.1
|
||||
# via trio
|
||||
@@ -405,16 +404,13 @@ sqlalchemy==1.4.54
|
||||
# flask-sqlalchemy
|
||||
# marshmallow-sqlalchemy
|
||||
# shillelagh
|
||||
# sqlalchemy-continuum
|
||||
# sqlalchemy-utils
|
||||
sqlalchemy-continuum==1.6.0
|
||||
# via apache-superset (pyproject.toml)
|
||||
sqlalchemy-utils==0.42.1
|
||||
# via
|
||||
# apache-superset (pyproject.toml)
|
||||
# apache-superset-core
|
||||
# flask-appbuilder
|
||||
sqlglot==30.12.0
|
||||
sqlglot==30.8.0
|
||||
# via
|
||||
# apache-superset (pyproject.toml)
|
||||
# apache-superset-core
|
||||
@@ -448,8 +444,6 @@ tzdata==2025.2
|
||||
# via
|
||||
# kombu
|
||||
# pandas
|
||||
tzlocal==5.4.4
|
||||
# via celery
|
||||
url-normalize==2.2.1
|
||||
# via requests-cache
|
||||
urllib3==2.7.0
|
||||
|
||||
@@ -97,7 +97,7 @@ cachelib==0.13.0
|
||||
# -c requirements/base-constraint.txt
|
||||
# flask-caching
|
||||
# flask-session
|
||||
cachetools==7.1.4
|
||||
cachetools==6.2.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -108,7 +108,7 @@ cattrs==25.1.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# requests-cache
|
||||
celery==5.6.3
|
||||
celery==5.5.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -407,7 +407,7 @@ hashids==1.3.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
holidays==0.100
|
||||
holidays==0.82
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -503,7 +503,7 @@ keyring==25.7.0
|
||||
# via py-key-value-aio
|
||||
kiwisolver==1.4.7
|
||||
# via matplotlib
|
||||
kombu==5.6.2
|
||||
kombu==5.5.3
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# celery
|
||||
@@ -635,7 +635,6 @@ packaging==25.0
|
||||
# fastmcp-slim
|
||||
# google-cloud-bigquery
|
||||
# gunicorn
|
||||
# kombu
|
||||
# limits
|
||||
# matplotlib
|
||||
# pytest
|
||||
@@ -959,7 +958,7 @@ six==1.17.0
|
||||
# python-dateutil
|
||||
# rfc3339-validator
|
||||
# wtforms-json
|
||||
slack-sdk==3.43.0
|
||||
slack-sdk==3.42.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -984,21 +983,16 @@ sqlalchemy==1.4.54
|
||||
# marshmallow-sqlalchemy
|
||||
# shillelagh
|
||||
# sqlalchemy-bigquery
|
||||
# sqlalchemy-continuum
|
||||
# sqlalchemy-utils
|
||||
sqlalchemy-bigquery==1.17.0
|
||||
# via apache-superset
|
||||
sqlalchemy-continuum==1.6.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
sqlalchemy-utils==0.42.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# apache-superset-core
|
||||
# flask-appbuilder
|
||||
sqlglot==30.12.0
|
||||
sqlglot==30.8.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -1017,7 +1011,7 @@ starlette==1.3.1
|
||||
# mcp
|
||||
statsd==4.0.1
|
||||
# via apache-superset
|
||||
syntaqlite==0.6.0
|
||||
syntaqlite==0.4.2
|
||||
# via apache-superset
|
||||
tabulate==0.10.0
|
||||
# via
|
||||
@@ -1078,11 +1072,8 @@ tzdata==2025.2
|
||||
# -c requirements/base-constraint.txt
|
||||
# kombu
|
||||
# pandas
|
||||
tzlocal==5.4.4
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# celery
|
||||
# trino
|
||||
tzlocal==5.2
|
||||
# via trino
|
||||
uncalled-for==0.2.0
|
||||
# via fastmcp-slim
|
||||
url-normalize==2.2.1
|
||||
|
||||
@@ -153,11 +153,10 @@ def main( # noqa: C901
|
||||
)
|
||||
|
||||
print(f"Migration goes from {down_revision} to {revision}")
|
||||
with db.engine.connect() as conn:
|
||||
current_revision = conn.execute(
|
||||
text("SELECT version_num FROM alembic_version")
|
||||
).scalar()
|
||||
print(f"Current version of the DB is {current_revision}")
|
||||
current_revision = db.engine.execute(
|
||||
text("SELECT version_num FROM alembic_version")
|
||||
).scalar()
|
||||
print(f"Current version of the DB is {current_revision}")
|
||||
|
||||
if current_revision != down_revision:
|
||||
if not force:
|
||||
|
||||
@@ -133,8 +133,8 @@ def main(docker: bool, frontend: bool, backend: bool) -> None: # noqa: C901
|
||||
requirements = [
|
||||
Requirement(
|
||||
"python",
|
||||
(Version("3.11.0"), Version("3.11.999")),
|
||||
(Version("3.11.0"), Version("3.12.999")),
|
||||
(Version("3.10.0"), Version("3.10.999")),
|
||||
(Version("3.9.0"), Version("3.11.999")),
|
||||
"backend",
|
||||
"python --version",
|
||||
),
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/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 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.
|
||||
|
||||
set -e
|
||||
|
||||
script_dir="$(dirname "$(realpath "$0")")"
|
||||
root_dir="$(dirname "$script_dir")"
|
||||
frontend_dir=superset-frontend
|
||||
|
||||
if [[ ! -d "$root_dir/$frontend_dir" ]]; then
|
||||
echo "Error: $frontend_dir directory not found in $root_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$root_dir/$frontend_dir"
|
||||
|
||||
# Filter files to only include JS/TS files and remove the frontend dir prefix
|
||||
js_ts_files=()
|
||||
for file in "$@"; do
|
||||
# Remove superset-frontend/ prefix if present
|
||||
cleaned_file="${file#$frontend_dir/}"
|
||||
|
||||
# Only include JS/TS files (Emotion styles live in these)
|
||||
if [[ "$cleaned_file" =~ \.(js|jsx|ts|tsx)$ ]]; then
|
||||
js_ts_files+=("$cleaned_file")
|
||||
fi
|
||||
done
|
||||
|
||||
# Only run if we have JS/TS files to lint. --allow-empty-input keeps the hook
|
||||
# green when every passed file is covered by .stylelintignore.
|
||||
if [ ${#js_ts_files[@]} -gt 0 ]; then
|
||||
npx stylelint --allow-empty-input "${js_ts_files[@]}"
|
||||
else
|
||||
echo "No JavaScript/TypeScript files to lint for styles"
|
||||
fi
|
||||
@@ -92,33 +92,4 @@ do
|
||||
fi
|
||||
done
|
||||
|
||||
# A few UI labels ("% calculation" etc.) parse as accidentally-valid
|
||||
# %-format directives (a space flag plus a conversion character), so
|
||||
# babel auto-flags them python-format on every write and msgfmt then
|
||||
# fatals on their translations. The app never %-formats them; strip the
|
||||
# flag AFTER the update pass (babel re-adds it during the update, so
|
||||
# this must run last). Line-targeted so canonical wrapping is untouched.
|
||||
python3 - <<'PYEOF'
|
||||
import glob
|
||||
|
||||
TARGETS = {'msgid "% calculation"\n', 'msgid "% of parent"\n', 'msgid "% of total"\n'}
|
||||
paths = ["superset/translations/messages.pot"] + sorted(
|
||||
glob.glob("superset/translations/*/LC_MESSAGES/messages.po")
|
||||
)
|
||||
for path in paths:
|
||||
lines = open(path, encoding="utf-8").readlines()
|
||||
changed = False
|
||||
for i, line in enumerate(lines):
|
||||
if line in TARGETS and i > 0 and lines[i - 1].startswith("#,"):
|
||||
tokens = [t.strip() for t in lines[i - 1][2:].split(",")]
|
||||
if "python-format" in tokens:
|
||||
tokens = [t for t in tokens if t != "python-format"]
|
||||
if "no-python-format" not in tokens:
|
||||
tokens.append("no-python-format")
|
||||
lines[i - 1] = "#, " + ", ".join(tokens) + "\n"
|
||||
changed = True
|
||||
if changed:
|
||||
open(path, "w", encoding="utf-8").writelines(lines)
|
||||
PYEOF
|
||||
|
||||
cd $CURRENT_DIR
|
||||
|
||||
@@ -21,7 +21,7 @@ under the License.
|
||||
|
||||
[](https://badge.fury.io/py/apache-superset-core)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://www.python.org/downloads/)
|
||||
|
||||
The official core package for building Apache Superset backend extensions and integrations. This package provides essential building blocks including base classes, API utilities, type definitions, and decorators for both the host application and extensions.
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ authors = [
|
||||
]
|
||||
license = "Apache-2.0"
|
||||
license-files = ["LICENSE.txt"]
|
||||
requires-python = ">=3.11"
|
||||
requires-python = ">=3.10"
|
||||
keywords = ["superset", "apache", "analytics", "business-intelligence", "extensions", "visualization"]
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
@@ -34,6 +34,7 @@ classifiers = [
|
||||
"Intended Audience :: Developers",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Database",
|
||||
|
||||
@@ -42,10 +42,7 @@ from superset_core.common.models import (
|
||||
Dashboard,
|
||||
Database,
|
||||
Dataset,
|
||||
Group,
|
||||
KeyValue,
|
||||
Role,
|
||||
Subject,
|
||||
Tag,
|
||||
User,
|
||||
)
|
||||
@@ -193,34 +190,6 @@ class UserDAO(BaseDAO[User]):
|
||||
id_column_name = "id"
|
||||
|
||||
|
||||
class RoleDAO(BaseDAO[Role]):
|
||||
"""
|
||||
Abstract Role DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
|
||||
|
||||
class GroupDAO(BaseDAO[Group]):
|
||||
"""
|
||||
Abstract Group DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
|
||||
|
||||
class TagDAO(BaseDAO[Tag]):
|
||||
"""
|
||||
Abstract Tag DAO interface.
|
||||
@@ -249,16 +218,13 @@ class KeyValueDAO(BaseDAO[KeyValue]):
|
||||
id_column_name = "id"
|
||||
|
||||
|
||||
class SubjectDAO(BaseDAO[Subject]):
|
||||
"""
|
||||
Abstract Subject DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
uuid_column_name = "uuid"
|
||||
__all__ = [
|
||||
"BaseDAO",
|
||||
"DatasetDAO",
|
||||
"DatabaseDAO",
|
||||
"ChartDAO",
|
||||
"DashboardDAO",
|
||||
"UserDAO",
|
||||
"TagDAO",
|
||||
"KeyValueDAO",
|
||||
]
|
||||
|
||||
@@ -285,38 +285,6 @@ class User(CoreModel):
|
||||
active: bool
|
||||
|
||||
|
||||
class Role(CoreModel):
|
||||
"""
|
||||
Abstract Role model interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
name: str | None
|
||||
|
||||
|
||||
class Group(CoreModel):
|
||||
"""
|
||||
Abstract Group model interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
name: str | None
|
||||
label: str | None
|
||||
description: str | None
|
||||
|
||||
|
||||
class Tag(CoreModel):
|
||||
"""
|
||||
Abstract Tag model interface.
|
||||
@@ -352,33 +320,6 @@ class KeyValue(CoreModel):
|
||||
changed_by_fk: int | None
|
||||
|
||||
|
||||
class Subject(CoreModel):
|
||||
"""
|
||||
Abstract Subject model interface.
|
||||
|
||||
A Subject is a unified representation of a User, Role, or Group. Host
|
||||
implementations will replace this class during initialization with a
|
||||
concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
uuid: UUID | None
|
||||
label: str | None
|
||||
secondary_label: str | None
|
||||
active: bool | None
|
||||
extra_search: str | None
|
||||
type: int
|
||||
|
||||
# Convenience references to the underlying principal. Exactly one is set,
|
||||
# matching ``type`` (User, Role, or Group respectively).
|
||||
user: User | None
|
||||
role: Role | None
|
||||
group: Group | None
|
||||
|
||||
|
||||
def get_session() -> scoped_session:
|
||||
"""
|
||||
Retrieve the SQLAlchemy session to directly interface with the
|
||||
@@ -398,11 +339,8 @@ __all__ = [
|
||||
"Chart",
|
||||
"Dashboard",
|
||||
"User",
|
||||
"Role",
|
||||
"Group",
|
||||
"Tag",
|
||||
"KeyValue",
|
||||
"Subject",
|
||||
"CoreModel",
|
||||
"get_session",
|
||||
]
|
||||
|
||||
@@ -158,7 +158,7 @@ class Filter:
|
||||
type: PredicateType
|
||||
column: Dimension | Metric | None
|
||||
operator: Operator
|
||||
value: FilterValues | tuple[FilterValues, ...] | frozenset[FilterValues]
|
||||
value: FilterValues | frozenset[FilterValues]
|
||||
|
||||
|
||||
class OrderDirection(enum.Enum):
|
||||
|
||||
@@ -21,7 +21,7 @@ under the License.
|
||||
|
||||
[](https://badge.fury.io/py/apache-superset-extensions-cli)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://www.python.org/downloads/)
|
||||
|
||||
Official command-line interface for building, bundling, and managing Apache Superset extensions. This CLI tool provides developers with everything needed to create, develop, and package extensions for the Superset ecosystem.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ authors = [
|
||||
]
|
||||
license = "Apache-2.0"
|
||||
license-files = ["LICENSE.txt"]
|
||||
requires-python = ">=3.11"
|
||||
requires-python = ">=3.10"
|
||||
keywords = ["superset", "apache", "cli", "extensions", "analytics", "business-intelligence", "development-tools"]
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
@@ -33,6 +33,7 @@ classifiers = [
|
||||
"Intended Audience :: Developers",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Database",
|
||||
|
||||
@@ -22,7 +22,7 @@ import thunk from 'redux-thunk';
|
||||
import { Provider } from 'react-redux';
|
||||
import reducerIndex from 'spec/helpers/reducerIndex';
|
||||
import { Global } from '@emotion/react';
|
||||
import { App, Layout } from 'antd';
|
||||
import { App, Layout, Space, Content } from 'antd';
|
||||
|
||||
import 'src/theme.ts';
|
||||
import './storybook.css';
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# Files whose Emotion template literals nest a `css` tag inside an
|
||||
# interpolation (e.g. styled(X)`${props => css`...`}`) or otherwise use a
|
||||
# structure that postcss-styled-syntax cannot parse. Stylelint reports a
|
||||
# CssSyntaxError on these rather than a real lint finding, so they are
|
||||
# excluded until the syntax gains nested-template support.
|
||||
src/components/ListView/Filters/Base.ts
|
||||
src/features/databases/DatabaseModal/styles.ts
|
||||
src/features/databases/UploadDataModel/styles.ts
|
||||
packages/superset-ui-core/src/components/Typography/index.tsx
|
||||
@@ -471,19 +471,19 @@ export function applyAdvancedTimeRangeFilterOnDashboard(
|
||||
endRange?: string,
|
||||
) {
|
||||
cy.get('.control-label').contains('Range type').should('be.visible');
|
||||
cy.get('.ant-popover-content .ant-select-content')
|
||||
cy.get('.ant-popover-content .ant-select-selector')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get(`[label="Advanced"]`).should('be.visible').click();
|
||||
cy.get('.section-title').contains('Advanced Time Range').should('be.visible');
|
||||
if (startRange) {
|
||||
cy.get('.ant-popover-content')
|
||||
cy.get('.ant-popover-inner-content')
|
||||
.find('[class^=ant-input]')
|
||||
.first()
|
||||
.type(`${startRange}`);
|
||||
}
|
||||
if (endRange) {
|
||||
cy.get('.ant-popover-content')
|
||||
cy.get('.ant-popover-inner-content')
|
||||
.find('[class^=ant-input]')
|
||||
.last()
|
||||
.type(`${endRange}`);
|
||||
@@ -514,14 +514,15 @@ export function inputNativeFilterDefaultValue(
|
||||
)
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get('.ant-select-input').type(`${defaultValue}{enter}`, {
|
||||
force: true,
|
||||
});
|
||||
cy.get('.ant-select-selection-search-input').type(
|
||||
`${defaultValue}{enter}`,
|
||||
{ force: true },
|
||||
);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
cy.getBySel('default-input').within(() => {
|
||||
cy.get('.ant-select-input').click();
|
||||
cy.get('.ant-select-selection-search-input').click();
|
||||
cy.get('.ant-select-item-option-content').contains(defaultValue).click();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -53,7 +53,9 @@ export function saveChartToDashboard(chartName: string, dashboardName: string) {
|
||||
.then($modal => {
|
||||
cy.wait(500);
|
||||
cy.wrap($modal)
|
||||
.find('.ant-select-input[aria-label*="Select a dashboard"]')
|
||||
.find(
|
||||
'.ant-select-selection-search-input[aria-label*="Select a dashboard"]',
|
||||
)
|
||||
.type(dashboardName, { force: true });
|
||||
|
||||
cy.get(`.ant-select-item-option[title="${dashboardName}"]`).click();
|
||||
|
||||
@@ -52,7 +52,7 @@ export const securityAccess = {
|
||||
};
|
||||
export const homePage = {
|
||||
homeSection: {
|
||||
sectionArea: '.ant-collapse-body',
|
||||
sectionArea: '.ant-collapse-content-box',
|
||||
sectionElement: '.ant-card-meta-title',
|
||||
},
|
||||
sections: {
|
||||
@@ -91,7 +91,7 @@ export const databasesPage = {
|
||||
preferredBlockSheets: '.preferred > :nth-child(6)',
|
||||
supportedDatabasesText: '.control-label',
|
||||
orChoose: '.available-label',
|
||||
dbDropdown: '.ant-select-input',
|
||||
dbDropdown: '[class="ant-select-selection-search-input"]',
|
||||
dbDropdownMenu: '.rc-virtual-list-holder-inner',
|
||||
dbDropdownMenuItem: '[class="ant-select-item-option-content"]',
|
||||
infoAlert: '.ant-alert',
|
||||
@@ -277,7 +277,7 @@ export const chartListView = {
|
||||
header: {
|
||||
cardView: '[aria-label="card-view"]',
|
||||
listView: '[aria-label="list-view"]',
|
||||
sort: '.ant-select-input[aria-label="Sort"]',
|
||||
sort: '[class="ant-select-selection-search-input"][aria-label="Sort"]',
|
||||
sortRecentlyModifiedMenuOption: '[label="Recently modified"]',
|
||||
sortAlphabeticalMenuOption: '[label="Alphabetical"]',
|
||||
sortDropdown: '.Select__menu',
|
||||
@@ -338,20 +338,20 @@ export const nativeFilters = {
|
||||
filtersPanel: {
|
||||
filterName: dataTestLocator('filters-config-modal__name-input'),
|
||||
datasetName: dataTestLocator('filters-config-modal__datasource-input'),
|
||||
filterInfoInput: '.ant-select-input',
|
||||
filterInfoInput: '.ant-select-selection-search-input',
|
||||
inputDropdown: '.ant-select-item-option-content',
|
||||
columnEmptyInput: '.ant-select-placeholder',
|
||||
columnEmptyInput: '.ant-select-selection-placeholder',
|
||||
filterTypeInput: dataTestLocator('filters-config-modal__filter-type'),
|
||||
fieldInput: dataTestLocator('field-input'),
|
||||
filterTypeItem: '.ant-select-content-has-value, .ant-select-selection-item',
|
||||
filterTypeItem: '.ant-select-selection-item',
|
||||
filterGear: dataTestLocator('filterbar-orientation-icon'),
|
||||
},
|
||||
filterFromDashboardView: {
|
||||
filterValueInput: '.ant-select-input',
|
||||
filterValueInput: '[class="ant-select-selection-search-input"]',
|
||||
expand: dataTestLocator('filter-bar__expand-button'),
|
||||
collapse: dataTestLocator('filter-bar__collapse-button'),
|
||||
filterName: dataTestLocator('filter-control-name'),
|
||||
filterContent: '.ant-select-content-has-value, .ant-select-selection-item',
|
||||
filterContent: '.ant-select-selection-item',
|
||||
createFilterButton: dataTestLocator('filter-bar__create-filter'),
|
||||
timeRangeFilterContent: dataTestLocator('time-range-trigger'),
|
||||
},
|
||||
@@ -365,8 +365,8 @@ export const nativeFilters = {
|
||||
checkedCheckbox: '.ant-checkbox-wrapper-checked',
|
||||
infoTooltip: '[aria-label="Show info tooltip"]',
|
||||
parentFilterInput: dataTestLocator('parent-filter-input'),
|
||||
filterPlaceholder: '.ant-select-placeholder',
|
||||
collapsedSectionContainer: '[class="ant-collapse-body"]',
|
||||
filterPlaceholder: '.ant-select-selection-placeholder',
|
||||
collapsedSectionContainer: '[class="ant-collapse-content-box"]',
|
||||
},
|
||||
filtersList: {
|
||||
list: '.ant-tabs-nav-list',
|
||||
@@ -376,7 +376,7 @@ export const nativeFilters = {
|
||||
removeIcon: '[aria-label="delete"]',
|
||||
},
|
||||
filterItem: dataTestLocator('form-item-value'),
|
||||
filterItemDropdown: '.ant-select-input',
|
||||
filterItemDropdown: '.ant-select-selection-search',
|
||||
applyFilter: dataTestLocator('filter-bar__apply-button'),
|
||||
defaultInput: dataTestLocator('default-input'),
|
||||
filterIcon: dataTestLocator('filter-icon'),
|
||||
@@ -484,7 +484,7 @@ export const exploreView = {
|
||||
saveModal: {
|
||||
modal: '.ant-modal-content',
|
||||
chartNameInput: dataTestLocator('new-chart-name'),
|
||||
dashboardNameInput: '.ant-select-input',
|
||||
dashboardNameInput: '.ant-select-selection-search-input',
|
||||
addToDashboardInput: dataTestLocator(
|
||||
'save-chart-modal-select-dashboard-form',
|
||||
),
|
||||
@@ -495,7 +495,7 @@ export const exploreView = {
|
||||
},
|
||||
controlPanel: {
|
||||
panel: dataTestLocator('control-tabs'),
|
||||
categoryArea: '.ant-collapse-body',
|
||||
categoryArea: '.ant-collapse-content-box',
|
||||
dragField: dataTestLocator('datasource'),
|
||||
metricsField: dataTestLocator('metrics'),
|
||||
optionField: dataTestLocator('option-label'),
|
||||
@@ -594,7 +594,7 @@ export const exploreView = {
|
||||
},
|
||||
};
|
||||
export const createChartView = {
|
||||
chooseDatasetInput: '.ant-select-input',
|
||||
chooseDatasetInput: '.ant-select-selection-search-input',
|
||||
chooseDatasetOption: '.ant-select-item-option-content',
|
||||
chooseDatasetList: '.rc-virtual-list-holder-inner',
|
||||
tableVizType: "[alt='Table']",
|
||||
@@ -641,7 +641,7 @@ export const dashboardView = {
|
||||
secondTabSalesDashboard: dataTestLocator('dragdroppable-object'),
|
||||
},
|
||||
timeRangeModal: {
|
||||
rangeTypeField: '.ant-select-content-has-value, .ant-select-selection-item',
|
||||
rangeTypeField: '.ant-select-selection-item',
|
||||
startTimeInputNumber: '.ant-input-number-input',
|
||||
datePicker: '.ant-picker-input',
|
||||
applyButton: dataTestLocator('date-filter-control__apply-button'),
|
||||
|
||||
@@ -75,7 +75,7 @@ module.exports = {
|
||||
// @ant-design/colors and @ant-design/fast-color are allowed through because
|
||||
// @ant-design/icons >= 6.3 deep-imports the ESM build of @ant-design/colors
|
||||
// from its CJS output, so babel-jest must transform those files.
|
||||
'node_modules/(?!@ant-design/(colors|fast-color)|@formatjs/.*|d3-(array|interpolate|color|time|scale|time-format|format)|internmap|@mapbox/tiny-sdf|remark-gfm|(?!@ngrx|(?!deck.gl)|d3-scale)|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|uuid|@rjsf/*.|@x0k/.*|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|geostyler|geostyler-.*|(?!geostyler)lodash|react-error-boundary|react-json-tree|react-base16-styling|lodash-es|rbush|quickselect|react-diff-viewer-continued|storybook/*.|json-stringify-pretty-compact)',
|
||||
'node_modules/(?!@ant-design/(colors|fast-color)|@formatjs/.*|d3-(array|interpolate|color|time|scale|time-format|format)|internmap|@mapbox/tiny-sdf|remark-gfm|(?!@ngrx|(?!deck.gl)|d3-scale)|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|uuid|@rjsf/*.|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|geostyler|geostyler-.*|(?!geostyler)lodash|react-error-boundary|react-json-tree|react-base16-styling|lodash-es|rbush|quickselect|react-diff-viewer-continued|storybook/*.|json-stringify-pretty-compact)',
|
||||
],
|
||||
preset: 'ts-jest',
|
||||
transform: {
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
// require-default-props, sort-comp, static-property-placement
|
||||
// (prefer-stateless-function / function-component-definition
|
||||
// are represented by react/prefer-function-component below)
|
||||
// jsx-a11y: interactive-supports-focus,
|
||||
// no-interactive-element-to-noninteractive-role,
|
||||
// no-noninteractive-element-interactions,
|
||||
// no-noninteractive-element-to-interactive-role
|
||||
// typescript: naming-convention
|
||||
// unicorn: prevent-abbreviations
|
||||
|
||||
@@ -192,7 +196,6 @@
|
||||
|
||||
// === JSX-a11y rules ===
|
||||
"jsx-a11y/alt-text": "error",
|
||||
"jsx-a11y/anchor-ambiguous-text": "error",
|
||||
"jsx-a11y/anchor-has-content": "error",
|
||||
"jsx-a11y/anchor-is-valid": "error",
|
||||
"jsx-a11y/aria-activedescendant-has-tabindex": "error",
|
||||
@@ -200,31 +203,20 @@
|
||||
"jsx-a11y/aria-proptypes": "error",
|
||||
"jsx-a11y/aria-role": ["error", { "ignoreNonDOM": false }],
|
||||
"jsx-a11y/aria-unsupported-elements": "error",
|
||||
"jsx-a11y/autocomplete-valid": "error",
|
||||
"jsx-a11y/click-events-have-key-events": "off",
|
||||
"jsx-a11y/control-has-associated-label": "error",
|
||||
"jsx-a11y/heading-has-content": "error",
|
||||
"jsx-a11y/html-has-lang": "error",
|
||||
"jsx-a11y/iframe-has-title": "error",
|
||||
"jsx-a11y/img-redundant-alt": "error",
|
||||
"jsx-a11y/interactive-supports-focus": "error",
|
||||
"jsx-a11y/label-has-associated-control": "error",
|
||||
"jsx-a11y/lang": "error",
|
||||
"jsx-a11y/media-has-caption": "error",
|
||||
"jsx-a11y/mouse-events-have-key-events": "error",
|
||||
"jsx-a11y/mouse-events-have-key-events": "off",
|
||||
"jsx-a11y/no-access-key": "error",
|
||||
"jsx-a11y/no-aria-hidden-on-focusable": "error",
|
||||
"jsx-a11y/no-autofocus": ["error", { "ignoreNonDOM": true }],
|
||||
"jsx-a11y/no-distracting-elements": "error",
|
||||
"jsx-a11y/no-interactive-element-to-noninteractive-role": "error",
|
||||
"jsx-a11y/no-noninteractive-element-interactions": "error",
|
||||
"jsx-a11y/no-noninteractive-element-to-interactive-role": "error",
|
||||
"jsx-a11y/no-noninteractive-tabindex": "error",
|
||||
"jsx-a11y/no-redundant-roles": "error",
|
||||
// TODO: Graduate to "error" — remaining violations are event-boundary
|
||||
// wrappers (divs/spans whose handlers only stopPropagation) and test
|
||||
// scaffolding where adding a role is semantically wrong. Needs a
|
||||
// dedicated pass; see PR enabling the other jsx-a11y interactive rules.
|
||||
"jsx-a11y/no-static-element-interactions": "off",
|
||||
"jsx-a11y/role-has-required-aria-props": "error",
|
||||
"jsx-a11y/role-supports-aria-props": "error",
|
||||
@@ -240,14 +232,7 @@
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"argsIgnorePattern": "^_",
|
||||
"varsIgnorePattern": "^_",
|
||||
"caughtErrors": "none"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-unused-vars": "warn",
|
||||
"@typescript-eslint/prefer-optional-chain": "error",
|
||||
|
||||
// === Unicorn rules (bonus coverage) ===
|
||||
@@ -297,16 +282,6 @@
|
||||
"rules": {
|
||||
"jsx-a11y/no-redundant-roles": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
// The pivot table intentionally exposes `role="grid"` on its <table>
|
||||
// for interactive grid semantics (asserted by tableRenders.test.tsx).
|
||||
"files": [
|
||||
"plugins/plugin-chart-pivot-table/src/react-pivottable/TableRenderers.tsx"
|
||||
],
|
||||
"rules": {
|
||||
"jsx-a11y/no-noninteractive-element-to-interactive-role": "off"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ignorePatterns": [
|
||||
|
||||
3026
superset-frontend/package-lock.json
generated
3026
superset-frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -57,9 +57,7 @@
|
||||
"lint:all": "npx oxlint --config oxlint.json && npm run type",
|
||||
"lint-fix": "npx oxlint --config oxlint.json --fix --quiet",
|
||||
"lint-fix:all": "npx oxlint --config oxlint.json --fix",
|
||||
"lint:full": "npm run lint && npm run check:custom-rules && npm run stylelint",
|
||||
"stylelint": "stylelint \"{src,packages/*/src,plugins/*/src}/**/*.{ts,tsx}\"",
|
||||
"stylelint-fix": "stylelint --fix \"{src,packages/*/src,plugins/*/src}/**/*.{ts,tsx}\"",
|
||||
"lint:full": "npm run lint && npm run check:custom-rules",
|
||||
"check:custom-rules": "node scripts/check-custom-rules.js",
|
||||
"check:storybook-coverage": "node scripts/check-storybook-coverage.js",
|
||||
"ensure-oxc": "echo 'OXC linter is ready' && npx oxlint --version",
|
||||
@@ -109,7 +107,6 @@
|
||||
"@deck.gl/mesh-layers": "~9.2.5",
|
||||
"@deck.gl/react": "~9.2.5",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/modifiers": "^9.0.0",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@emotion/cache": "^11.4.0",
|
||||
@@ -130,9 +127,10 @@
|
||||
"@luma.gl/shadertools": "~9.2.5",
|
||||
"@luma.gl/webgl": "~9.2.5",
|
||||
"@reduxjs/toolkit": "^1.9.3",
|
||||
"@rjsf/core": "^6.6.2",
|
||||
"@rjsf/utils": "^6.6.2",
|
||||
"@rjsf/validator-ajv8": "^6.6.2",
|
||||
"@rjsf/antd": "^5.24.13",
|
||||
"@rjsf/core": "^5.24.13",
|
||||
"@rjsf/utils": "^5.24.3",
|
||||
"@rjsf/validator-ajv8": "^5.24.13",
|
||||
"@scarf/scarf": "^1.4.0",
|
||||
"@superset-ui/chart-controls": "file:./packages/superset-ui-chart-controls",
|
||||
"@superset-ui/core": "file:./packages/superset-ui-core",
|
||||
@@ -166,9 +164,9 @@
|
||||
"@visx/scale": "^4.0.0",
|
||||
"@visx/tooltip": "^4.0.0",
|
||||
"@visx/xychart": "^4.0.0",
|
||||
"ag-grid-community": "36.0.0",
|
||||
"ag-grid-react": "36.0.0",
|
||||
"antd": "^6.0.0",
|
||||
"ag-grid-community": "35.3.1",
|
||||
"ag-grid-react": "35.3.1",
|
||||
"antd": "^5.26.0",
|
||||
"chrono-node": "^2.9.1",
|
||||
"classnames": "^2.2.5",
|
||||
"content-disposition": "^2.0.1",
|
||||
@@ -187,7 +185,7 @@
|
||||
"geostyler-style": "11.0.2",
|
||||
"geostyler-wfs-parser": "^3.0.1",
|
||||
"google-auth-library": "^10.9.0",
|
||||
"immer": "^11.1.11",
|
||||
"immer": "^11.1.9",
|
||||
"interweave": "^13.1.1",
|
||||
"jquery": "^4.0.0",
|
||||
"js-levenshtein": "^1.1.6",
|
||||
@@ -206,7 +204,7 @@
|
||||
"query-string": "9.4.1",
|
||||
"re-resizable": "^6.11.2",
|
||||
"react": "^18.3.0",
|
||||
"react-arborist": "^3.13.2",
|
||||
"react-arborist": "^3.12.0",
|
||||
"react-checkbox-tree": "^1.8.0",
|
||||
"react-diff-viewer-continued": "^4.2.2",
|
||||
"react-dnd": "^11.1.3",
|
||||
@@ -273,7 +271,7 @@
|
||||
"@storybook/test-runner": "0.24.4",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@swc/core": "^1.15.43",
|
||||
"@swc/plugin-emotion": "^14.15.0",
|
||||
"@swc/plugin-emotion": "^14.14.1",
|
||||
"@swc/plugin-transform-imports": "^12.5.0",
|
||||
"@testing-library/dom": "^9.3.4",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
@@ -300,13 +298,13 @@
|
||||
"@types/rison": "0.1.0",
|
||||
"@types/tinycolor2": "^1.4.3",
|
||||
"@types/unzipper": "^0.10.11",
|
||||
"@typescript-eslint/eslint-plugin": "^8.63.0",
|
||||
"@typescript-eslint/parser": "^8.63.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.62.1",
|
||||
"@typescript-eslint/parser": "^8.62.1",
|
||||
"babel-jest": "^30.4.1",
|
||||
"babel-loader": "^10.1.1",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
||||
"baseline-browser-mapping": "^2.10.42",
|
||||
"baseline-browser-mapping": "^2.10.40",
|
||||
"cheerio": "1.2.0",
|
||||
"concurrently": "^10.0.3",
|
||||
"copy-webpack-plugin": "^14.0.0",
|
||||
@@ -345,9 +343,8 @@
|
||||
"mini-css-extract-plugin": "^2.10.2",
|
||||
"minimizer-webpack-plugin": "^5.6.1",
|
||||
"open-cli": "^9.0.0",
|
||||
"oxlint": "^1.73.0",
|
||||
"oxlint": "^1.72.0",
|
||||
"po2json": "^0.4.5",
|
||||
"postcss-styled-syntax": "^0.7.2",
|
||||
"prettier": "3.9.4",
|
||||
"prettier-plugin-packagejson": "^3.0.2",
|
||||
"process": "^0.11.10",
|
||||
@@ -360,21 +357,20 @@
|
||||
"speed-measure-webpack-plugin": "^1.6.0",
|
||||
"storybook": "10.4.6",
|
||||
"style-loader": "^4.0.0",
|
||||
"stylelint": "^17.14.0",
|
||||
"swc-loader": "^0.2.7",
|
||||
"ts-jest": "^29.4.11",
|
||||
"tscw-config": "^1.1.2",
|
||||
"tsx": "^4.23.0",
|
||||
"tsx": "^4.22.4",
|
||||
"typescript": "5.4.5",
|
||||
"unzipper": "^0.12.5",
|
||||
"vm-browserify": "^1.1.2",
|
||||
"wait-on": "^9.0.10",
|
||||
"webpack": "^5.108.4",
|
||||
"webpack": "^5.108.3",
|
||||
"webpack-bundle-analyzer": "^5.3.0",
|
||||
"webpack-cli": "^7.0.3",
|
||||
"webpack-dev-server": "^5.2.5",
|
||||
"webpack-manifest-plugin": "^6.0.1",
|
||||
"webpack-sources": "^3.5.1",
|
||||
"webpack-sources": "^3.5.0",
|
||||
"webpack-visualizer-plugin2": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -390,9 +386,6 @@
|
||||
},
|
||||
"overrides": {
|
||||
"uuid": "$uuid",
|
||||
"@great-expectations/jsonforms-antd-renderers": {
|
||||
"antd": "$antd"
|
||||
},
|
||||
"core-js": "^3.38.1",
|
||||
"dompurify": "^3.4.11",
|
||||
"esbuild": "^0.28.1",
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"react-loadable": "^5.5.0",
|
||||
"tinycolor2": "*",
|
||||
"lodash": "^4.18.1",
|
||||
"antd": "^6.0.0",
|
||||
"antd": "^5.26.0",
|
||||
"jed": "^1.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -38,7 +38,7 @@ export const GlobalStyles = () => {
|
||||
<Global
|
||||
key={`global-${theme.colorLink}`}
|
||||
styles={css`
|
||||
/* SPA */
|
||||
// SPA
|
||||
html {
|
||||
color-scheme: ${isDark ? 'dark' : 'light'};
|
||||
}
|
||||
@@ -93,7 +93,7 @@ export const GlobalStyles = () => {
|
||||
}
|
||||
}
|
||||
|
||||
/* Overriding bootstrap styles */
|
||||
// Overriding bootstrap styles
|
||||
#app {
|
||||
flex: 1 1 auto;
|
||||
position: relative;
|
||||
@@ -105,18 +105,8 @@ export const GlobalStyles = () => {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* antd 6 removed the Tag's default trailing margin (v5 shipped */
|
||||
/* margin-inline-end: 8px on every tag) in favor of parents spacing */
|
||||
/* tags via flex/Space gaps. The app's layouts predate that and rely */
|
||||
/* on the v5 default (e.g. the dashboard header's Published tag), */
|
||||
/* so restore it for visual parity. Remove once Tag-adjacent layouts */
|
||||
/* declare their own gaps. */
|
||||
.ant-tag {
|
||||
margin-inline-end: ${theme.marginXS}px;
|
||||
}
|
||||
|
||||
/* Override geostyler CSS that hides AntD ColorPicker alpha input */
|
||||
/* See: https://github.com/apache/superset/issues/34721 */
|
||||
// Override geostyler CSS that hides AntD ColorPicker alpha input
|
||||
// See: https://github.com/apache/superset/issues/34721
|
||||
.ant-color-picker .ant-color-picker-alpha-input {
|
||||
display: block;
|
||||
}
|
||||
@@ -127,7 +117,7 @@ export const GlobalStyles = () => {
|
||||
}
|
||||
|
||||
.superset-explore-popover.ant-popover
|
||||
.ant-popover-container:has(.ant-popover-title) {
|
||||
.ant-popover-inner:has(.ant-popover-title) {
|
||||
padding-top: 0;
|
||||
}
|
||||
.superset-explore-popover.ant-popover .ant-popover-title {
|
||||
@@ -136,7 +126,7 @@ export const GlobalStyles = () => {
|
||||
line-height: 1;
|
||||
}
|
||||
.superset-explore-popover.ant-popover
|
||||
.ant-popover-container:has(.ant-popover-title)
|
||||
.ant-popover-inner:has(.ant-popover-title)
|
||||
.ant-tabs-tab {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
@@ -18,34 +18,7 @@
|
||||
*/
|
||||
import { theme as antdThemeImport } from 'antd';
|
||||
import { Theme } from './Theme';
|
||||
import { AnyThemeConfig, ThemeAlgorithm, allowedAntdTokens } from './types';
|
||||
|
||||
/**
|
||||
* A fixed, Superset-representative base theme used by the characterization
|
||||
* tests below. Mirrors the real THEME_DEFAULT token set so the snapshots are
|
||||
* stable and meaningful. Do NOT churn this casually — it is the baseline the
|
||||
* Ant Design v6 upgrade is measured against.
|
||||
*/
|
||||
const SUPERSET_BASE_THEME: AnyThemeConfig = {
|
||||
token: {
|
||||
colorPrimary: '#2893B3',
|
||||
colorError: '#e04355',
|
||||
colorWarning: '#fcc700',
|
||||
colorSuccess: '#5ac189',
|
||||
colorInfo: '#66bcfe',
|
||||
fontFamily: "'Inter', Helvetica, Arial",
|
||||
fontFamilyCode: "'IBM Plex Mono', 'Courier New', monospace",
|
||||
},
|
||||
};
|
||||
|
||||
/** Collect the computed value of every allow-listed antd token, sorted. */
|
||||
function pickAllowedTokens(theme: Theme): Record<string, unknown> {
|
||||
const out: Record<string, unknown> = {};
|
||||
[...allowedAntdTokens].sort().forEach(key => {
|
||||
out[key] = (theme.theme as unknown as Record<string, unknown>)[key];
|
||||
});
|
||||
return out;
|
||||
}
|
||||
import { AnyThemeConfig, ThemeAlgorithm } from './types';
|
||||
|
||||
// Mock emotion's cache to avoid actual DOM operations
|
||||
jest.mock('@emotion/cache', () => ({
|
||||
@@ -365,10 +338,10 @@ test('Theme edge cases correctly applies base theme tokens in dark mode', () =>
|
||||
algorithm: antdThemeImport.defaultAlgorithm,
|
||||
};
|
||||
|
||||
const baseThemeDark = {
|
||||
const baseThemeDark: AnyThemeConfig = {
|
||||
...baseTheme,
|
||||
algorithm: antdThemeImport.darkAlgorithm,
|
||||
} as AnyThemeConfig;
|
||||
};
|
||||
|
||||
// Simulate light mode with base theme
|
||||
const lightTheme = Theme.fromConfig({}, baseTheme);
|
||||
@@ -500,10 +473,10 @@ test('Theme base theme integration handles base theme with dark algorithm correc
|
||||
},
|
||||
};
|
||||
|
||||
const baseThemeDark = {
|
||||
const baseThemeDark: AnyThemeConfig = {
|
||||
...baseTheme,
|
||||
algorithm: antdThemeImport.darkAlgorithm,
|
||||
} as AnyThemeConfig;
|
||||
};
|
||||
|
||||
const userDarkTheme: AnyThemeConfig = {
|
||||
algorithm: antdThemeImport.darkAlgorithm,
|
||||
@@ -552,7 +525,7 @@ test('Theme base theme integration works with real-world Superset base theme con
|
||||
const darkTheme = Theme.fromConfig(themeDark, {
|
||||
...supersetBaseTheme,
|
||||
algorithm: antdThemeImport.darkAlgorithm,
|
||||
} as AnyThemeConfig);
|
||||
});
|
||||
expect(darkTheme.theme.fontFamily).toBe("'Inter', Helvetica, Arial");
|
||||
|
||||
const darkSerialized = darkTheme.toSerializedConfig();
|
||||
@@ -631,9 +604,7 @@ test('Theme base theme integration handles cssVar, hashed and inherit properties
|
||||
|
||||
// User properties override/add to base
|
||||
expect(serialized.inherit).toBe(true);
|
||||
// Ant Design v6 dropped boolean `cssVar`; Superset normalizes `true` to the
|
||||
// object form `{}` at the antd boundary (CSS variables are on by default).
|
||||
expect(serialized.cssVar).toEqual({});
|
||||
expect(serialized.cssVar).toBe(true);
|
||||
expect(serialized.hashed).toBe(false);
|
||||
|
||||
// Tokens are still merged
|
||||
@@ -938,81 +909,3 @@ test('colorLink is preserved in setConfig when explicitly set', () => {
|
||||
expect(theme.theme.colorPrimary).toBe('#f759ab');
|
||||
expect(theme.theme.colorLink).toBe('#ff0000');
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Characterization tests — theming safety net for the Ant Design v6 upgrade.
|
||||
//
|
||||
// These lock the bridge between Superset's theme and Ant Design's design
|
||||
// tokens (getDesignToken -> allowedAntdTokens -> SupersetTheme). When antd
|
||||
// renames or removes a token, the completeness tests fail loudly instead of
|
||||
// letting a token silently resolve to `undefined`, and the snapshots make any
|
||||
// value drift reviewable. See packages/superset-core/src/theme/types.ts.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test('every allowed antd token resolves to a defined value in light mode', () => {
|
||||
const theme = Theme.fromConfig(
|
||||
{ algorithm: antdThemeImport.defaultAlgorithm },
|
||||
SUPERSET_BASE_THEME,
|
||||
);
|
||||
|
||||
const missing = allowedAntdTokens.filter(
|
||||
key =>
|
||||
(theme.theme as unknown as Record<string, unknown>)[key] === undefined,
|
||||
);
|
||||
|
||||
// A non-empty list means antd dropped/renamed a token we still allow-list.
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
|
||||
test('every allowed antd token resolves to a defined value in dark mode', () => {
|
||||
const theme = Theme.fromConfig(
|
||||
{ algorithm: antdThemeImport.darkAlgorithm },
|
||||
SUPERSET_BASE_THEME,
|
||||
);
|
||||
|
||||
const missing = allowedAntdTokens.filter(
|
||||
key =>
|
||||
(theme.theme as unknown as Record<string, unknown>)[key] === undefined,
|
||||
);
|
||||
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
|
||||
test('allowed antd token key set is stable', () => {
|
||||
// Locks the *set* of tokens Superset exposes (independent of their values),
|
||||
// so additions/removals to allowedAntdTokens are an explicit, reviewed diff.
|
||||
expect([...allowedAntdTokens].sort()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('computed light-mode token values match snapshot', () => {
|
||||
const theme = Theme.fromConfig(
|
||||
{ algorithm: antdThemeImport.defaultAlgorithm },
|
||||
SUPERSET_BASE_THEME,
|
||||
);
|
||||
|
||||
expect(pickAllowedTokens(theme)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('computed dark-mode token values match snapshot', () => {
|
||||
const theme = Theme.fromConfig(
|
||||
{ algorithm: antdThemeImport.darkAlgorithm },
|
||||
SUPERSET_BASE_THEME,
|
||||
);
|
||||
|
||||
expect(pickAllowedTokens(theme)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('dark mode actually diverges from light mode for background tokens', () => {
|
||||
const light = Theme.fromConfig(
|
||||
{ algorithm: antdThemeImport.defaultAlgorithm },
|
||||
SUPERSET_BASE_THEME,
|
||||
);
|
||||
const dark = Theme.fromConfig(
|
||||
{ algorithm: antdThemeImport.darkAlgorithm },
|
||||
SUPERSET_BASE_THEME,
|
||||
);
|
||||
|
||||
// Guards the dark algorithm wiring: base surface and text must invert.
|
||||
expect(dark.theme.colorBgBase).not.toBe(light.theme.colorBgBase);
|
||||
expect(dark.theme.colorTextBase).not.toBe(light.theme.colorTextBase);
|
||||
});
|
||||
|
||||
@@ -1,730 +0,0 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`allowed antd token key set is stable 1`] = `
|
||||
[
|
||||
"borderRadius",
|
||||
"borderRadiusLG",
|
||||
"borderRadiusOuter",
|
||||
"borderRadiusSM",
|
||||
"borderRadiusXS",
|
||||
"boxShadow",
|
||||
"boxShadowDrawerLeft",
|
||||
"boxShadowDrawerRight",
|
||||
"boxShadowDrawerUp",
|
||||
"boxShadowPopoverArrow",
|
||||
"boxShadowSecondary",
|
||||
"boxShadowTabsOverflowBottom",
|
||||
"boxShadowTabsOverflowLeft",
|
||||
"boxShadowTabsOverflowRight",
|
||||
"boxShadowTabsOverflowTop",
|
||||
"boxShadowTertiary",
|
||||
"colorBgBase",
|
||||
"colorBgBlur",
|
||||
"colorBgContainer",
|
||||
"colorBgContainerDisabled",
|
||||
"colorBgElevated",
|
||||
"colorBgLayout",
|
||||
"colorBgMask",
|
||||
"colorBgSpotlight",
|
||||
"colorBgTextActive",
|
||||
"colorBgTextHover",
|
||||
"colorBorder",
|
||||
"colorBorderBg",
|
||||
"colorBorderSecondary",
|
||||
"colorError",
|
||||
"colorErrorActive",
|
||||
"colorErrorBg",
|
||||
"colorErrorBgActive",
|
||||
"colorErrorBgHover",
|
||||
"colorErrorBorder",
|
||||
"colorErrorBorderHover",
|
||||
"colorErrorHover",
|
||||
"colorErrorOutline",
|
||||
"colorErrorText",
|
||||
"colorErrorTextActive",
|
||||
"colorErrorTextHover",
|
||||
"colorFill",
|
||||
"colorFillAlter",
|
||||
"colorFillContent",
|
||||
"colorFillContentHover",
|
||||
"colorFillQuaternary",
|
||||
"colorFillSecondary",
|
||||
"colorFillTertiary",
|
||||
"colorHighlight",
|
||||
"colorIcon",
|
||||
"colorIconHover",
|
||||
"colorInfo",
|
||||
"colorInfoActive",
|
||||
"colorInfoBg",
|
||||
"colorInfoBgHover",
|
||||
"colorInfoBorder",
|
||||
"colorInfoBorderHover",
|
||||
"colorInfoHover",
|
||||
"colorInfoText",
|
||||
"colorInfoTextActive",
|
||||
"colorInfoTextHover",
|
||||
"colorLink",
|
||||
"colorLinkActive",
|
||||
"colorLinkHover",
|
||||
"colorPrimary",
|
||||
"colorPrimaryActive",
|
||||
"colorPrimaryBg",
|
||||
"colorPrimaryBgHover",
|
||||
"colorPrimaryBorder",
|
||||
"colorPrimaryBorderHover",
|
||||
"colorPrimaryHover",
|
||||
"colorPrimaryText",
|
||||
"colorPrimaryTextActive",
|
||||
"colorPrimaryTextHover",
|
||||
"colorSplit",
|
||||
"colorSuccess",
|
||||
"colorSuccessActive",
|
||||
"colorSuccessBg",
|
||||
"colorSuccessBgHover",
|
||||
"colorSuccessBorder",
|
||||
"colorSuccessBorderHover",
|
||||
"colorSuccessHover",
|
||||
"colorSuccessText",
|
||||
"colorSuccessTextActive",
|
||||
"colorSuccessTextHover",
|
||||
"colorText",
|
||||
"colorTextBase",
|
||||
"colorTextDescription",
|
||||
"colorTextDisabled",
|
||||
"colorTextHeading",
|
||||
"colorTextLabel",
|
||||
"colorTextLightSolid",
|
||||
"colorTextPlaceholder",
|
||||
"colorTextQuaternary",
|
||||
"colorTextSecondary",
|
||||
"colorTextTertiary",
|
||||
"colorWarning",
|
||||
"colorWarningActive",
|
||||
"colorWarningBg",
|
||||
"colorWarningBgHover",
|
||||
"colorWarningBorder",
|
||||
"colorWarningBorderHover",
|
||||
"colorWarningHover",
|
||||
"colorWarningOutline",
|
||||
"colorWarningText",
|
||||
"colorWarningTextActive",
|
||||
"colorWarningTextHover",
|
||||
"colorWhite",
|
||||
"controlHeight",
|
||||
"controlHeightLG",
|
||||
"controlHeightSM",
|
||||
"controlHeightXS",
|
||||
"controlInteractiveSize",
|
||||
"controlItemBgActive",
|
||||
"controlItemBgActiveDisabled",
|
||||
"controlItemBgActiveHover",
|
||||
"controlItemBgHover",
|
||||
"controlOutline",
|
||||
"controlOutlineWidth",
|
||||
"controlPaddingHorizontal",
|
||||
"controlPaddingHorizontalSM",
|
||||
"controlTmpOutline",
|
||||
"fontFamily",
|
||||
"fontFamilyCode",
|
||||
"fontHeight",
|
||||
"fontHeightLG",
|
||||
"fontHeightSM",
|
||||
"fontSize",
|
||||
"fontSizeHeading1",
|
||||
"fontSizeHeading2",
|
||||
"fontSizeHeading3",
|
||||
"fontSizeHeading4",
|
||||
"fontSizeHeading5",
|
||||
"fontSizeIcon",
|
||||
"fontSizeLG",
|
||||
"fontSizeSM",
|
||||
"fontSizeXL",
|
||||
"fontWeightStrong",
|
||||
"lineHeight",
|
||||
"lineHeightHeading1",
|
||||
"lineHeightHeading2",
|
||||
"lineHeightHeading3",
|
||||
"lineHeightHeading4",
|
||||
"lineHeightHeading5",
|
||||
"lineHeightLG",
|
||||
"lineHeightSM",
|
||||
"lineType",
|
||||
"lineWidth",
|
||||
"lineWidthBold",
|
||||
"lineWidthFocus",
|
||||
"linkDecoration",
|
||||
"linkFocusDecoration",
|
||||
"linkHoverDecoration",
|
||||
"margin",
|
||||
"marginLG",
|
||||
"marginMD",
|
||||
"marginSM",
|
||||
"marginXL",
|
||||
"marginXS",
|
||||
"marginXXL",
|
||||
"marginXXS",
|
||||
"motion",
|
||||
"motionBase",
|
||||
"motionDurationFast",
|
||||
"motionDurationMid",
|
||||
"motionDurationSlow",
|
||||
"motionEaseInBack",
|
||||
"motionEaseInOut",
|
||||
"motionEaseInOutCirc",
|
||||
"motionEaseInQuint",
|
||||
"motionEaseOut",
|
||||
"motionEaseOutBack",
|
||||
"motionEaseOutCirc",
|
||||
"motionEaseOutQuint",
|
||||
"motionUnit",
|
||||
"opacityImage",
|
||||
"opacityLoading",
|
||||
"padding",
|
||||
"paddingContentHorizontal",
|
||||
"paddingContentHorizontalLG",
|
||||
"paddingContentHorizontalSM",
|
||||
"paddingContentVertical",
|
||||
"paddingContentVerticalLG",
|
||||
"paddingContentVerticalSM",
|
||||
"paddingLG",
|
||||
"paddingMD",
|
||||
"paddingSM",
|
||||
"paddingXL",
|
||||
"paddingXS",
|
||||
"paddingXXS",
|
||||
"screenLG",
|
||||
"screenLGMax",
|
||||
"screenLGMin",
|
||||
"screenMD",
|
||||
"screenMDMax",
|
||||
"screenMDMin",
|
||||
"screenSM",
|
||||
"screenSMMax",
|
||||
"screenSMMin",
|
||||
"screenXL",
|
||||
"screenXLMax",
|
||||
"screenXLMin",
|
||||
"screenXS",
|
||||
"screenXSMax",
|
||||
"screenXSMin",
|
||||
"screenXXL",
|
||||
"screenXXLMin",
|
||||
"size",
|
||||
"sizeLG",
|
||||
"sizeMD",
|
||||
"sizeMS",
|
||||
"sizePopupArrow",
|
||||
"sizeSM",
|
||||
"sizeStep",
|
||||
"sizeUnit",
|
||||
"sizeXL",
|
||||
"sizeXS",
|
||||
"sizeXXL",
|
||||
"sizeXXS",
|
||||
"wireframe",
|
||||
"zIndexBase",
|
||||
"zIndexPopupBase",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`computed dark-mode token values match snapshot 1`] = `
|
||||
{
|
||||
"borderRadius": 6,
|
||||
"borderRadiusLG": 8,
|
||||
"borderRadiusOuter": 4,
|
||||
"borderRadiusSM": 4,
|
||||
"borderRadiusXS": 2,
|
||||
"boxShadow": "
|
||||
0 6px 16px 0 rgba(255,255,255,0.016),
|
||||
0 3px 6px -4px rgba(255,255,255,0.024),
|
||||
0 9px 28px 8px rgba(255,255,255,0.010000000000000002)
|
||||
",
|
||||
"boxShadowDrawerLeft": "
|
||||
6px 0 16px 0 rgba(255,255,255,0.016),
|
||||
3px 0 6px -4px rgba(255,255,255,0.024),
|
||||
9px 0 28px 8px rgba(255,255,255,0.010000000000000002)
|
||||
",
|
||||
"boxShadowDrawerRight": "
|
||||
-6px 0 16px 0 rgba(255,255,255,0.016),
|
||||
-3px 0 6px -4px rgba(255,255,255,0.024),
|
||||
-9px 0 28px 8px rgba(255,255,255,0.010000000000000002)
|
||||
",
|
||||
"boxShadowDrawerUp": "
|
||||
0 6px 16px 0 rgba(255,255,255,0.016),
|
||||
0 3px 6px -4px rgba(255,255,255,0.024),
|
||||
0 9px 28px 8px rgba(255,255,255,0.010000000000000002)
|
||||
",
|
||||
"boxShadowPopoverArrow": "2px 2px 5px rgba(255,255,255,0.010000000000000002)",
|
||||
"boxShadowSecondary": "
|
||||
0 6px 16px 0 rgba(255,255,255,0.016),
|
||||
0 3px 6px -4px rgba(255,255,255,0.024),
|
||||
0 9px 28px 8px rgba(255,255,255,0.010000000000000002)
|
||||
",
|
||||
"boxShadowTabsOverflowBottom": "inset 0 -10px 8px -8px rgba(255,255,255,0.016)",
|
||||
"boxShadowTabsOverflowLeft": "inset 10px 0 8px -8px rgba(255,255,255,0.016)",
|
||||
"boxShadowTabsOverflowRight": "inset -10px 0 8px -8px rgba(255,255,255,0.016)",
|
||||
"boxShadowTabsOverflowTop": "inset 0 10px 8px -8px rgba(255,255,255,0.016)",
|
||||
"boxShadowTertiary": "
|
||||
0 1px 2px 0 rgba(255,255,255,0.010000000000000002),
|
||||
0 1px 6px -1px rgba(255,255,255,0.006),
|
||||
0 2px 4px 0 rgba(255,255,255,0.006)
|
||||
",
|
||||
"colorBgBase": "#000",
|
||||
"colorBgBlur": "rgba(255,255,255,0.04)",
|
||||
"colorBgContainer": "#141414",
|
||||
"colorBgContainerDisabled": "rgba(255,255,255,0.08)",
|
||||
"colorBgElevated": "#1f1f1f",
|
||||
"colorBgLayout": "#000000",
|
||||
"colorBgMask": "rgba(0,0,0,0.45)",
|
||||
"colorBgSpotlight": "#424242",
|
||||
"colorBgTextActive": "rgba(255,255,255,0.18)",
|
||||
"colorBgTextHover": "rgba(255,255,255,0.12)",
|
||||
"colorBorder": "#424242",
|
||||
"colorBorderBg": "#141414",
|
||||
"colorBorderSecondary": "#303030",
|
||||
"colorError": "#e04355",
|
||||
"colorErrorActive": "#99333e",
|
||||
"colorErrorBg": "#271619",
|
||||
"colorErrorBgActive": "#512228",
|
||||
"colorErrorBgHover": "#3e1b20",
|
||||
"colorErrorBorder": "#512228",
|
||||
"colorErrorBorderHover": "#702931",
|
||||
"colorErrorHover": "#d7646e",
|
||||
"colorErrorOutline": "rgba(231,42,76,0.09)",
|
||||
"colorErrorText": "#c13c4b",
|
||||
"colorErrorTextActive": "#99333e",
|
||||
"colorErrorTextHover": "#d7646e",
|
||||
"colorFill": "rgba(255,255,255,0.18)",
|
||||
"colorFillAlter": "rgba(255,255,255,0.04)",
|
||||
"colorFillContent": "rgba(255,255,255,0.12)",
|
||||
"colorFillContentHover": "rgba(255,255,255,0.18)",
|
||||
"colorFillQuaternary": "rgba(255,255,255,0.04)",
|
||||
"colorFillSecondary": "rgba(255,255,255,0.12)",
|
||||
"colorFillTertiary": "rgba(255,255,255,0.08)",
|
||||
"colorHighlight": "#c13c4b",
|
||||
"colorIcon": "rgba(255,255,255,0.45)",
|
||||
"colorIconHover": "rgba(255,255,255,0.85)",
|
||||
"colorInfo": "#66bcfe",
|
||||
"colorInfoActive": "#4981ac",
|
||||
"colorInfoBg": "#19222c",
|
||||
"colorInfoBgHover": "#223545",
|
||||
"colorInfoBorder": "#2d465a",
|
||||
"colorInfoBorderHover": "#39607d",
|
||||
"colorInfoHover": "#39607d",
|
||||
"colorInfoText": "#5aa3db",
|
||||
"colorInfoTextActive": "#4981ac",
|
||||
"colorInfoTextHover": "#83bfe8",
|
||||
"colorLink": "#2893B3",
|
||||
"colorLinkActive": "#21677b",
|
||||
"colorLinkHover": "#1d4d5c",
|
||||
"colorPrimary": "#2893B3",
|
||||
"colorPrimaryActive": "#21677b",
|
||||
"colorPrimaryBg": "#1a3a44",
|
||||
"colorPrimaryBgHover": "#1d4d5c",
|
||||
"colorPrimaryBorder": "#1a3a44",
|
||||
"colorPrimaryBorderHover": "#1d4d5c",
|
||||
"colorPrimaryHover": "#4499ae",
|
||||
"colorPrimaryText": "#25809b",
|
||||
"colorPrimaryTextActive": "#21677b",
|
||||
"colorPrimaryTextHover": "#4499ae",
|
||||
"colorSplit": "rgba(253,253,253,0.12)",
|
||||
"colorSuccess": "#5ac189",
|
||||
"colorSuccessActive": "#428460",
|
||||
"colorSuccessBg": "#17231d",
|
||||
"colorSuccessBgHover": "#1f362a",
|
||||
"colorSuccessBorder": "#294837",
|
||||
"colorSuccessBorderHover": "#346249",
|
||||
"colorSuccessHover": "#346249",
|
||||
"colorSuccessText": "#50a777",
|
||||
"colorSuccessTextActive": "#428460",
|
||||
"colorSuccessTextHover": "#77bc94",
|
||||
"colorText": "rgba(255,255,255,0.85)",
|
||||
"colorTextBase": "#fff",
|
||||
"colorTextDescription": "rgba(255,255,255,0.45)",
|
||||
"colorTextDisabled": "rgba(255,255,255,0.25)",
|
||||
"colorTextHeading": "rgba(255,255,255,0.85)",
|
||||
"colorTextLabel": "rgba(255,255,255,0.65)",
|
||||
"colorTextLightSolid": "#fff",
|
||||
"colorTextPlaceholder": "rgba(255,255,255,0.25)",
|
||||
"colorTextQuaternary": "rgba(255,255,255,0.25)",
|
||||
"colorTextSecondary": "rgba(255,255,255,0.65)",
|
||||
"colorTextTertiary": "rgba(255,255,255,0.45)",
|
||||
"colorWarning": "#fcc700",
|
||||
"colorWarningActive": "#ab8807",
|
||||
"colorWarningBg": "#2b2411",
|
||||
"colorWarningBgHover": "#45370f",
|
||||
"colorWarningBorder": "#5a4a0e",
|
||||
"colorWarningBorderHover": "#7c650b",
|
||||
"colorWarningHover": "#7c650b",
|
||||
"colorWarningOutline": "rgba(173,127,0,0.15)",
|
||||
"colorWarningText": "#d9ac03",
|
||||
"colorWarningTextActive": "#ab8807",
|
||||
"colorWarningTextHover": "#e8c427",
|
||||
"colorWhite": "#fff",
|
||||
"controlHeight": 32,
|
||||
"controlHeightLG": 40,
|
||||
"controlHeightSM": 24,
|
||||
"controlHeightXS": 16,
|
||||
"controlInteractiveSize": 16,
|
||||
"controlItemBgActive": "#1a3a44",
|
||||
"controlItemBgActiveDisabled": "rgba(255,255,255,0.18)",
|
||||
"controlItemBgActiveHover": "#1d4d5c",
|
||||
"controlItemBgHover": "rgba(255,255,255,0.08)",
|
||||
"controlOutline": "rgba(49,201,249,0.21)",
|
||||
"controlOutlineWidth": 2,
|
||||
"controlPaddingHorizontal": 12,
|
||||
"controlPaddingHorizontalSM": 8,
|
||||
"controlTmpOutline": "rgba(255,255,255,0.04)",
|
||||
"fontFamily": "'Inter', Helvetica, Arial",
|
||||
"fontFamilyCode": "'IBM Plex Mono', 'Courier New', monospace",
|
||||
"fontHeight": 22,
|
||||
"fontHeightLG": 24,
|
||||
"fontHeightSM": 20,
|
||||
"fontSize": 14,
|
||||
"fontSizeHeading1": 38,
|
||||
"fontSizeHeading2": 30,
|
||||
"fontSizeHeading3": 24,
|
||||
"fontSizeHeading4": 20,
|
||||
"fontSizeHeading5": 16,
|
||||
"fontSizeIcon": 12,
|
||||
"fontSizeLG": 16,
|
||||
"fontSizeSM": 12,
|
||||
"fontSizeXL": 20,
|
||||
"fontWeightStrong": 600,
|
||||
"lineHeight": 1.5714285714285714,
|
||||
"lineHeightHeading1": 1.2105263157894737,
|
||||
"lineHeightHeading2": 1.2666666666666666,
|
||||
"lineHeightHeading3": 1.3333333333333333,
|
||||
"lineHeightHeading4": 1.4,
|
||||
"lineHeightHeading5": 1.5,
|
||||
"lineHeightLG": 1.5,
|
||||
"lineHeightSM": 1.6666666666666667,
|
||||
"lineType": "solid",
|
||||
"lineWidth": 1,
|
||||
"lineWidthBold": 2,
|
||||
"lineWidthFocus": 3,
|
||||
"linkDecoration": "none",
|
||||
"linkFocusDecoration": "none",
|
||||
"linkHoverDecoration": "none",
|
||||
"margin": 16,
|
||||
"marginLG": 24,
|
||||
"marginMD": 20,
|
||||
"marginSM": 12,
|
||||
"marginXL": 32,
|
||||
"marginXS": 8,
|
||||
"marginXXL": 48,
|
||||
"marginXXS": 4,
|
||||
"motion": true,
|
||||
"motionBase": 0,
|
||||
"motionDurationFast": "0.1s",
|
||||
"motionDurationMid": "0.2s",
|
||||
"motionDurationSlow": "0.3s",
|
||||
"motionEaseInBack": "cubic-bezier(0.71, -0.46, 0.88, 0.6)",
|
||||
"motionEaseInOut": "cubic-bezier(0.645, 0.045, 0.355, 1)",
|
||||
"motionEaseInOutCirc": "cubic-bezier(0.78, 0.14, 0.15, 0.86)",
|
||||
"motionEaseInQuint": "cubic-bezier(0.755, 0.05, 0.855, 0.06)",
|
||||
"motionEaseOut": "cubic-bezier(0.215, 0.61, 0.355, 1)",
|
||||
"motionEaseOutBack": "cubic-bezier(0.12, 0.4, 0.29, 1.46)",
|
||||
"motionEaseOutCirc": "cubic-bezier(0.08, 0.82, 0.17, 1)",
|
||||
"motionEaseOutQuint": "cubic-bezier(0.23, 1, 0.32, 1)",
|
||||
"motionUnit": 0.1,
|
||||
"opacityImage": 1,
|
||||
"opacityLoading": 0.65,
|
||||
"padding": 16,
|
||||
"paddingContentHorizontal": 16,
|
||||
"paddingContentHorizontalLG": 24,
|
||||
"paddingContentHorizontalSM": 16,
|
||||
"paddingContentVertical": 12,
|
||||
"paddingContentVerticalLG": 16,
|
||||
"paddingContentVerticalSM": 8,
|
||||
"paddingLG": 24,
|
||||
"paddingMD": 20,
|
||||
"paddingSM": 12,
|
||||
"paddingXL": 32,
|
||||
"paddingXS": 8,
|
||||
"paddingXXS": 4,
|
||||
"screenLG": 992,
|
||||
"screenLGMax": 1199,
|
||||
"screenLGMin": 992,
|
||||
"screenMD": 768,
|
||||
"screenMDMax": 991,
|
||||
"screenMDMin": 768,
|
||||
"screenSM": 576,
|
||||
"screenSMMax": 767,
|
||||
"screenSMMin": 576,
|
||||
"screenXL": 1200,
|
||||
"screenXLMax": 1599,
|
||||
"screenXLMin": 1200,
|
||||
"screenXS": 480,
|
||||
"screenXSMax": 575,
|
||||
"screenXSMin": 480,
|
||||
"screenXXL": 1600,
|
||||
"screenXXLMin": 1600,
|
||||
"size": 16,
|
||||
"sizeLG": 24,
|
||||
"sizeMD": 20,
|
||||
"sizeMS": 16,
|
||||
"sizePopupArrow": 16,
|
||||
"sizeSM": 12,
|
||||
"sizeStep": 4,
|
||||
"sizeUnit": 4,
|
||||
"sizeXL": 32,
|
||||
"sizeXS": 8,
|
||||
"sizeXXL": 48,
|
||||
"sizeXXS": 4,
|
||||
"wireframe": false,
|
||||
"zIndexBase": 0,
|
||||
"zIndexPopupBase": 1000,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`computed light-mode token values match snapshot 1`] = `
|
||||
{
|
||||
"borderRadius": 6,
|
||||
"borderRadiusLG": 8,
|
||||
"borderRadiusOuter": 4,
|
||||
"borderRadiusSM": 4,
|
||||
"borderRadiusXS": 2,
|
||||
"boxShadow": "
|
||||
0 6px 16px 0 rgba(0,0,0,0.08),
|
||||
0 3px 6px -4px rgba(0,0,0,0.12),
|
||||
0 9px 28px 8px rgba(0,0,0,0.05)
|
||||
",
|
||||
"boxShadowDrawerLeft": "
|
||||
6px 0 16px 0 rgba(0,0,0,0.08),
|
||||
3px 0 6px -4px rgba(0,0,0,0.12),
|
||||
9px 0 28px 8px rgba(0,0,0,0.05)
|
||||
",
|
||||
"boxShadowDrawerRight": "
|
||||
-6px 0 16px 0 rgba(0,0,0,0.08),
|
||||
-3px 0 6px -4px rgba(0,0,0,0.12),
|
||||
-9px 0 28px 8px rgba(0,0,0,0.05)
|
||||
",
|
||||
"boxShadowDrawerUp": "
|
||||
0 6px 16px 0 rgba(0,0,0,0.08),
|
||||
0 3px 6px -4px rgba(0,0,0,0.12),
|
||||
0 9px 28px 8px rgba(0,0,0,0.05)
|
||||
",
|
||||
"boxShadowPopoverArrow": "2px 2px 5px rgba(0,0,0,0.05)",
|
||||
"boxShadowSecondary": "
|
||||
0 6px 16px 0 rgba(0,0,0,0.08),
|
||||
0 3px 6px -4px rgba(0,0,0,0.12),
|
||||
0 9px 28px 8px rgba(0,0,0,0.05)
|
||||
",
|
||||
"boxShadowTabsOverflowBottom": "inset 0 -10px 8px -8px rgba(0,0,0,0.08)",
|
||||
"boxShadowTabsOverflowLeft": "inset 10px 0 8px -8px rgba(0,0,0,0.08)",
|
||||
"boxShadowTabsOverflowRight": "inset -10px 0 8px -8px rgba(0,0,0,0.08)",
|
||||
"boxShadowTabsOverflowTop": "inset 0 10px 8px -8px rgba(0,0,0,0.08)",
|
||||
"boxShadowTertiary": "
|
||||
0 1px 2px 0 rgba(0,0,0,0.05),
|
||||
0 1px 6px -1px rgba(0,0,0,0.03),
|
||||
0 2px 4px 0 rgba(0,0,0,0.03)
|
||||
",
|
||||
"colorBgBase": "#fff",
|
||||
"colorBgBlur": "transparent",
|
||||
"colorBgContainer": "#ffffff",
|
||||
"colorBgContainerDisabled": "rgba(0,0,0,0.04)",
|
||||
"colorBgElevated": "#ffffff",
|
||||
"colorBgLayout": "#f5f5f5",
|
||||
"colorBgMask": "rgba(0,0,0,0.45)",
|
||||
"colorBgSpotlight": "rgba(0,0,0,0.85)",
|
||||
"colorBgTextActive": "rgba(0,0,0,0.15)",
|
||||
"colorBgTextHover": "rgba(0,0,0,0.06)",
|
||||
"colorBorder": "#d9d9d9",
|
||||
"colorBorderBg": "#ffffff",
|
||||
"colorBorderSecondary": "#f0f0f0",
|
||||
"colorError": "#e04355",
|
||||
"colorErrorActive": "#ba2f43",
|
||||
"colorErrorBg": "#fff0f0",
|
||||
"colorErrorBgActive": "#ffc7c8",
|
||||
"colorErrorBgHover": "#fff0f0",
|
||||
"colorErrorBorder": "#ffc7c8",
|
||||
"colorErrorBorderHover": "#fa9ba0",
|
||||
"colorErrorHover": "#ed6d78",
|
||||
"colorErrorOutline": "rgba(255,5,5,0.06)",
|
||||
"colorErrorText": "#e04355",
|
||||
"colorErrorTextActive": "#ba2f43",
|
||||
"colorErrorTextHover": "#ed6d78",
|
||||
"colorFill": "rgba(0,0,0,0.15)",
|
||||
"colorFillAlter": "rgba(0,0,0,0.02)",
|
||||
"colorFillContent": "rgba(0,0,0,0.06)",
|
||||
"colorFillContentHover": "rgba(0,0,0,0.15)",
|
||||
"colorFillQuaternary": "rgba(0,0,0,0.02)",
|
||||
"colorFillSecondary": "rgba(0,0,0,0.06)",
|
||||
"colorFillTertiary": "rgba(0,0,0,0.04)",
|
||||
"colorHighlight": "#e04355",
|
||||
"colorIcon": "rgba(0,0,0,0.45)",
|
||||
"colorIconHover": "rgba(0,0,0,0.88)",
|
||||
"colorInfo": "#66bcfe",
|
||||
"colorInfoActive": "#4c97d9",
|
||||
"colorInfoBg": "#f0fbff",
|
||||
"colorInfoBgHover": "#f0faff",
|
||||
"colorInfoBorder": "#e0f5ff",
|
||||
"colorInfoBorderHover": "#b8e5ff",
|
||||
"colorInfoHover": "#b8e5ff",
|
||||
"colorInfoText": "#66bcfe",
|
||||
"colorInfoTextActive": "#4c97d9",
|
||||
"colorInfoTextHover": "#8fd2ff",
|
||||
"colorLink": "#2893B3",
|
||||
"colorLinkActive": "#186d8c",
|
||||
"colorLinkHover": "#6ebccc",
|
||||
"colorPrimary": "#2893B3",
|
||||
"colorPrimaryActive": "#186d8c",
|
||||
"colorPrimaryBg": "#e4f1f2",
|
||||
"colorPrimaryBgHover": "#c5e2e6",
|
||||
"colorPrimaryBorder": "#98d0d9",
|
||||
"colorPrimaryBorderHover": "#6ebccc",
|
||||
"colorPrimaryHover": "#49a8bf",
|
||||
"colorPrimaryText": "#2893b3",
|
||||
"colorPrimaryTextActive": "#186d8c",
|
||||
"colorPrimaryTextHover": "#49a8bf",
|
||||
"colorSplit": "rgba(5,5,5,0.06)",
|
||||
"colorSuccess": "#5ac189",
|
||||
"colorSuccessActive": "#419c6d",
|
||||
"colorSuccessBg": "#f0fff4",
|
||||
"colorSuccessBgHover": "#e6f5eb",
|
||||
"colorSuccessBorder": "#dae8df",
|
||||
"colorSuccessBorderHover": "#addbbf",
|
||||
"colorSuccessHover": "#addbbf",
|
||||
"colorSuccessText": "#5ac189",
|
||||
"colorSuccessTextActive": "#419c6d",
|
||||
"colorSuccessTextHover": "#82cfa2",
|
||||
"colorText": "rgba(0,0,0,0.88)",
|
||||
"colorTextBase": "#000",
|
||||
"colorTextDescription": "rgba(0,0,0,0.45)",
|
||||
"colorTextDisabled": "rgba(0,0,0,0.25)",
|
||||
"colorTextHeading": "rgba(0,0,0,0.88)",
|
||||
"colorTextLabel": "rgba(0,0,0,0.65)",
|
||||
"colorTextLightSolid": "#fff",
|
||||
"colorTextPlaceholder": "rgba(0,0,0,0.25)",
|
||||
"colorTextQuaternary": "rgba(0,0,0,0.25)",
|
||||
"colorTextSecondary": "rgba(0,0,0,0.65)",
|
||||
"colorTextTertiary": "rgba(0,0,0,0.45)",
|
||||
"colorWarning": "#fcc700",
|
||||
"colorWarningActive": "#d6a100",
|
||||
"colorWarningBg": "#fffee6",
|
||||
"colorWarningBgHover": "#fff7a3",
|
||||
"colorWarningBorder": "#fff07a",
|
||||
"colorWarningBorderHover": "#ffe552",
|
||||
"colorWarningHover": "#ffe552",
|
||||
"colorWarningOutline": "rgba(255,245,5,0.1)",
|
||||
"colorWarningText": "#fcc700",
|
||||
"colorWarningTextActive": "#d6a100",
|
||||
"colorWarningTextHover": "#ffd829",
|
||||
"colorWhite": "#fff",
|
||||
"controlHeight": 32,
|
||||
"controlHeightLG": 40,
|
||||
"controlHeightSM": 24,
|
||||
"controlHeightXS": 16,
|
||||
"controlInteractiveSize": 16,
|
||||
"controlItemBgActive": "#e4f1f2",
|
||||
"controlItemBgActiveDisabled": "rgba(0,0,0,0.15)",
|
||||
"controlItemBgActiveHover": "#c5e2e6",
|
||||
"controlItemBgHover": "rgba(0,0,0,0.04)",
|
||||
"controlOutline": "rgba(10,128,137,0.11)",
|
||||
"controlOutlineWidth": 2,
|
||||
"controlPaddingHorizontal": 12,
|
||||
"controlPaddingHorizontalSM": 8,
|
||||
"controlTmpOutline": "rgba(0,0,0,0.02)",
|
||||
"fontFamily": "'Inter', Helvetica, Arial",
|
||||
"fontFamilyCode": "'IBM Plex Mono', 'Courier New', monospace",
|
||||
"fontHeight": 22,
|
||||
"fontHeightLG": 24,
|
||||
"fontHeightSM": 20,
|
||||
"fontSize": 14,
|
||||
"fontSizeHeading1": 38,
|
||||
"fontSizeHeading2": 30,
|
||||
"fontSizeHeading3": 24,
|
||||
"fontSizeHeading4": 20,
|
||||
"fontSizeHeading5": 16,
|
||||
"fontSizeIcon": 12,
|
||||
"fontSizeLG": 16,
|
||||
"fontSizeSM": 12,
|
||||
"fontSizeXL": 20,
|
||||
"fontWeightStrong": 600,
|
||||
"lineHeight": 1.5714285714285714,
|
||||
"lineHeightHeading1": 1.2105263157894737,
|
||||
"lineHeightHeading2": 1.2666666666666666,
|
||||
"lineHeightHeading3": 1.3333333333333333,
|
||||
"lineHeightHeading4": 1.4,
|
||||
"lineHeightHeading5": 1.5,
|
||||
"lineHeightLG": 1.5,
|
||||
"lineHeightSM": 1.6666666666666667,
|
||||
"lineType": "solid",
|
||||
"lineWidth": 1,
|
||||
"lineWidthBold": 2,
|
||||
"lineWidthFocus": 3,
|
||||
"linkDecoration": "none",
|
||||
"linkFocusDecoration": "none",
|
||||
"linkHoverDecoration": "none",
|
||||
"margin": 16,
|
||||
"marginLG": 24,
|
||||
"marginMD": 20,
|
||||
"marginSM": 12,
|
||||
"marginXL": 32,
|
||||
"marginXS": 8,
|
||||
"marginXXL": 48,
|
||||
"marginXXS": 4,
|
||||
"motion": true,
|
||||
"motionBase": 0,
|
||||
"motionDurationFast": "0.1s",
|
||||
"motionDurationMid": "0.2s",
|
||||
"motionDurationSlow": "0.3s",
|
||||
"motionEaseInBack": "cubic-bezier(0.71, -0.46, 0.88, 0.6)",
|
||||
"motionEaseInOut": "cubic-bezier(0.645, 0.045, 0.355, 1)",
|
||||
"motionEaseInOutCirc": "cubic-bezier(0.78, 0.14, 0.15, 0.86)",
|
||||
"motionEaseInQuint": "cubic-bezier(0.755, 0.05, 0.855, 0.06)",
|
||||
"motionEaseOut": "cubic-bezier(0.215, 0.61, 0.355, 1)",
|
||||
"motionEaseOutBack": "cubic-bezier(0.12, 0.4, 0.29, 1.46)",
|
||||
"motionEaseOutCirc": "cubic-bezier(0.08, 0.82, 0.17, 1)",
|
||||
"motionEaseOutQuint": "cubic-bezier(0.23, 1, 0.32, 1)",
|
||||
"motionUnit": 0.1,
|
||||
"opacityImage": 1,
|
||||
"opacityLoading": 0.65,
|
||||
"padding": 16,
|
||||
"paddingContentHorizontal": 16,
|
||||
"paddingContentHorizontalLG": 24,
|
||||
"paddingContentHorizontalSM": 16,
|
||||
"paddingContentVertical": 12,
|
||||
"paddingContentVerticalLG": 16,
|
||||
"paddingContentVerticalSM": 8,
|
||||
"paddingLG": 24,
|
||||
"paddingMD": 20,
|
||||
"paddingSM": 12,
|
||||
"paddingXL": 32,
|
||||
"paddingXS": 8,
|
||||
"paddingXXS": 4,
|
||||
"screenLG": 992,
|
||||
"screenLGMax": 1199,
|
||||
"screenLGMin": 992,
|
||||
"screenMD": 768,
|
||||
"screenMDMax": 991,
|
||||
"screenMDMin": 768,
|
||||
"screenSM": 576,
|
||||
"screenSMMax": 767,
|
||||
"screenSMMin": 576,
|
||||
"screenXL": 1200,
|
||||
"screenXLMax": 1599,
|
||||
"screenXLMin": 1200,
|
||||
"screenXS": 480,
|
||||
"screenXSMax": 575,
|
||||
"screenXSMin": 480,
|
||||
"screenXXL": 1600,
|
||||
"screenXXLMin": 1600,
|
||||
"size": 16,
|
||||
"sizeLG": 24,
|
||||
"sizeMD": 20,
|
||||
"sizeMS": 16,
|
||||
"sizePopupArrow": 16,
|
||||
"sizeSM": 12,
|
||||
"sizeStep": 4,
|
||||
"sizeUnit": 4,
|
||||
"sizeXL": 32,
|
||||
"sizeXS": 8,
|
||||
"sizeXXL": 48,
|
||||
"sizeXXS": 4,
|
||||
"wireframe": false,
|
||||
"zIndexBase": 0,
|
||||
"zIndexPopupBase": 1000,
|
||||
}
|
||||
`;
|
||||
@@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { theme as antdThemeImport, type MappingAlgorithm } from 'antd';
|
||||
import { theme as antdThemeImport } from 'antd';
|
||||
import {
|
||||
type AntdThemeConfig,
|
||||
type AnyThemeConfig,
|
||||
@@ -48,8 +48,8 @@ export function isSerializableConfig(
|
||||
export function deserializeThemeConfig(
|
||||
config: SerializableThemeConfig,
|
||||
): AntdThemeConfig {
|
||||
const { algorithm, cssVar, ...rest } = config;
|
||||
const algorithmMap: Record<string, MappingAlgorithm> = {
|
||||
const { algorithm, ...rest } = config;
|
||||
const algorithmMap: Record<string, any> = {
|
||||
default: antdThemeImport.defaultAlgorithm,
|
||||
dark: antdThemeImport.darkAlgorithm,
|
||||
compact: antdThemeImport.compactAlgorithm,
|
||||
@@ -74,17 +74,9 @@ export function deserializeThemeConfig(
|
||||
resolvedAlgorithm = antdThemeImport.defaultAlgorithm;
|
||||
}
|
||||
|
||||
// Ant Design v6 dropped `boolean` from ThemeConfig['cssVar'] (it is now
|
||||
// object-only, and CSS variables are enabled by default). Superset keeps a
|
||||
// boolean-friendly serializable API, so coerce at the antd boundary:
|
||||
// `true` -> `{}` (defaults), `false`/undefined -> omit (antd default).
|
||||
const normalizedCssVar =
|
||||
typeof cssVar === 'boolean' ? (cssVar ? {} : undefined) : cssVar;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
algorithm: resolvedAlgorithm,
|
||||
...(normalizedCssVar !== undefined ? { cssVar: normalizedCssVar } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"lodash-es": "^4.18.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ant-design/icons": "^5.6.1 || ^6.0.0",
|
||||
"@ant-design/icons": "^5.6.1",
|
||||
"@emotion/react": "^11.4.1",
|
||||
"@superset-ui/core": "*",
|
||||
"@testing-library/dom": "^9.3.4",
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@visx/responsive": "^4.0.0",
|
||||
"ace-builds": "^1.44.0",
|
||||
"ag-grid-community": "36.0.0",
|
||||
"ag-grid-react": "36.0.0",
|
||||
"ag-grid-community": "35.3.1",
|
||||
"ag-grid-react": "35.3.1",
|
||||
"brace": "^0.11.1",
|
||||
"classnames": "^2.5.1",
|
||||
"core-js": "^3.49.0",
|
||||
@@ -54,7 +54,7 @@
|
||||
"react-ace": "^14.0.1",
|
||||
"react-draggable": "^4.7.0",
|
||||
"react-error-boundary": "^6.1.2",
|
||||
"react-js-cron": "^6.0.2",
|
||||
"react-js-cron": "^5.2.0",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-resize-detector": "^7.1.2",
|
||||
"react-syntax-highlighter": "^16.1.1",
|
||||
@@ -100,7 +100,7 @@
|
||||
"@types/react-loadable": "*",
|
||||
"@types/react-window": "^1.8.8",
|
||||
"@types/tinycolor2": "*",
|
||||
"antd": "^6.0.0",
|
||||
"antd": "^5.26.0",
|
||||
"nanoid": "^5.0.9",
|
||||
"react": "^18.3.0",
|
||||
"react-dom": "^18.3.0",
|
||||
|
||||
@@ -92,7 +92,7 @@ const MatrixNoDataComponent = () => {
|
||||
* Individual grid cell component - memoized to prevent unnecessary re-renders
|
||||
*/
|
||||
const MatrixifyGridCell = memo(
|
||||
({ cell, hooks }: MatrixifyGridCellProps) => {
|
||||
({ cell, rowHeight, datasource, hooks }: MatrixifyGridCellProps) => {
|
||||
// Use computed title from template (will be empty string if no template)
|
||||
const cellLabel = cell.title || '';
|
||||
|
||||
|
||||
@@ -118,6 +118,7 @@ interface MatrixifyGridRendererProps {
|
||||
function MatrixifyGridRenderer({
|
||||
formData,
|
||||
datasource,
|
||||
width,
|
||||
height,
|
||||
hooks,
|
||||
}: MatrixifyGridRendererProps) {
|
||||
@@ -248,7 +249,7 @@ function MatrixifyGridRenderer({
|
||||
{/* Row cells for this column group */}
|
||||
{row
|
||||
.slice(colGroup.startIdx, colGroup.endIdx)
|
||||
.map(cell =>
|
||||
.map((cell, colIdx) =>
|
||||
cell ? (
|
||||
<MatrixifyGridCell
|
||||
key={cell.id}
|
||||
|
||||
@@ -444,6 +444,7 @@ export function AsyncAceEditor(
|
||||
/* Adjust tooltip styles */
|
||||
.ace_tooltip {
|
||||
margin-left: ${token.margin}px;
|
||||
padding: ${token.sizeUnit * 2}px;
|
||||
background-color: ${token.colorBgElevated} !important;
|
||||
color: ${token.colorText} !important;
|
||||
border: 1px solid ${token.colorBorderSecondary};
|
||||
|
||||
@@ -82,10 +82,8 @@ test('collapses on click', async () => {
|
||||
|
||||
await userEvent.click(screen.getAllByRole('button')[0]);
|
||||
|
||||
// antd v6 moved the hidden state to the panel wrapper element
|
||||
// (ant-collapse-panel-hidden) instead of the content wrapper.
|
||||
expect(screen.getByText('Content 1').parentElement).toHaveClass(
|
||||
'ant-collapse-panel-hidden',
|
||||
expect(screen.getByText('Content 1').parentNode).toHaveClass(
|
||||
'ant-collapse-content-hidden',
|
||||
);
|
||||
expect(screen.queryByText('Content 2')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user