Skip to content

Filter collection-item tables with uncorrelated subqueries #123411

Filter collection-item tables with uncorrelated subqueries

Filter collection-item tables with uncorrelated subqueries #123411

Workflow file for this run

name: Run tests
on:
push:
branches:
- "master"
- "release-**"
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
permissions:
id-token: write
contents: read
actions: read
checks: write
pull-requests: write
security-events: write
jobs:
# `force-run` and `force-skip` are global overrides; `defer` means this
# job has no opinion and every downstream gate behaves as it always has.
#
# Only the lowest unmerged PR of a stack runs CI: it is the one whose base
# ref is the stack base. Every PR above it is force-skipped and gets tested
# once it reaches the bottom of the stack.
should-run:
name: Decide which jobs should run
runs-on: ${{ vars.SLIM_RUNNER_KEY }}
timeout-minutes: 5
outputs:
verdict: ${{ steps.decide.outputs.verdict }}
steps:
- name: Decide
id: decide
# Precedence matters for the conditions below.
env:
VERDICT: >-
${{ (github.ref_name == 'master' || startsWith(github.ref_name, 'release-x.')) && 'force-run'
|| contains(github.event.pull_request.labels.*.name, 'ci:run-all') && 'force-run'
|| contains(github.event.pull_request.labels.*.name, 'ci:skip') && 'force-skip'
|| (github.event.pull_request.stack != null && github.event.pull_request.stack.base.ref != github.event.pull_request.base.ref) && 'force-skip'
|| 'defer' }}
run: echo "verdict=$VERDICT" | tee -a "$GITHUB_OUTPUT"
files-changed:
needs: should-run
name: Detect changed files
if: ${{ needs.should-run.outputs.verdict == 'defer' }}
runs-on: ${{ vars.SLIM_RUNNER_KEY }}
timeout-minutes: 5
outputs:
e2e_all: ${{ steps.changes.outputs.e2e_all }}
e2e_specs: ${{ steps.changes.outputs.e2e_specs }}
e2e_infra: ${{ steps.changes.outputs.e2e_infra }}
backend_all: ${{ steps.changes.outputs.backend_all }}
build_scripts: ${{ steps.changes.outputs.build_scripts }}
embedder_plugin: ${{ steps.changes.outputs.embedder_plugin }}
frontend_all: ${{ steps.changes.outputs.frontend_all }}
frontend_sources: ${{ steps.changes.outputs.frontend_sources }}
frontend_unit_infra: ${{ steps.changes.outputs.frontend_unit_infra }}
frontend_loki_infra: ${{ steps.changes.outputs.frontend_loki_infra }}
frontend_loki_all: ${{ steps.changes.outputs.frontend_loki_all }}
shared_sources: ${{ steps.changes.outputs.shared_sources }}
documentation: ${{ steps.changes.outputs.documentation }}
embedding_documentation: ${{ steps.changes.outputs.embedding_documentation }}
embedding_sdk_components: ${{ steps.changes.outputs.embedding_sdk_components }}
embedding_sdk_host_sample_apps: ${{ steps.changes.outputs.embedding_sdk_host_sample_apps }}
embedding_sdk_ci: ${{ steps.changes.outputs.embedding_sdk_ci }}
custom_viz_all: ${{ steps.changes.outputs.custom_viz_all }}
ci_scripts: ${{ steps.changes.outputs.ci_scripts }}
project_backend_checks: ${{ steps.changes.outputs.project_backend_checks }}
project_migration_checks: ${{ steps.changes.outputs.project_migration_checks }}
project_ratchet_checks: ${{ steps.changes.outputs.project_ratchet_checks }}
# A ratchets-only change (the shrink automation PR) needs the ratchet check, not an uberjar.
no_source_code_changes: >-
${{ (steps.changes.outputs.documentation == 'true'
|| steps.changes.outputs.project_ratchet_checks == 'true')
&& steps.changes.outputs.backend_all == 'false'
&& steps.changes.outputs.frontend_all == 'false'
&& steps.changes.outputs.e2e_all == 'false' }}
all_changed_files: ${{ steps.changes.outputs.all_changed_files }}
e2e_all_files: ${{ steps.changes.outputs.e2e_all_files }}
e2e_specs_files: ${{ steps.changes.outputs.e2e_specs_files }}
frontend_sources_files: ${{ steps.changes.outputs.frontend_sources_files }}
backend_sources_files: ${{ steps.changes.outputs.backend_sources_files }}
steps:
- uses: actions/checkout@v7
- name: Test which files changed
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: changes
with:
token: ${{ github.token }}
# comma separated list of files
list-files: csv
filters: .github/file-paths.yaml
create-test-plan:
needs: [should-run, files-changed]
name: Create test plan
if: ${{ github.event_name == 'pull_request' && needs.should-run.outputs.verdict == 'defer' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
timeout-minutes: 10
outputs:
stats: ${{ steps.compute.outputs.stats }}
artifact-id: ${{ steps.compute.outputs.artifact-id }}
steps:
- uses: actions/checkout@v7
- name: Create test plan
id: compute
uses: ./.github/actions/create-test-plan
with:
changed-files: ${{ needs.files-changed.outputs.all_changed_files }}
fe-changed-files: ${{ needs.files-changed.outputs.frontend_sources_files }}
be-changed-files: ${{ needs.files-changed.outputs.backend_sources_files }}
unit-infra-touched: ${{ needs.files-changed.outputs.frontend_unit_infra }}
loki-infra-touched: ${{ needs.files-changed.outputs.frontend_loki_infra }}
e2e-infra-touched: ${{ needs.files-changed.outputs.e2e_infra }}
shared-sources-touched: ${{ needs.files-changed.outputs.shared_sources }}
upload-affected-tests-stats:
needs: create-test-plan
# Only land rows for PRs from the upstream repo so forks don't pollute the table.
if: |
!cancelled() &&
needs.create-test-plan.result == 'success' &&
github.event.pull_request.head.repo.full_name == 'metabase/metabase'
# Stats upload is best-effort — a failure here shouldn't fail the PR run.
continue-on-error: true
runs-on: ${{ vars.SLIM_RUNNER_KEY }}
timeout-minutes: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/prepare-node-bun
- name: Upload affected tests stats
env:
STATS_JSON: ${{ needs.create-test-plan.outputs.stats }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
ENG_STATS_URL: ${{ secrets.ENG_STATS_URL }}
API_KEY: ${{ secrets.ENG_STATS_API_KEY }}
run: bun .github/scripts/upload-affected-tests-stats.ts
uberjar:
needs: [should-run, files-changed]
if: |
!cancelled() && needs.should-run.outputs.verdict != 'force-skip' &&
(needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.outputs.no_source_code_changes != 'true')
uses: ./.github/workflows/uberjar.yml
secrets: inherit
containerize:
needs: [uberjar]
if: >-
!cancelled() &&
needs.uberjar.result == 'success' &&
(
(github.event_name == 'push' && github.ref_name == 'master') ||
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar'))
)
name: containerize (${{ matrix.edition }})
strategy:
matrix:
edition: ['ee', 'oss']
uses: ./.github/workflows/containerize-jar.yml
secrets: inherit
with:
build-args: |
GIT_COMMIT_SHA=${{ github.event.pull_request.head.sha || github.sha }}
commit: ${{ github.event.pull_request.head.sha || github.sha }}
edition: ${{ matrix.edition }}
release: false
# Compile CLJS in parallel with the uberjar and pass it to each e2e group.
# The compile is doesn't depend on MB_EDITION
e2e-cljs:
name: Compile CLJS for e2e
needs: [should-run, files-changed]
if: |
!cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' ||
(needs.files-changed.result == 'success' &&
needs.files-changed.outputs.e2e_all == 'true'))
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Compile CLJS
run: bun run build-pure:cljs
- name: Upload compiled CLJS
uses: actions/upload-artifact@v7
with:
name: e2e-cljs-${{ github.event.pull_request.head.sha || github.sha }}
path: target/cljs_dev
if-no-files-found: error
# Uploads fail when an artifact of this name already exists in the run
# replace it rather than fail on a re-run.
overwrite: true
static-viz-files-changed:
name: Check whether static-viz files changed
needs: should-run
# Its only consumer is the backend skip gate, which a force-run overrides.
if: ${{ needs.should-run.outputs.verdict == 'defer' }}
runs-on: ${{ vars.DEFAULT_RUNNER_KEY }}
timeout-minutes: 10
outputs:
static_viz: ${{ steps.static_viz.outputs.static_viz }}
steps:
- uses: actions/checkout@v7
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Build static-viz frontend
run: bun run build-static-viz
env:
MB_EDITION: ee
- name: Check for static viz changes
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: static_viz
with:
token: ${{ github.token }}
filters: .github/static-viz-sources.yaml
backend-tests:
if: |
!cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.result == 'success')
needs: [should-run, files-changed, static-viz-files-changed]
uses: ./.github/workflows/backend.yml
secrets: inherit
with:
skip: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.backend_all != 'true' &&
needs.static-viz-files-changed.outputs.static_viz != 'true' }}
force-run: ${{ needs.should-run.outputs.verdict == 'force-run' }}
run-project-backend-checks: ${{ needs.files-changed.outputs.project_backend_checks == 'true' }}
run-project-migration-checks: ${{ needs.files-changed.outputs.project_migration_checks == 'true' }}
run-project-ratchet-checks: ${{ needs.files-changed.outputs.project_ratchet_checks == 'true' }}
semantic-search-tests:
if: |
!cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.result == 'success')
needs: [should-run, files-changed]
uses: ./.github/workflows/semantic-search.yml
secrets: inherit
with:
skip: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.backend_all != 'true' }}
smoke-only: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
!contains(github.event.pull_request.labels.*.name, 'ci:run-semantic-search-tests')
}}
app-db-tests:
if: |
!cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.result == 'success')
needs: [should-run, files-changed]
uses: ./.github/workflows/app-db.yml
secrets: inherit
with:
skip: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.backend_all != 'true' }}
force-run: ${{ needs.should-run.outputs.verdict == 'force-run' }}
driver-tests:
if: |
!cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.result == 'success')
needs: [should-run, files-changed]
uses: ./.github/workflows/drivers.yml
secrets: inherit
with:
skip: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.backend_all != 'true' }}
force-run: ${{ needs.should-run.outputs.verdict == 'force-run' }}
frontend-tests:
needs: [should-run, files-changed, create-test-plan]
if: |
!cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.result == 'success')
uses: ./.github/workflows/frontend.yml
secrets: inherit
with:
skip: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.frontend_all != 'true' }}
# A skipped/failed planner supplies no artifact, so the suite runs in full.
test-plan-artifact-id: ${{ needs.create-test-plan.result == 'success' && needs.create-test-plan.outputs.artifact-id || '' }}
skip-lint: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.frontend_all != 'true' &&
needs.files-changed.outputs.e2e_all != 'true' }}
skip-custom-viz: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.custom_viz_all != 'true' }}
skip-ci-scripts: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.ci_scripts != 'true' }}
loki-tests:
needs: [should-run, files-changed, create-test-plan]
if: |
!cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.result == 'success')
uses: ./.github/workflows/loki.yml
with:
skip: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.frontend_loki_all != 'true' }}
# A skipped/failed planner supplies no artifact, so the suite runs in full.
test-plan-artifact-id: ${{ needs.create-test-plan.result == 'success' && needs.create-test-plan.outputs.artifact-id || '' }}
e2e-tests:
needs: [should-run, files-changed, uberjar, create-test-plan]
# Skip e2e tests when the uberjar build failed or was cancelled — the
# downstream tests can't fetch a missing artifact, and we don't want to
# mask the uberjar failure with a wave of misleading e2e errors. We still
# enter the workflow when uberjar is `skipped` (docs-only PRs), because
# the inner `skip` input handles that path and reports the required
# `e2e-tests-result` check as success. When the uberjar genuinely failed,
# this whole job is skipped, the inner required checks never report, and
# branch protection blocks the merge as pending.
if: |
always() && !cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' || needs.files-changed.result == 'success') &&
needs.uberjar.result != 'failure' &&
needs.uberjar.result != 'cancelled'
uses: ./.github/workflows/e2e-tests.yml
secrets: inherit
with:
skip: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.e2e_all != 'true' }}
# Only narrow specs on pull requests that haven't been forced to run everything.
# Push and merge-queue runs always use the full suite.
test-plan-artifact-id: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
github.event_name == 'pull_request' &&
needs.create-test-plan.result == 'success' &&
needs.create-test-plan.outputs.artifact-id || '' }}
embedding-sdk-package:
needs: [should-run, files-changed]
if: |
!cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.outputs.embedding_sdk_components == 'true' ||
needs.files-changed.outputs.frontend_sources == 'true' ||
needs.files-changed.outputs.embedding_documentation == 'true' ||
needs.files-changed.outputs.embedding_sdk_ci == 'true' ||
needs.files-changed.outputs.embedding_sdk_host_sample_apps == 'true')
uses: ./.github/workflows/embedding-sdk-package-build.yml
secrets: inherit
sdk-tests:
needs: [should-run, uberjar, embedding-sdk-package, files-changed]
if: always() && !cancelled()
uses: ./.github/workflows/embedding-sdk.yml
secrets: inherit
with:
cli-snippets-type-check: >-
${{ needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.outputs.frontend_sources == 'true' }}
docs-snippets-type-check: >-
${{ needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.outputs.embedding_documentation == 'true' }}
documentation-validation: >-
${{ needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.outputs.frontend_sources == 'true' }}
component-tests: >-
${{ needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.outputs.embedding_sdk_components == 'true' }}
host-sample-apps-tests: >-
${{ needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.outputs.embedding_sdk_host_sample_apps == 'true' }}
skip: >-
${{ needs.embedding-sdk-package.result != 'success' ||
needs.uberjar.result != 'success' }}
build-scripts-tests:
needs: [should-run, files-changed]
if: |
!cancelled() &&
(needs.should-run.outputs.verdict == 'force-run' ||
needs.files-changed.result == 'success')
uses: ./.github/workflows/build-scripts.yml
secrets: inherit
with:
skip-build-scripts: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.build_scripts != 'true' }}
skip-embedder-plugin: >-
${{ needs.should-run.outputs.verdict != 'force-run' &&
needs.files-changed.outputs.embedder_plugin != 'true' }}
bundle-size:
needs: [uberjar, files-changed]
if: |
!cancelled() &&
github.event_name == 'pull_request' &&
needs.uberjar.result == 'success' &&
needs.files-changed.outputs.frontend_sources == 'true'
uses: ./.github/workflows/bundle-size.yml
secrets: inherit