Compare commits

...

256 Commits

Author SHA1 Message Date
Uladzimir Havenchyk
39a68def7e cleanup sandboxing 2025-10-30 22:30:51 +03:00
Uladzimir Havenchyk
3da641ba00 fix typecheck 2025-10-29 16:15:09 +03:00
Uladzimir Havenchyk
91247c3be2 Merge remote-tracking branch 'origin/nmezzopera/test-pyodie' into test-python-be 2025-10-29 16:03:16 +03:00
Uladzimir Havenchyk
ed4f399a01 add a comment 2025-10-28 18:49:55 +03:00
Uladzimir Havenchyk
a291c967c7 improve sandboxing 2025-10-28 18:49:12 +03:00
Uladzimir Havenchyk
4f1dec3ce8 add a comment 2025-10-28 16:42:41 +03:00
Uladzimir Havenchyk
f6347c776d log python error 2025-10-28 16:42:25 +03:00
Uladzimir Havenchyk
ae3c2c7a2a move mocks to proper place 2025-10-28 16:40:03 +03:00
Uladzimir Havenchyk
3a985e46a2 lint 2025-10-28 16:13:18 +03:00
Uladzimir Havenchyk
ba2ae00dac fix typecheck 2025-10-28 14:28:01 +03:00
Uladzimir Havenchyk
0df6adcc51 remove duplicated button 2025-10-28 14:20:52 +03:00
Uladzimir Havenchyk
87c2392827 Merge remote-tracking branch 'origin/master' into nmezzopera/test-pyodie 2025-10-28 13:32:00 +03:00
Riley Thompson
0760630f10 Fix databricks multi-level-schema-wanted-catalogs-test (#65073)
* use schema inclusion filters

* fix test

* remove set dep
2025-10-27 23:16:02 +00:00
Noah Moss
27a078faf0 Move honeysql helper to simplify module dependencies (#64689)
* init branch

* FE - add codemirror diffing, add diff support to native query editor, fake a proposed query

* Add /ee/metabot-tools/get-transforms endpoint

Returns a sequence of all python or native query transforms.

BOT-391 [Backend] Create transform index tool API

* Add test that get-transforms does not include non-native MBQL transforms

* Add /ee/metabot-tools/get-transform-details endpoint

* allow opening metabot on transforms admin pages

* use transforms_codegen profile for metabot on transforms page

* send transform in context

* show metabot on edit + create transforms page

* accept tranform suggestions from metabot

* Cleanup malli schemas for get-transforms and get-transform-details

* add transform context on edit query page

* use transforms instead of data queries

* Parse out tables from transforms in metabot user context

* wip on creation flow

* hack in a message to metabot on save

* quick fix preview error not displaying correctly

* misc. fe improvements

* fix transform context on subsequent edits for the same transform

* half hacky way to use current editor state for context in transform editing

* Switch /ee/metabot-v3/get-transforms from :get to :post

This endpoint doesn't expect args of it's own in the body, but does accept the standard metabot conversation_id that
it echoes back.

* Show 'Apply Changes' button when a transform change is generated by the agent

* handle new transforms better

* Ensure we have a fallback for context items that don't have SQL to parse

* persist diff of transform to the conversation history

* temp - make metabot always visible on transforms admin pages

* Change button label to "Proposed changes to <transform>"

* copy change for create transform buttons in chat

* better hidden message ui

* hack - better emtpy convo text

* hide suggested prompts

* Add basic snippets tools

* ensure proposed queries go through nativeQuery.setQueryText so that template tags are parsed

* better todos

* even better todo list ui

* crude sidebar ui for query transforms diffs

* better suggestion chat ui

* good'nuff @mentions

* debug logging for search table bug

* further logging

* Ensure we parse template tags for transform edits in Metabot sidebar (#64001)

* cleaner, more copy/pastable, better flowing @mentions in metabot

* Fix metabot get-transforms api test to :post not :get

* Update metabot tools test with basic python transform tests

* Ensure transform :source and :target keys get snake cased when returned from metabot tool apis

* Add get-transform-python-library-details metabot tool api endpoint

* Enhance context with :used_tables for python transforms

* surface transforms in @-mention search

* some type fixes

* python FE progress

* python fe improvements + edit experience now works

* clear proposed on cancel

* fix accept in sidebar not saving

* better diff colors

* smaller todos

* cleaner code for todos

* improve ranking of transforms in search by hardcoding a last_viewed_at time in user-recency-expr

* first pass at nested @mentions

* Conditionally add transforms to model->db-model

* Add transforms-python to module deps for metabot

* Move native-query-transform? into transforms.util and re-use existing utils

metabot-v3.tools.transforms defined a couple of helper functions that were nearly identical to ones that have since
been added to transforms.util ns. Move some things around and make use of the existing transforms.util predicates,
which are now exported from the module's core namespace.

* lots of fe clean up

* prevent rewinding conversation for admin pages

* @mention solution that plays nicely with documents

* fix search bug

* fix type issues and few small feedback things

* Add transforms to search for Metabot (#64134)

* index transforms content

* Add support for transforms & query search in metabot search tool API

* fixup whitespace

* update to use new :fields syntax

* Fix up serach-native-query malli types

* Fix the 15-day interval for transforms to be db-agnostic

* move engine loading to metabase.search.init to break circular dep

* fix kondo

* Revert "Fix the 15-day interval for transforms to be db-agnostic"

This reverts commit 11b34e4cd4a8a5a0cf8041a1d82d487ed8c81025.

* add transform to set of appdb scorer models; unrevert db type fix

* fix kondo

* implement requisite multimethods for transforms not to error in in-place search engine

* ensure we enforce metabot/unknown contexts for transforms in in-place search backend as well

* fix filter test

* transform->postprocess to reduce naming ambiguity; add a basic transform ingestion test

* add a metabot result postprocessing test

* add transforms scoring test

* expand ingestion tests

* fix tests + kondo

* address feedback

* make suggestion models configurable for a Metabot instance

* fix @mention recents in documents, update suggestion sidebar component to not accept / reject items + calculate isViewing better

* quick fixes

* for rye guy

* Handful of fixes for transforms search (#64287)

* Add both search and search_v2 endpoints, and fix bug with search-native-query option

* add a docstring

* add a basic unit test for search-native-query option

* address comments

* better state management for suggested transofrms, move css around, clean up suggestion message code

* Update the list of source tables in Python editor when metabot changes it (#64258)

If metabot proposes changes to the list of input tables for a Python transform, update the PythonDataPicker component
to keep it in sync with the text of the transform source.

* python tables reference fix

* bug fixes and better state organization

* better draft support

* fix types

* add on leave modal, clear transforms on route leave, calc dirty state, fix onChange but for native query editor, better logic for showing cta text for transform suggestions

* Ensure transforms get deleted synchronously from the search index (#64382)

* Delete transforms from search index in t2/define-before-delete

* kondo

* fix up tests

* Stop pretending to snake_case transform source and target keys

The malli schemas were wrong, so these weren't actually getting snake_cased anyway.

See also:

https://github.com/metabase/ai-service/pull/387#discussion_r2414569482

* Fix failing test & kondo warning

* Add transforms dependency check API for metabot (#64542)

* WIP - add dependency check API for metabot

* omit bad_cards for now

* update return format

* add tests

* Fix fn call

* revert unneeded refactor

* Fix search transform-ingestion-test to use mt/native-query

* switch test to mt/native-query

* Fix module usage test

* fix up tests to use lib/native-query instead

* try to fix last test

* switch native-query-transform? to use lib.query/native?

* more mbql 5/metabase lib updates

* revert the 1-pixel fix

* Subtract a pixel when computing metabot chat filler height to avoid scrollbar flicker (#64690)

* Fix MetabotAgentSuggestionMessage only show "create" for new transforms (#64598)

https://metaboat.slack.com/archives/C09CR3MT1KR/p1760034396345789

* Surface broken cards from Metabot dependencies check API (#64781)

* fix missing sidebar diff after mbql5 change

* surface broken cards

* add test

* fix kondo

* remove unused code

* Fix up dep check question terminology & schema

* fix up test

* fix up another test

* address feedback

* Update the transform source schema to use ::queries.schema/query

* remove unused require

* address FE feedback

* fix modules config test

* @mentions tests and improvements

* couple of e2e tests fixes

* prevent leave confirmation when saving

* fix most of unit tests

* add back searchable models in metabot @mentions

* More tests for transform search + transform dependencies tool, and some new future-proofing read checks (#64896)

* add some future-proofing read checks to transform deps checks + related tests

* add some more transform search tests

* remove 404 check; move read check later in impl

* convert from toucan transform instance to metadata

* clean ns

* Move honeysql helper to simplify module dependencies

* fix more function calls in tests

* fix more calls

* fix (hopefully) last two calls

* kondo fix

* fix module config

* Fix detection of requires in threading macros

* Add metabase.driver.sql.query-processor back as a driver API namespace

* Add tests for metabot tools snippets and check-transform-dependencies endpoints (#64894)

* Add tests for metabot tools snippets API endpoints

* Add test for metabot tools check-transform-dependencies endpoint

* Remove trailing blank line to appease linter

* copy over appdb implementations of add-interval-honeysql-form to h2x; add back the sql.qp version for other drivers

* switch other driver methods back to sql.qp

* update relevant callsites

* move some test logic

* fix up error

* restore :added meta

* fix tests, move over one more pg timestamp helper

* oops, update callsites

* make function public

* add MetabotChatEditor.unit.spec.tsx

* add links.unit.spec.ts

* add AIMarkdown.unit.spec.tsx

* add MetabotAgentTodoMessage.unit.spec.tsx

* add MetabotAgentSuggestionMessage.unit.spec.tsx

* add metabot/state/reducer.unit.spec.ts w/ tests for suggested transforms state

* add e2e test coverage for create + update flow for both native sql + python transforms

* FE pr feedback and lint fix

* unit test fixes

* fix search test

* add temp metabot toggle button in admin nav

* fix a couple of failing FE tests

* attempt fix ci flake issue with metabot.unit.spec.tsx

* remove metabot-only restriction on transform search

* remove redundant logs in transform api endpoints to address ngoc's comment

* fix a number of transform search tests

* fix another test

* fix hopefully last search test

* bot feedback

* bot feedback

* fix function name

---------

Co-authored-by: Sloan Sparger <sloansparger@gmail.com>
Co-authored-by: Mike Appleby <86076+appleby@users.noreply.github.com>
Co-authored-by: Mihael Konjevic <konjevic@gmail.com>
Co-authored-by: Tyler Plude <tsplude@gmail.com>
2025-10-27 21:53:34 +00:00
Nemanja Glumac
3177f079e8 Upgrade Mantine to v8.3.5 (#65050)
This commit removes our custom Mantine hooks patch because it was resolved upstream.
See: https://github.com/mantinedev/mantine/pull/8189
2025-10-27 21:13:25 +01:00
Nemanja Glumac
49c0589aa8 Remove mage tests from the core classpath (#65046) 2025-10-27 21:06:08 +01:00
William
57afac78ba Make native validation allow using current-level aliases in other clauses (#64701)
Make native validation allow using current-level aliases in other clauses

`select a as b from table where b > 1` wasn't passing validation because the b alias wasn't in scope in the where.
This should now be fixed.

Also, native validation keeps more context when generating references, which should allow for better error messages.
2025-10-27 19:15:57 +00:00
Nick Fitzpatrick
1fed0f701c Dark mode day 4 patch (#64996)
* document resize handles

* metrics background color

* update command palette, account profile to use new form components

* fixing button variant

* fix e2e
2025-10-27 18:58:44 +00:00
Nathan Voxland
e9950fdc21 Additional error handling in appdb reindexing (#65013) 2025-10-27 13:06:02 -05:00
Nemanja Glumac
02f7a885ee Bring back the inlined explicit deduplicate command to postinstall (#65058) 2025-10-27 17:05:41 +01:00
Nemanja Glumac
3def5f4ca9 Fix frontend coverage workflow (#65048)
Instrumentation adds a lot of overhead. Unfortunately, even 30 seconds timeout wasn't enough for some of our unit tests. We're doubling that value in order to minimize the chances of this workflow halting/failing again.

* Add workflow_dispatch trigger

* Rename workflow to 'Frontend Test Coverage'
2025-10-27 09:27:34 -06:00
Nemanja Glumac
fcd7a98745 Do not include already patched libraries in node_modules cache (#65052) 2025-10-27 14:49:59 +01:00
Phoomparin Mano
b025a5bfb7 Add horizontal padding on embedding hub when shown in homepage (#65051) 2025-10-27 20:27:13 +07:00
Phoomparin Mano
02467bd231 Design updates for static and interactive embedding settings (#64930) 2025-10-27 08:45:03 +00:00
Nemanja Glumac
ba60e617ba Temporarily patch the broken FE unit test that times out (#65027) 2025-10-27 09:36:29 +01:00
Nemanja Glumac
7738ae7271 Enable Trunk Quarantine for FE unit tests (#65022) 2025-10-27 11:50:20 +13:00
metamben
08c8d0f1f6 Add implicitly joined tables as dependencies (#65015)
* Add implicitly joined tables as dependencies

Fixes QUE-2705

* Simplify table ID collection

* Align local names with producer function names
2025-10-27 01:11:26 +03:00
Nemanja Glumac
bdef8558a9 Remove manual version resolution for nanoid (#65023)
It already resolves to a higher version than that
which was defined in a resolution.
2025-10-26 21:59:24 +01:00
Jeff Bruemmer
20c7cb44a3 docs - minor edits (#65021)
* minor edits

* Apply suggestions from code review
2025-10-26 15:00:19 +00:00
Uladzimir Havenchyk
eda355803b Merge remote-tracking branch 'origin/master' into nmezzopera/test-pyodie 2025-10-26 16:39:15 +03:00
Uladzimir Havenchyk
e6df0dc8c5 Merge remote-tracking branch 'origin/master' into nmezzopera/test-pyodie 2025-10-26 16:02:00 +03:00
Uladzimir Havenchyk
90b57af0ae drop patch from cypress-esbuild-preprocessor (#65010) 2025-10-26 00:08:49 +02:00
Uladzimir Havenchyk
6ec03b098e chore: make bookmark button look the same as other action buttons (#64951)
* chore: make bookmark button look the same as other action buttons

* revert active state
2025-10-25 22:50:07 +03:00
Uladzimir Havenchyk
7b7d02442a deps: don't bring node polyfills into browser (#64740)
* deps: don't bring node polyfills into browser

* patch package

* fix lint

* bring back Buffer

* another attempt

* Revert "patch package"

This reverts commit 0aee5326018c25f3281400a9254c37fe2b4e7199.

* update password-generator

* try different config

* add fallback

* one more attempt

* one more attempt

* add back buffer

* one more time

* update rspack

* update rspack config

* drop crypto polyfill and patch package instead

* address review

* update patch
2025-10-25 06:54:41 +00:00
Maz Ameli
5decddf00c Simplify metabot icon (#65017) 2025-10-24 23:59:37 +00:00
John Swanson
bacdb174ee Remote Sync (#62686)
* Fix remote sync settings test

* Fix sync type setting validation test

* Fix check sync task type is production

* Update plain type to collection_type

* Cascade changes to collection type

* Update deps checks when collection type changes

* Fix task type check in export

* move setting check to api for better status report

* add tests for sync-type

* Don't mark newly created entities as updated or removed UXW-1806

* UXW-1821 enabled badge

* UXW-1818: hide branch picker and push button for non-admins

* cleanup and UXW-1814

* remove border from the branch picker button

* cleanup

* UXW-1829 update diff modal ui

* UXW-1807: token should appear masked

* Allow setting of nil token

* UXW-1833: show backend error when saving invalid git settings

* Add new collection update/create events

* Remove per collection imp/exp; change dirty status table

* Redo event handling add removed status

* Sync object table on syncs

* Fix status names

* Added /current-task/cancel API and track version in remote_sync_task

* Add is_remote_synced to api responses

* Fix adding is_remote_sync hydration

* Fixed compilation error

* remove hashp

* Fix loading is_remote_sync hydration

* Resolve ambiguous reference

* Fix n+1 detector

if it gets a heterogeneous set of things we should hydrate each type
separately.

* Add can-create? handlers

* remote sync: a few bugfixes and improvements from my bugbash (#64372)

* Set `collection.type` on archive/unarchive

When unarchiving or archiving collections that have the `remote-synced`
type, we need to set their new type appropriately.

When archiving, we should give them a normal (nil) type.

When unarchiving any collection *to* a remote-synced collection, we
should set the type to `remote-synced`.

* Allow serdes without archived items

and use it in remote sync export.

During dependency checking, we do *not* want to exclude archived items:
if card A uses card B, and card B is archived, we need to include Card B
in the list of dependencies! Otherwise we'll say that it's fine to
remote sync card A when it's not.

* Add tests

* Documents are descendants of collections

* don't include cards as document descendants

* fix tests, dashboard descendants args

* remove #p and unnecessary query

* remove another `#p`

* Update auto sync token to enable import job

* More is_remote_sync hydration fixes

* Fix lints and document oss serdes

* Fix cards to be valid for update events

* Don't actually import if nothing has changed in the remote repo

* Remove hashp

* UXW-1817: change branches should update content

* UXW-1813 ensure sync dirty state is properly invalidated

* UXW-1864 fix how collections changes appear in the diff

* Fix ee-available? check

* Improve is_remote_synced hydration

* Fix some more oss/ee issues

finish remote ChangeLog model

* fix invalidation on removal

* fix missing require

* Don't need to handle transforms directories specially

* fix tests to make sure state is fully reset

* remove duplicate require

* Fix deadlock on import

* Fixing tests

* Fix document tests

* Fix kondos

* handle removed sync_status

* UXW-1851: show moving out of synced collection error

* feature flag, misc fixes

* dirty state tracking for snippets

* Fix ns typo

* Add remote-sync token and config

* enforce remote_sync token feature on the FE

* allow cancelling the remote-sync

* Track timeline

* Force re-import when configuring for production mode

* Fixed compilation error

* Force re-import when configuring for production mode only when auto-sync is enabled

* Throwa 400 error if there are dirty objects when doing an import

* force import button

* Better archiving checks with remote synced collections

* Better tests for documents and remote-sync deps

* Remove hashp

* remote hashp

* Remove other hashp

* More consistent collection write checks

* Fix broken collection tests

* Fix broken documents tests

* improve imports/exports frontend

* Implement can-create? for timeline-event

* tweak copy

* Always update branch setting

* Initial Commit

* Fix more tests

* Remove bad parallel annotations

* Show error toast when adding a collection that has references outside of the repo

* reasonable structure, error handling

* timelines editing is less frequent, we can invalidate dirty state on any edit

* Fix dirty state api tests for mysql

* bring error details back

* Fix collection move tests

* Fix remove parallel from can_restore tests

Splitting this into smaller tests seems to introduce some kind of state
that causes tests to fail in parallel

* Fix make logs use unique names for be tests

* Bump toucan2 versions

* Fix var name

* Fix check that there are exportable collections

* Add test for exportable check

* Started on e2e test

* Fix issue with merge

* Fix arguments to card descendants

* Handle new ingestable interface

* Put back changes in cypress-runner

* Fix remaining failing enterprise tests

* Fix one set of app tests

* Clean remote sync state in obj tests

* single collection

* Fix unit test - enterprise getIcon function only applied when new feature is enabled (ResultItem.unit.spec.tsx)

* Fix ts issues / Clean up

* FE fixes

* Remove parallel annotations

* Fix missing import from merging master

* Fix the fix

* always create collection to sync

* no unsyncing

* Remove associating location to trash from search

* Prevent users from switching branches with unsynced changes + show warning

* Create remote-sync collection when it doesn't exist

* Prevent changing to production with unsynced changes

* Make sure dirty state refetches on admin settings load

* single synced collection ui update

* Cannot change to production mode when there are unsynced changes

* Fix failing query

* unquote branches

* fix eastwood

* fix timeline event publishing

* fix import

* Move dashboard remote sync api tests into ee

...where they can reference the setting

* Created /stash API and renamed create branch api to /create-branch

* Fix settings issue

* Fix remaining permissions message tests

* Make sure drop target always works for trash

* Add checks for if we're in trash elsewhere

* cleanup

* git-sync to remote-sync

* more git-sync to remote-sync

* Don't allow export if it overwrites an external commit

* - Don't assume a "main" branch
- Attempt an import when no remote-sync branch exists when enabling dev mode

* Fix creating remote sync library

* refactor to middleware

* hack: add a delay for refetching instance settings or dirty state after remote sync task finishes

* UXW-1953: confirmation flow when switching branches in prod

* Update modal when switching branches with dirty state / Component refactorings

* Create a branch off the last-used commit, not the branch itself

* Add options modal when trying to push while remote is ahead

* Support force option on export

* Update branch setting and complete task in txn

* Let export! set branch in stash and fix tests

* Fix PR feedback nits

* Update enterprise/backend/src/metabase_enterprise/remote_sync/api.clj

* Consistent documentation style in remote-sync

* Add option to pull from remote / Adjust push/pull icons / Adjust out-of-sync options modal

* modals UI polish

* constants clean up

* Add api schemas and make error messages consistent

* fix check-403 to write-check

* Apply suggestions from code review

Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>

* Clean up a couple components / Move things around

* Address renaming suggestions

* Fix var names and bad merge

* double->float in schema

* Share error handling

* Update enterprise/backend/src/metabase_enterprise/remote_sync/settings.clj

* Update enterprise/backend/src/metabase_enterprise/remote_sync/settings.clj

* Update enterprise/backend/src/metabase_enterprise/remote_sync/settings.clj

* Addressing small PR comments

* Refetch properties when branch is created (current branch changed)

* Make sure /current-task is only called when import and export are not in progress

* Replace unset color variables

* Improve element padding on side panel

* Remove a couple trailing spaces reported by clj whitespace linter

* Show error when settings request fails / Make sure current-task also waits for the PUT settings mutation

* Fix document perm tests

* Allow empty remote-url, moved import and export calls to impl

* Fix minor prettier issue

* Fix another lil lint issue

* temp

* e2e push / pull

* Unify more of the import implementation

* fix CI failures

* fix mysql ci failures

* Address metabot critiques

* Address additional metabot feedback

* last round of docstring feedback

* library admin settings e2e

* Add attribution to TODO

* fix ws

* fix missed commiting file

* fix another missing file

* production switch branches

* More clojure like docstrings

* More docstring fixes

* adding branch switching test

* Address Nick's PR review comments (most of them)

* Fix more nits

* Resolving Nick's comments part 2

* Improving remote-sync settings handling

* attempt to repair synced_folder icon

* Fail if attempting to connect to an uninitialized repo

* correct the name of synced_collection.svg

* add new repository icon

* Add default-branch to source protocol

* Update Git Sync to Remote Sync in Admin settings (#64993)

* Make api docstrings and errors more generic

* Use check-400 to simplify api

* fix ws

* Rollback BaseSMTPConnectionForm.tsx (fixes a e2e test)

* fix e2e tests?

* Fix small merge issue

* Always use `last-version` instead of caring about import vs. export version

* starting warning modal tests

* Fetch source at the beginning of import/export operations

* Fix broken test

* Delete branches that were deleted on remote

* Fix missing test suffix

* Fix eastwood

* Adjust branching e2e test, skip failing tests

---------

Co-authored-by: Edward Paget <ed.paget@gmail.com>
Co-authored-by: Nathan Voxland <nathan@metabase.com>
Co-authored-by: Aleksandr Lesnenko <alxnddr@gmail.com>
Co-authored-by: Edward Paget <edpaget@users.noreply.github.com>
Co-authored-by: Aleksandr Lesnenko <alxnddr@users.noreply.github.com>
Co-authored-by: Anderson <anderson@metabase.com>
Co-authored-by: eliotmetabase <eliot@metabase.com>
Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>
Co-authored-by: Nick Fitzpatrick <nickfitz.582@gmail.com>
Co-authored-by: Maz Ameli <maz@metabase.com>
2025-10-24 15:58:25 -07:00
metamben
bb6d7b1cbc Fix transform target table hydration (#64999) 2025-10-24 21:41:57 +00:00
Nemanja Glumac
f01ea21e37 Do not deduplicate js dependencies automatically (#65004) 2025-10-24 21:53:53 +02:00
Riley Thompson
e937214a8d Include documents and dashboards in dependencies (#64888) 2025-10-24 13:42:24 -04:00
Tyler Plude
d9060d941c [METABOT] Project Code Gen (#63313)
* init branch

* FE - add codemirror diffing, add diff support to native query editor, fake a proposed query

* Add /ee/metabot-tools/get-transforms endpoint

Returns a sequence of all python or native query transforms.

BOT-391 [Backend] Create transform index tool API

* Add test that get-transforms does not include non-native MBQL transforms

* Add /ee/metabot-tools/get-transform-details endpoint

* allow opening metabot on transforms admin pages

* use transforms_codegen profile for metabot on transforms page

* send transform in context

* show metabot on edit + create transforms page

* accept tranform suggestions from metabot

* Cleanup malli schemas for get-transforms and get-transform-details

* add transform context on edit query page

* use transforms instead of data queries

* Parse out tables from transforms in metabot user context

* wip on creation flow

* hack in a message to metabot on save

* quick fix preview error not displaying correctly

* misc. fe improvements

* fix transform context on subsequent edits for the same transform

* half hacky way to use current editor state for context in transform editing

* Switch /ee/metabot-v3/get-transforms from :get to :post

This endpoint doesn't expect args of it's own in the body, but does accept the standard metabot conversation_id that
it echoes back.

* Show 'Apply Changes' button when a transform change is generated by the agent

* handle new transforms better

* Ensure we have a fallback for context items that don't have SQL to parse

* persist diff of transform to the conversation history

* temp - make metabot always visible on transforms admin pages

* Change button label to "Proposed changes to <transform>"

* copy change for create transform buttons in chat

* better hidden message ui

* hack - better emtpy convo text

* hide suggested prompts

* Add basic snippets tools

* ensure proposed queries go through nativeQuery.setQueryText so that template tags are parsed

* better todos

* even better todo list ui

* crude sidebar ui for query transforms diffs

* better suggestion chat ui

* good'nuff @mentions

* debug logging for search table bug

* further logging

* Ensure we parse template tags for transform edits in Metabot sidebar (#64001)

* cleaner, more copy/pastable, better flowing @mentions in metabot

* Fix metabot get-transforms api test to :post not :get

* Update metabot tools test with basic python transform tests

* Ensure transform :source and :target keys get snake cased when returned from metabot tool apis

* Add get-transform-python-library-details metabot tool api endpoint

* Enhance context with :used_tables for python transforms

* surface transforms in @-mention search

* some type fixes

* python FE progress

* python fe improvements + edit experience now works

* clear proposed on cancel

* fix accept in sidebar not saving

* better diff colors

* smaller todos

* cleaner code for todos

* improve ranking of transforms in search by hardcoding a last_viewed_at time in user-recency-expr

* first pass at nested @mentions

* Conditionally add transforms to model->db-model

* Add transforms-python to module deps for metabot

* Move native-query-transform? into transforms.util and re-use existing utils

metabot-v3.tools.transforms defined a couple of helper functions that were nearly identical to ones that have since
been added to transforms.util ns. Move some things around and make use of the existing transforms.util predicates,
which are now exported from the module's core namespace.

* lots of fe clean up

* prevent rewinding conversation for admin pages

* @mention solution that plays nicely with documents

* fix search bug

* fix type issues and few small feedback things

* Add transforms to search for Metabot (#64134)

* index transforms content

* Add support for transforms & query search in metabot search tool API

* fixup whitespace

* update to use new :fields syntax

* Fix up serach-native-query malli types

* Fix the 15-day interval for transforms to be db-agnostic

* move engine loading to metabase.search.init to break circular dep

* fix kondo

* Revert "Fix the 15-day interval for transforms to be db-agnostic"

This reverts commit 11b34e4cd4a8a5a0cf8041a1d82d487ed8c81025.

* add transform to set of appdb scorer models; unrevert db type fix

* fix kondo

* implement requisite multimethods for transforms not to error in in-place search engine

* ensure we enforce metabot/unknown contexts for transforms in in-place search backend as well

* fix filter test

* transform->postprocess to reduce naming ambiguity; add a basic transform ingestion test

* add a metabot result postprocessing test

* add transforms scoring test

* expand ingestion tests

* fix tests + kondo

* address feedback

* make suggestion models configurable for a Metabot instance

* fix @mention recents in documents, update suggestion sidebar component to not accept / reject items + calculate isViewing better

* quick fixes

* for rye guy

* Handful of fixes for transforms search (#64287)

* Add both search and search_v2 endpoints, and fix bug with search-native-query option

* add a docstring

* add a basic unit test for search-native-query option

* address comments

* better state management for suggested transofrms, move css around, clean up suggestion message code

* Update the list of source tables in Python editor when metabot changes it (#64258)

If metabot proposes changes to the list of input tables for a Python transform, update the PythonDataPicker component
to keep it in sync with the text of the transform source.

* python tables reference fix

* bug fixes and better state organization

* better draft support

* fix types

* add on leave modal, clear transforms on route leave, calc dirty state, fix onChange but for native query editor, better logic for showing cta text for transform suggestions

* Ensure transforms get deleted synchronously from the search index (#64382)

* Delete transforms from search index in t2/define-before-delete

* kondo

* fix up tests

* Stop pretending to snake_case transform source and target keys

The malli schemas were wrong, so these weren't actually getting snake_cased anyway.

See also:

https://github.com/metabase/ai-service/pull/387#discussion_r2414569482

* Fix failing test & kondo warning

* Add transforms dependency check API for metabot (#64542)

* WIP - add dependency check API for metabot

* omit bad_cards for now

* update return format

* add tests

* Fix fn call

* revert unneeded refactor

* Fix search transform-ingestion-test to use mt/native-query

* switch test to mt/native-query

* Fix module usage test

* fix up tests to use lib/native-query instead

* try to fix last test

* switch native-query-transform? to use lib.query/native?

* more mbql 5/metabase lib updates

* revert the 1-pixel fix

* Subtract a pixel when computing metabot chat filler height to avoid scrollbar flicker (#64690)

* Fix MetabotAgentSuggestionMessage only show "create" for new transforms (#64598)

https://metaboat.slack.com/archives/C09CR3MT1KR/p1760034396345789

* Surface broken cards from Metabot dependencies check API (#64781)

* fix missing sidebar diff after mbql5 change

* surface broken cards

* add test

* fix kondo

* remove unused code

* Fix up dep check question terminology & schema

* fix up test

* fix up another test

* address feedback

* Update the transform source schema to use ::queries.schema/query

* remove unused require

* address FE feedback

* fix modules config test

* @mentions tests and improvements

* couple of e2e tests fixes

* prevent leave confirmation when saving

* fix most of unit tests

* add back searchable models in metabot @mentions

* More tests for transform search + transform dependencies tool, and some new future-proofing read checks (#64896)

* add some future-proofing read checks to transform deps checks + related tests

* add some more transform search tests

* remove 404 check; move read check later in impl

* convert from toucan transform instance to metadata

* clean ns

* Add tests for metabot tools snippets and check-transform-dependencies endpoints (#64894)

* Add tests for metabot tools snippets API endpoints

* Add test for metabot tools check-transform-dependencies endpoint

* Remove trailing blank line to appease linter

* add MetabotChatEditor.unit.spec.tsx

* add links.unit.spec.ts

* add AIMarkdown.unit.spec.tsx

* add MetabotAgentTodoMessage.unit.spec.tsx

* add MetabotAgentSuggestionMessage.unit.spec.tsx

* add metabot/state/reducer.unit.spec.ts w/ tests for suggested transforms state

* add e2e test coverage for create + update flow for both native sql + python transforms

* FE pr feedback and lint fix

* unit test fixes

* fix search test

* add temp metabot toggle button in admin nav

* fix a couple of failing FE tests

* attempt fix ci flake issue with metabot.unit.spec.tsx

* remove metabot-only restriction on transform search

* remove redundant logs in transform api endpoints to address ngoc's comment

* fix a number of transform search tests

* fix another test

* fix hopefully last search test

---------

Co-authored-by: Sloan Sparger <sloansparger@gmail.com>
Co-authored-by: Mike Appleby <86076+appleby@users.noreply.github.com>
Co-authored-by: Noah Moss <noahbmoss@gmail.com>
Co-authored-by: Mihael Konjevic <konjevic@gmail.com>
Co-authored-by: Noah Moss <32746338+noahmoss@users.noreply.github.com>
2025-10-24 11:58:30 -05:00
Cam Saul
15b31fb834 nest-query => Lib (#64940)
* nest-query => Lib

* Fix schema

* Update changelog

* PR feedback from #64901

* Upgrade field resolution to handle CATEGORY_2 => CATEGORY

* Update docstring

* Test fix 🔧

* Test fixes 🔧

* Whoops commit new file

* Test fixes 🔧
2025-10-24 09:42:55 -07:00
Nemanja Glumac
ce56b8e398 Simplify and unify M2 and node-modules caches (#64955) 2025-10-24 18:18:51 +02:00
Sébastien
d2b54425f2 Closes EMB-906 custom branding images for SDK (#64946)
* .

* .

* types

* tidy up

* tidy up again

* tidy up again

* cleanup
2025-10-24 17:35:22 +02:00
metamben
8722548f6d Add permissions checks for the dependencies API (#64965) 2025-10-24 10:57:43 -04:00
Nemanja Glumac
8a542dd80a Introduce Metabase CI caching strategy (#64988) 2025-10-24 16:20:56 +02:00
Marcos
940d244d2d fix stuck loading in 'caching in questions and dashboards' admin section (#64799) 2025-10-24 11:15:50 -03:00
Alex Yarosh
33e9a2cc25 docs: ai chat component (#64989)
* ai chat component

* oops

* Update docs/embedding/embedded-analytics-js.md

Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>

* Update docs/embedding/embedded-analytics-js.md

* Update docs/embedding/embedded-analytics-js.md

---------

Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>
2025-10-24 14:05:48 +00:00
Nick Fitzpatrick
9ddffb2edf handful of fixes (#64854)
* handful of fixes

* trash icon color, fix tooltip text in charts

* Update Loki Snapshots

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-10-24 09:48:04 -03:00
Uladzimir Havenchyk
c396990a98 fix(command palette): show different skeleton when no recent items (#64929)
* fix(command palette): show different skeleton when no recent items

* cleanup

* make props required

* fix typecheck

* remove default
2025-10-24 11:23:40 +00:00
github-automation-metabase
29f1dac45f Update generated docs (master) (#64975)
Co-authored-by: github-actions <github-actions@github.com>
2025-10-24 07:14:17 -04:00
Mahatthana (Kelvin) Nomsawadi
db9c8dcfbf Wait for timeline to refresh before clicking the checkbox (#64984) 2025-10-24 11:41:08 +01:00
Dan Stone
2dc59090e3 Connection closed flake during python-transform-timeout-status-test round 2 (#64947)
* Remove redundant transaction setting in timeout test

Did not fix flake as expected

* If in a transaction do not open the python log thread
2025-10-24 09:48:04 +00:00
Fraser
a13c7d234d Remove unused packages from package json (#64941) 2025-10-24 20:43:51 +13:00
Fraser
577b1d8fb6 Remove regenorator-runtime (#64942)
Generators are native in browsers now, this dep is not needed
2025-10-24 14:30:23 +13:00
Anderson
6586bba402 Removing docs/* for ignore (#64973)
Due to `useEngineDocMarkdownContent` changes the dynamic imports are needed for `import(`docs/databases/connections/${docFileName}.md`)`

Co-authored-by: Jonathan Sheely <jsheely@thirtytech.net>
2025-10-23 20:03:34 -03:00
dpsutton
686113d2d7 disable snowflake (#64962)
https://linear.app/metabase/issue/DEV-997/reenable-snowflake-in-ci

due date one week
2025-10-23 17:00:56 -05:00
John Swanson
a893803cfb Collections are delete-able (#64414)
* Collections are delete-able

The `can_delete` flag for collections was the only missing bit to have
collections be deletable, since I added an API endpoint to delete
collections a while ago! I thought FE work was required, doh.

Fixes UXW-1090

* Fix e2e tests
2025-10-23 13:16:52 -07:00
Cam Saul
aa200bc31f X-Rays => Lib (#64901)
* Rework X-Rays to use Lib

* Test change

* Fix the last few failing tests

* Remove dead code

* PR feedback

* Claude updates

* Fix typos

* Oops

* e2e test fix 🔧
2025-10-23 10:03:38 -07:00
Alexander Polyankin
1b03fa10a9 Dependency tracking graph (#64202)
* Search

* Search

* Search

* Search

* Search

* Search

* Search

* Search

* New format

* New format

* New format

* New format

* New format

* New format

* updated graph endpoint

* added /graph/node

* remove prn

* add ability to get graph for a single node

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* New format

* update graph api again

* Fix viz icon

* CSS hack

* CSS hack

* Fix layout jump

* Types

* Types

* Types

* Types

* Types

* Types

* Types

* Types

* Types

* Types

* Types

* Types

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix tests

* Fix tests

* Fix

* update api

* Fixes

* Add view count

* Add view count

* update api again

* Fix

* Fix

* Fix

* Fix

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* Add sorting

* api update

* Fix merge

* Fix merge

* Fix merge

* Search

* Search

* Search

* Search

* Search

* Search

* selection

* selection

* selection

* selection

* selection

* selection

* selection

* selection

* selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Restrict transform search to admin users and add basic test

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix selection

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Info

* Info

* Add a bunch of fields to the data nodes

* Info

* Info

* Info

* Info

* Hydrate table fields in graph endpoints

* Info

* Info

* Info

* Info

* Info

* Info

* Hydrate table for transforms and db for tables

* Remove comment form

* Info

* Info

* Acknowledge that db id, schema, and table name form a key

* Info

* Info

* Info

* Fixes

* Fixes

* Adjust loading

* Add check

* Add check

* Fixes

* Fixes

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Tests

* Fix compilation

* Tests

* Tests

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* UI updates

* Handle errors

* Handle errors

* Handle errors

* Handle errors

* Handle errors

* Remove view_count for non-questions

* Remove view_count for non-questions

* Remove view_count for non-questions

* Fix some tests

* Remove view_count for non-questions

* Fix one more test

* Add more tests

* Remove view_count for non-questions

* Remove view_count for non-questions

* Remove view_count for non-questions

* Remove view_count for non-questions

* Remove view_count for non-questions

* Remove view_count for non-questions

* Remove view_count for non-questions

* Remove view_count for non-questions

* Add e2e tests

* Add e2e tests

* Rename to dependents_count on FE

* Rename :dependents to :dependents_count in the BE

* Fix FE types

* Fix FE types

---------

Co-authored-by: William Zimrin <william@metabase.com>
Co-authored-by: Tamás Benkő <tamas@metabase.com>
2025-10-23 12:17:13 -04:00
Nemanja Glumac
ac8285254b Start utilizing the Trunk Quarantine for E2E tests (#64873) 2025-10-23 14:10:37 +02:00
Sébastien
1a8a04cf82 fix(sdk): Closes EMB-905 no error when embedding MB localhost->distant MB (#64835)
* Closes EMB-905 no error when embedding MB localhost->distant MB

* cleanup
2025-10-23 12:33:32 +02:00
Sébastien
750c6ebb22 Fixes "In HTML, <button> cannot be a descendant of <button>." error and removes console warnings (#64904)
* Removes many console NPE warnings

* button -> icon for widgetStatus

* role

* fixup

* padding

* fixed flaky
2025-10-23 11:56:09 +02:00
Nemanja Glumac
2c71824e61 Sane CI caches PoC - Cypress (#64932) 2025-10-23 13:53:08 +13:00
Nemanja Glumac
a58b2ebefc Remove unused add-to-project action (#64910) 2025-10-22 17:13:39 -07:00
Nathan Voxland
ac22d632bc Improve logging and recovery around errors in reindexing and create-table! (#64897) 2025-10-22 16:07:13 -05:00
Uladzimir Havenchyk
7fac1f9d24 Merge remote-tracking branch 'origin/master' into nmezzopera/test-pyodie 2025-10-23 00:06:52 +03:00
Phoomparin Mano
b56f63252b Design polishes for modular embedding and embedding setup guide (#64893) 2025-10-23 03:14:52 +07:00
Uladzimir Havenchyk
62fceee952 fix: restore missing css after migration to new postcss-preset-env (#64874)
* fix: restore missing css after migration to new postcss-preset-env

* update comment

* Update postcss.config.js

Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>

* proper fix

* fix comment

* remove path

---------

Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>
2025-10-22 22:36:56 +03:00
Phoomparin Mano
2feb85417d feat(sdk-bundle, embed-js): stacked layout updates for metabot question (#64573) 2025-10-22 19:16:44 +00:00
John Swanson
8dc5cec918 Remove :feature checks on some EE code (#64848)
* Assert premium features for some middleware

* Fix an existing bug

These tests started failing here, which revealed that they formerly
never actually were testing what they thought they were.

A few reasons:
- they turned on `advanced-permissions` feature by itself, so sandboxing
was always off here

- they set up sandboxing in a nonstandard way

- one had a typo so we weren't even wrapping the body with
`with-download-perms!` (it was a separate block entirely)

This hid the bug that some of the tests were intended to reproduce - if
a card used for sandboxing had a native query, then we required that you
have download permissions on the entire database, which is wrong.

* fix test

* make assertions with/without tokens for sandboxing

* Add comments about why `:feature :none`

* Update enterprise/backend/test/metabase_enterprise/sandbox/query_processor/middleware/sandboxing_test.clj

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>

* add a nicer docstring and change fn name

replace `any-native-unsandboxed-stage?` with
`any-native-stage-not-introduced-by-sandbox?`

* Block without feature enabled

* CR response

---------

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-10-22 11:20:12 -07:00
Phoomparin Mano
560a253192 Design polishes for EAJS embed wizard (#64895) 2025-10-23 01:19:07 +07:00
github-automation-metabase
753c645216 Update generated docs (master) (#64900)
Co-authored-by: github-actions <github-actions@github.com>
2025-10-22 14:10:00 -04:00
Anderson
bd18384233 Fix unnecessary redirects on Models & Metrics pages (#64489)
* Fix models and metrics links to prevent redirect from /question/:id-slug

* Fix e2e
2025-10-22 13:42:49 -03:00
Nicolò Pretto
67d603aa42 feat(sdk): plugins passed to the provider are passed down to the (#64920)
dashboard
2025-10-22 15:52:18 +00:00
Rodrigo López Dato
b9ac3ab886 Allow app and capacitor schemes as valid origins for Ionic apps (#64719)
* Allow any scheme for URLs, not just http/https

* Explicitly allow app:// and capacitor:// schemes

* fix flakiness in e2e test

* Only accept HTTP/HTTPS when no protocol is specified

---------

Co-authored-by: Uladzimir Havenchyk <uladzimir@metabase.com>
2025-10-22 11:02:11 -03:00
Nicolò Pretto
bef6cb6908 make mapQuestionClickActions intercept links and fix links to host app (#64623)
* ugly solution #1

* revert the ugly part

* refactor and tests

* fix(modular): make links/click behavior that link to the same origin as the host app work and open them on a new tab

* update tests to expect a click behavior

* clean up tests

* tests for the same domain issue

* add also basic support for links, just in case

* Update e2e/test-component/scenarios/embedding-sdk/dashboard-click-behavior.cy.spec.tsx

* refactor tests as per feedback to use mockIsEmbeddingSdk

* don't remove column settings
2025-10-22 15:07:59 +02:00
Nemanja Glumac
f573f15de1 Replace and remove use-table-list-query (#64772) 2025-10-22 10:33:01 +00:00
Kamil Mielnik
38bf19399d Update onboarding video (#64905) 2025-10-22 09:59:44 +00:00
Cam Saul
f3b85b3e33 Lib column unique key (#64889) 2025-10-22 09:54:57 +00:00
Nemanja Glumac
23f74a039f Update team members in team.json (#64902)
Removed 'kulyk' from Admin team and added multiple members to DevEx team.
2025-10-22 11:19:25 +02:00
Kamil Mielnik
3ad1913339 Separate favicon for dev env (#64845)
* Add separate favicon for dev env

* Don't use dev favicon if a custom one has been set

* Red favicon

* Format code
2025-10-22 16:16:37 +07:00
Dan Stone
e622f71034 Opt logging test out of slower drivers (#64903) 2025-10-22 09:03:45 +00:00
Mahatthana (Kelvin) Nomsawadi
abeef3b5a8 feat(sdk): Let end users archive items in the CollectionBrowser SDK component (#64561)
* Remove unnecessary default value

* Remove unnecessary export

* Show move to trash icon in CollectionBrowser

* Make the trash button easier to work with

* Add a dropdown

* Fix icon

* Archive resources in the collection browser

* Add tests

* Update UX

* Prevent external type change

* Remove custom style
2025-10-22 04:38:59 +01:00
Fraser
2637538cee Use more robust approach to detecting unmocked routes (#64508) 2025-10-22 16:14:26 +13:00
Maz Ameli
5aad91c383 fix border color (#64857) 2025-10-21 20:49:49 -04:00
Maz Ameli
5931cb0d0a Subtler Add Data button in side nav (#64745)
* subtler add data button in side nav

* fix tests

* update test

* fix unrelated broken test

* fix another unrelated broken test

* try fixing test again

* undo changes to unrelated tests

* Cursor's attempt at fixing related test
2025-10-21 15:49:01 -07:00
Cam Saul
8ad785fdbb Deprecate legacy MBQL utils (#64595)
* Deprecate legacy MBQL utils

* Deprecate legacy MBQL utils

* cljfmt

* Fix most tests except long native column names

* Kondo

* Test fixes 🔧

* Fix .clj versus .cljc in Lib

* Disable deprecation warnings

* Fix cljs

* Mega normalization improvements

* Kondo

* Another round of test fixes 🔧

* Schema fix 🔧

* PR feedback; test fixes

* Test fixes 🔧

* Fix BigQuery tests

* Test fix 🔧

* Test fixes 🔧

* Fix Card QP parameter normalization AGAIN 😆

* Oops

* Fix Claude code review

* Fix Claude code review

* Fix BigQuery tests
2025-10-21 15:29:36 -07:00
dpsutton
78308b14f9 Extend db connection timeout in tests (#64886)
* Extend db connection timeout in tests

We allow for 10 seconds in the app, and 3 seconds in test. I extend that
3 seconds to 5 seconds. This should really only affect bigquery.

In bigquery, we test if you "can connect" by connecting to the project
and then attmepting to find any datasets that you are able to see. This
is important because each test run connects to the same project but is
scoped down to fewer datsets. It's possible we could change this
behavior and return if you can list datasets at all, but it is nice if
you can see at least one dataset based on your inclusion and exclusion
filters.

For reference, the filters for my current CI run are:

```clojure
bigquery-cloud-sdk=> (update details :service-account-json (constantly "<<redacted>>"))
{:project-id nil,
 :service-account-json "<<redacted>>",
 :dataset-filters-type "inclusion",
 :dataset-filters-patterns "sha_4c3ca6238018e2b60025297f3e5c39671588adf2_QLGKZKIAOSQXOGGDURQY",
 :include-user-id-and-hash true,
 :project-id-from-credentials "metabase-bigquery-driver"}
```

In my repl, i'm seeing the following behavior:

```clojure
bigquery-cloud-sdk=> (time (let [client (database-details->client details)
                            project-id (get-project-id details)
                            datasets (.listDatasets client project-id (u/varargs BigQuery$DatasetListOption))
                            ]
                        (vec (for [^Dataset dataset (.iterateAll datasets)
                               :let [dataset-id (.. dataset getDatasetId getDataset)]
                               ]
                           dataset-id))))
"Elapsed time: 2692.292292 msecs"
["BQ_tupac_sightings"
 "Shakespeare"
 ...
 "v6_sample_dataset"]
bigquery-cloud-sdk=> (count *1)
273
```

So just enumerating all datasets takes ~2.7 seconds so we are flirting
with the fail limit of 3 seconds.

I extend this to 5 seconds and this should only give a bit of breathing
room to bigquery and everything else remains the same.

* fix flakiness in e2e test

---------

Co-authored-by: Uladzimir Havenchyk <uladzimir@metabase.com>
2025-10-21 17:15:28 -05:00
Alex Yarosh
3d5410d199 samesite (#64883) 2025-10-21 17:28:05 -04:00
Phoomparin Mano
497ef8ebe1 Embedding hub's checklist endpoint fails due to sample database changes (#64642) 2025-10-22 02:39:38 +07:00
Dan Stone
ec16936ff8 Add new columns to metabase_field for internal-tools/data-apps (#60263)
* Add migrations

* Add new columns to serde spec

* Update serde baseline

Will change again in follow up once sql-jdbc behaviour is ported

* Extend sql-jdbc describe-table

* Sync new field columns

* Extend field our-metadata to the new sync columns

* Fix tests

* Add postgres support new field columns

* Add generic driver tests for nullability and defaults

* Extend clickhouse test driver to :not-null? :default field defs

* Add new columns to mysql describe-fields-sql

* Add new features for better test specification

- :describe-is-nullable
- :describe-default-expr

In both cases if the feature is unsupported, the driver must return `nil` for the respective field metadata keyword.

* Add :database-is-generated test and driver feature

* Fix load-data inserts when rows empty

* Do not return generated-column-sql for redshift

* Fix snowflake-test/describe-table-test

* Fix bigquery load-tabledef when table has no rows

* Use generation_expression rather than :extra for mysql/mariadb

* Fixup driver features

* Amend pk-sync-test to verify the new :database_is_pk behaviour more explicitly as the semantic type changes

* Add sync tests for default/generated/nullable

* Formatting

* Add SQLite support for generated/nullable/default

* Add SQL-Server support for generated/nullable/default

* Only test dynamic dataset databases for now

* For druid JDBC all columns (apart from __time) are nullable

* Vertica does not support generated columns

* Starburst does not support generated columns

* Presto does not support generated columns

* Revert accidental database-required behaviour change

* Assert table synced

* Use def'd datasets rather than inline

* Oracle features

* Vertica features

* Opt starburst, presto out of defaults

* Add :test/create-table-without-data to deal with mongo

* Add some new lines to mig yml

* Add note about sync to driver test

* Do not spam logs for pk changes on upgrade

* Further logging guard refinement

* Fix migration conflicts
2025-10-21 17:59:51 +01:00
Dan Stone
c4cfe78c2c Fix devcontainer deprecated apt-keys call (#64879)
NodeSource should handle its own keys
2025-10-21 16:29:09 +01:00
github-automation-metabase
d0fff0402a Update generated docs (master) (#64858)
Co-authored-by: github-actions <github-actions@github.com>
2025-10-21 11:26:52 -04:00
Alex Yarosh
f267ce0c56 Revise impersonation permissions details (#64878)
Updated impersonation permissions documentation to clarify supported databases and row-level security for PostgreSQL.
2025-10-21 11:14:00 -04:00
Dan Stone
363ed3b959 Ensure idle_in_transaction_session_timeout is large enough during timeout test (#64866) 2025-10-21 15:53:19 +01:00
Noah Moss
b4c65c3299 [semantic search] Separate out embeddable_text from searchable_text and use labeled format for embedding (#64693)
* [Search] Separate out embeddable_text from searchable_text and use labeled format for embedding

* add embeddable_text to test data

* update mock-embeddings in tests to use new format for embeddable strings

* Fix more tests

* Fix more tests

* Fix last tests

* Fix last test

* improve comments & add a test that transform fns are not applied
2025-10-21 10:37:35 -04:00
Nemanja Glumac
195b18d690 Remove unused [ci nocache] CI option (#64852) 2025-10-21 16:36:53 +02:00
Phoomparin Mano
3a0e283b12 Move the SameSite cookie settings from interactive embedding to security tab (#64533) 2025-10-21 21:07:23 +07:00
github-automation-metabase
97c57e7bac chore(sdk): Update published npm version to 0.57.0-alpha.3 (#64870) 2025-10-21 12:43:23 +00:00
Mahatthana (Kelvin) Nomsawadi
92cea5d4f5 Fix download not getting parameters from visualized dashcards (#64754)
* Fix download not getting parameters from visualized dashcards

* Add E2E test

* Make test name clearer
2025-10-21 12:50:03 +01:00
Nemanja Glumac
dbf8855111 Ignore fn-deprecated warnings in cljs logs (#64867) 2025-10-21 13:46:49 +02:00
Kamil Mielnik
292a7c8058 Fix flaky test (#64863) 2025-10-21 11:12:32 +00:00
Dan Stone
83fdbaa65c Ensure field insertion order is consistent with :database-position (#62491)
Avoids FE ordering depending on hash iteration order on initial sync - in particular avoids
breakage in tests relying on id positionally if hashes change.
2025-10-21 09:07:58 +01:00
Mahatthana (Kelvin) Nomsawadi
0ab2b9f4f6 Fix flaky SDK tests (#64699)
* Remove double beforeEach setup probably from a mistake

* Fix the flaky test. I hope...

* Attempt to fix the test that failed the interception

* Revert change

* Fix the flake on Cypress CI
2025-10-21 04:50:17 +01:00
Timofey Kachalov
9d687287fe Fix build-e2e-matrix.unit.spec.js tests (#64851) 2025-10-20 23:51:27 +04:00
Phoomparin Mano
b5e93da266 fix(sdk-bundle, sdk-package): add missing focus color due to dark mode changes (#64641) 2025-10-21 02:15:15 +07:00
Nathan Voxland
78bf0474d6 Removed unneeded liquibase preconditions (#64694) 2025-10-20 11:11:33 -05:00
Nathan Voxland
b7bf8b6ecc Move the creation of the "card_view" tracking from the card APIs to query execution level (#64115) 2025-10-20 11:10:27 -05:00
Ngoc Khuat
65d95d9438 Polymorphic transforms (#64084) 2025-10-20 12:00:01 +00:00
Mahatthana (Kelvin) Nomsawadi
205bd075a9 Fix some events not shown on charts when grouping with different units (#64801)
* Fix some events not shown on charts when grouping with different units

* Take timezone into account

* Add tests

* Simplify return
2025-10-20 12:23:30 +01:00
Nemanja Glumac
0e8804a8cc Avoid setting up python transforms in every e2e test group (#64749) 2025-10-20 11:09:23 +00:00
Kamil Mielnik
6773707b3e Fix multiple flaky e2e tests (#64728)
* Unskip and unjail

* Modernize test

* Fix stubbing

* Remove tag

* Wait for sync to finish

* Fix flaky test

* Update test

* Unmark test as flaky

* Unmark tests as flaky

* Increase timeout

* Add const

* Fix flaky test

* Decrease flakiness

* Decrease flakiness

* Decrease flakiness

* Resync db

* Decrease flakiness

* Add a comment

* Fix flaky test

* Revert

* Out of jail

* Fix flake

* Decrease flakiness

* Try to decrease flakiness

* Revert "Try to decrease flakiness"

This reverts commit 38eadb47a3.

* Try to fix flakiness

* Fix

* Decrease flakiness

* Decrease flakiness

* Decrease flakiness

* Decrease flakiness

* Decrease flakiness

* Decrease flakiness

* Decrease flakiness

* Remove redundant blur

* Decrease flakiness

* Decrease flakiness

* Decrease flakiness

* Decrease flakiness

* Add comments
2025-10-20 16:57:52 +07:00
Uladzimir Havenchyk
3037854ee0 deps: upgrade rspack (#64800) 2025-10-20 09:53:15 +03:00
Sébastien
14b05dc189 Closes EMB-853 renamed legends get ignored by content translation (followup) (#64706)
* Closes EMB-853 for cartesian charts

* tests

* cleanup
2025-10-20 08:15:49 +02:00
Sébastien
20d149c48d Make switch to data button keyboard accessible/interactive (#64321)
* .

* fixed e2e

* toggle color
2025-10-20 08:14:58 +02:00
Nemanja Glumac
165c061afb Fix rspack alias type issue (#64770)
Co-authored-by: Uladzimir Havenchyk <125459446+uladzimirdev@users.noreply.github.com>
2025-10-18 23:53:24 +02:00
Oleksandr Yakushev
2fce0a53a6 Bump Malli to 0.19.2 (#64593) 2025-10-18 19:03:04 +00:00
Nathan Voxland
fd2c44a380 Reduce reflection overhead in search (#64785) 2025-10-17 15:18:37 -05:00
Alexander Polyankin
b86eb24b0c Fix transform e2e tests (#64805) 2025-10-17 20:50:23 +03:00
Uladzimir Havenchyk
8eb405c96b speed up fe build by upgrading svgo (#64671) 2025-10-17 20:18:59 +03:00
Braden Shepherdson
dd5117bdb1 [QP] Fix convertTimezone exprs with no src TZ and SQL source (#64710)
Closes QUE-2613.

`convertTimezone` now checks the type of the field ref, since we might not know to make the compiled
column a timezone-backed column when the previous stage is a native query.
2025-10-17 12:39:44 -04:00
Romeo Van Snick
935fe5a0e5 CodeMirror editor small fixes and dark mode updates (#64791)
* Remove double border

* Remove overflowing corners on functionbrowser

* Fix HelpText header background in dark mode

* Remove dot in customexpression editor

* Fix dark mode completions in native editor

* Move color fixes to CodeMirror component

* Move CodeMirror cursor fix in darkmode to shared CodeMirror module

* Move completion styles to shared CodeMirror component

* Enable highlighting of partials in Python completions

* Remove more shared CM code

* Fix e2e test

* Fix timout in e2e test
2025-10-17 16:38:32 +02:00
Uladzimir Havenchyk
96750294f5 deps: upgrade packages we had duplicated in bundle (#64743)
* deps: upgrade packages we had duplicated in bundle

* update imports
2025-10-17 08:24:59 +00:00
Romeo Van Snick
19a811f282 Fix timeout in e2e test (#64796) 2025-10-17 07:22:00 +00:00
Oleksandr Yakushev
0be7ef31cf [perf] Introduce lean implementations of for and doseq (#64392) 2025-10-17 09:48:39 +03:00
Braden Shepherdson
7c76029e6b [perf] Use cached MetadataProvider on FE; reuse MP in /query_metadata (#64780)
This addresses most of QUE-2686 #64774 but a second PR is required to fix a
56-specific issue that doesn't apply to `master`.

The FE was not using the new
`lib.metadata.cached-provider/cached-metadata-provider` except where
it gets added by `lib/query`. Previously, the FE constructed the
*uncached* MP once (ish) and then passed it to `lib/query` many times.
Each of those queries got its MP wrapped with `cached-metadata-provider`
but the next time the query got converted via `lib/query` its cached
values (eg. `visible-columns`, `returned-columns`) were lost.

This PR wraps the `lib.js.metadata/metadata-provider*` with
`cached-metadata-provider` from the start, so the cached values have
the same lifespan as the `MetadataProvider`, rather than each individual
query.

I also noticed that `/query_metadata` requests don't use
`lib-be.metadata.jvm/with-metadata-provider-cache`, so they end up
recreating `MetadataProvider`s for the same underlying database over and
over. That increases AppDB traffic and CPU usage to recompute
`returned-columns` etc. repeatedly. Both of those scale fast with the
complexity of the query.
2025-10-17 05:34:59 +00:00
metamben
7ee5fffead Allow both db and dbname in Redshift connection details (#64748) 2025-10-17 05:08:59 +00:00
Romeo Van Snick
7491d37214 Do not reset collection selection after canceling action (#64766)
* Do not clear selection when canceling action

* Add repro for metabase#44911
2025-10-17 10:38:25 +11:00
Oleksandr Yakushev
fc98a81852 [malli] Use optimized postwalk when calculating schema-cache-key (#64655) 2025-10-17 01:19:36 +03:00
Oleksandr Yakushev
d76377e784 Fix two backend test flakes (#64782)
* Fix extract-nested-efficient-test flake

* Fix health-check-database-test flake
2025-10-17 00:23:49 +03:00
Oleksandr Yakushev
dddf6568c1 [util] Implement Seqable for rconcat to avoid crashing CIDER (#64656) 2025-10-16 23:12:59 +03:00
Alexander Polyankin
9fd8200087 Convert DataModel queries to MBQL lib (#64633) 2025-10-16 15:16:37 +00:00
Uladzimir Havenchyk
a9c06c5ece chore: speed up frontend build with upgrade of postcss plugin (#64670)
* speed up frontend build

* fix tests

* deduplicate

* add a comment

* deduplicate
2025-10-16 14:52:00 +00:00
Uladzimir Havenchyk
0a2aa0f087 deps: move html2canvas to a separate bundle (#64708) 2025-10-16 17:02:11 +03:00
Marcos
f42ea9842a Add Marcos and Rodrigo to slack map (#64773)
* add rodrigo and marcos to github slack map

* chore: add marcos and rodrigo to github-slack-map
2025-10-16 10:33:49 -03:00
Jeff Bruemmer
448ed2d9e0 fix script link (#64767) 2025-10-16 13:47:03 +02:00
Nicolò Pretto
0bcd797755 disable excessive spam in the prs caused by sdk build (#64733)
* disable excessive spam in the prs

* to-revert: change source code to trigger the build

* test2

* :shrugs:

* Revert "to-revert: change source code to trigger the build"

This reverts commit 37f6abb085.

* clean up and comment
2025-10-16 10:22:05 +02:00
Kamil Mielnik
1a645a55d6 Fix flaky embedding-reproductions test (#64702)
* Fix flaky test

* Increase timeout

* Decrease flakiness

* Fix flaky test

* Try with cypress-iframe

* Decrease flakiness

* Pass selector arg

* Move line

* Add a wait

* Fix test

* Add comment
2025-10-16 07:28:41 +00:00
Romeo Van Snick
d1cb9336da Cancel sql transform preview (#64726)
* Allow canceling SQL transform preview

* Add repro for metabase#64474
2025-10-16 13:14:30 +11:00
John Swanson
f569537850 Fix the fixup-viz-settings hack (#64746)
This fixup broke because QP started returning the db-shaped
viz-settings (e.g. `:table.columns`) instead of the normalized
viz-settings (e.g.
`:metabase.models.visualization-settings/table-columns `) under
`[:json_query :viz-settings]`.

The existing test for this fix did not catch the regression because the
shape of viz settings was faked out for testing, and did not get
transformed like real viz settings. `{:ver 2}` stayed as `{:ver 2}`,
while `{:table.columns []}` is transformed into
`{::visualization-settings/table-columns []}`
2025-10-15 22:07:16 +00:00
John Swanson
392a3ebc48 uxw-1935: mark settings as set by env var (#64569)
A few settings weren't wrapped with `SetByEnvVarWrapper`, so weren't
marked as un-modifiable.
2025-10-15 09:00:37 -07:00
Alexander Polyankin
9e401daa2e Ignore BE exception when checking dependencies (#64716) 2025-10-15 11:36:54 -04:00
Kamil Mielnik
f67961423a Fix flaky documents test (#64711)
* Use H.visitDocument

* Revert

* Decrease flakiness

* Fix chaining

* Revert

* Remove redundant within

* Fix
2025-10-15 17:06:03 +07:00
Kamil Mielnik
a4564a2e12 Unskip and update calendar test + fix date range picker text inputs not in sync with calendar inputs (#64603)
* Fix date range picker text inputs not in sync with calendar inputs (#64602)

* Unskip and update test

* Add repro for #64602

* Add unit tests

* Add issue tags

* Rename date to displayedDate
2025-10-15 05:49:47 +00:00
Alexander Polyankin
0cf0d86421 Deprecate fields in Question.create that are used to manipulate raw MBQL (#64715) 2025-10-15 02:20:50 +00:00
Alexander Polyankin
309e69774e Fix caching with drills (#64723) 2025-10-14 21:49:55 -04:00
Alexander Polyankin
5a880ebfb8 Use MBQL lib for table editing (#64722) 2025-10-14 20:50:33 -04:00
Nemanja Glumac
645543ff3e Remove deprecated radio form (#64679)
* Update the last instance of deprecated `FormRadioWidget`

This commit replaces a deprecated `FormRadioWidget` with the
`FormRadioGroup` component (which is a light wrapper around
the plain Radio.Group from Mantine).

* Remove the deprecated `FormRadio` component
2025-10-15 00:05:35 +02:00
Uladzimir Havenchyk
4b1ee493db chore: use standard colors for skeleton (#64588) 2025-10-14 19:36:38 +00:00
Alex Yarosh
db08e23530 docs: new place for alerts (#64688)
* Revise alert creation instructions in documentation

Updated instructions for creating alerts, including clearer steps and options for different alert types. Adjusted formatting for consistency and added details on editing and managing alerts.

* Enhance clarity in delete and restore documentation

Updated the documentation for deleting and restoring items to clarify the impact on related content and improve phrasing.

* Apply suggestions from code review

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>

---------

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2025-10-14 16:45:49 +00:00
Jeff Bruemmer
d5131a98f6 Update iframe resizer script source in documentation (#64718) 2025-10-14 15:46:28 +00:00
Brad Anderson
4f99d70ece UXW-88 Fixed issue where Show values for this series switch is hidden because of the default value for show_stack_values (#64691) 2025-10-14 11:24:04 -04:00
Nick Fitzpatrick
ed772da268 Dark mode Day 2 patches (#64549)
* lots of small fixes

* removing debug code

* adjusting e2e

* small adjustments

* whoops
2025-10-14 15:56:25 +02:00
Kamil Mielnik
1d88be2135 Refactor - Organize TablePicker (#64617)
* Move EmptyState, Search, and Tree to separate files

* Move hooks and constants out of utils

* Move components to a separate directory

* Fix import
2025-10-14 13:42:53 +00:00
Kamil Mielnik
d825953952 Fix flaky tests (#64700) 2025-10-14 17:31:52 +07:00
Kamil Mielnik
bf5799df15 UXW-311 [Sheets] Clicking notification should refresh the page (#64614)
* Fix UXW-311

* Add unit test

* Add tag
2025-10-14 09:23:23 +00:00
Romeo Van Snick
4bc3b6484b Ban certain imports in Python script 2025-10-13 17:02:06 +11:00
Romeo Van Snick
ee29d769a0 Add more tests for backend test runner 2025-10-10 14:25:02 +11:00
Romeo Van Snick
013974b705 Improve python runner mode switch 2025-10-10 13:53:51 +11:00
Romeo Van Snick
202290121b Remove unused helper 2025-10-09 16:08:02 +11:00
Romeo Van Snick
5766d22bce Fix flaky test 2025-10-09 15:59:46 +11:00
Romeo Van Snick
7b500427ec Increase timeout for python runner 2025-10-09 15:47:00 +11:00
Romeo Van Snick
d0a36c3d7c Fix misplaced docstring 2025-10-09 14:56:32 +11:00
Romeo Van Snick
ef7ee34349 Add UI to switch between browser runner and api runnner 2025-10-09 14:55:27 +11:00
Romeo Van Snick
24d6fc3d7d WIP 2025-10-09 14:37:27 +11:00
Romeo Van Snick
e00705930f Update python transform endpoint 2025-10-09 14:34:44 +11:00
Romeo Van Snick
a85b69ce0d Adjust pyodide worker types to align with test endpoint 2025-10-09 14:33:20 +11:00
Romeo Van Snick
dff77917f4 Remove blob: for worker-src 2025-10-09 13:17:38 +11:00
Romeo Van Snick
c25d90382f Fix metababot broken code 2025-10-09 13:16:46 +11:00
Romeo Van Snick
42d8c14a8e Improve comments 2025-10-09 13:14:45 +11:00
Romeo Van Snick
6b37f5f3af Add more documentation on the worker pool 2025-10-09 13:13:54 +11:00
Romeo Van Snick
809503986a Only unsubscribe when message is handled 2025-10-09 13:10:13 +11:00
Romeo Van Snick
b551d305fc Remove any 2025-10-09 13:08:59 +11:00
Romeo Van Snick
b24f87f5d1 Remove todo 2025-10-09 13:08:38 +11:00
Romeo Van Snick
9c95e9b8a7 Add comment to proxy route 2025-10-09 13:06:59 +11:00
Romeo Van Snick
8e8480fc95 Only add querystring when it exists
Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>
2025-10-09 13:04:29 +11:00
Romeo Van Snick
abf5f8caa8 Top-level comments should have three semicolons
Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>
2025-10-09 13:00:52 +11:00
Romeo Van Snick
d13f7355c5 Decompress archive 2025-10-09 12:49:19 +11:00
Romeo Van Snick
e560d95105 Fix typo 2025-10-09 12:48:36 +11:00
Romeo Van Snick
e7828cc2f8 Remove redundant declare 2025-10-09 12:48:09 +11:00
Romeo Van Snick
0af03be7cc Merge branch 'master' into nmezzopera/test-pyodie
# Conflicts:
#	enterprise/frontend/src/metabase-enterprise/transforms-python/components/PythonTransformEditor/PythonEditorResults/PythonEditorResults.module.css
2025-10-09 12:31:14 +11:00
Romeo Van Snick
26915a1feb Remove log 2025-10-09 12:30:03 +11:00
Romeo Van Snick
8fcd5d3839 Do not store pyodide packages in git 2025-10-09 12:28:29 +11:00
Romeo Van Snick
39cefbab7f Revert "Remove pyodide from github repo"
This reverts commit 95bb56b5e8.
2025-10-08 23:11:00 +11:00
Romeo Van Snick
e002ff8980 Revert "Ignore code issues in vendored library"
This reverts commit 3606567fc8.
2025-10-08 23:10:04 +11:00
Romeo Van Snick
95bb56b5e8 Remove pyodide from github repo 2025-10-08 22:50:35 +11:00
Romeo Van Snick
1e03d56dac Install pyodide on install 2025-10-08 22:49:38 +11:00
Romeo Van Snick
a5d21e9623 Add script to download pyodide's distro 2025-10-08 22:49:27 +11:00
Romeo Van Snick
3606567fc8 Ignore code issues in vendored library 2025-10-08 21:12:10 +11:00
Romeo Van Snick
a3b380ca00 Remove template string quotes 2025-10-08 20:57:55 +11:00
Romeo Van Snick
59ec9091d8 Increase ready timout 2025-10-08 20:57:36 +11:00
Romeo Van Snick
158ce159f7 Add mock for PyodideWorkerManager 2025-10-08 15:52:25 +11:00
Romeo Van Snick
a6a737b33b Handle app/dist when not in dev mode 2025-10-08 13:09:57 +11:00
Romeo Van Snick
af75705b3c Remove unused argument 2025-10-08 13:05:41 +11:00
Romeo Van Snick
f904f950ba Rename variable to be clearer 2025-10-08 11:12:49 +11:00
Romeo Van Snick
64a8ec3593 Add search params to request 2025-10-08 10:47:43 +11:00
Romeo Van Snick
39e2e551dc Simplify worker loops 2025-10-07 17:02:26 +11:00
Romeo Van Snick
7606803604 Add termination better 2025-10-07 16:30:53 +11:00
Romeo Van Snick
7fd1c79dad Ignore results for aborted runs 2025-10-07 16:04:04 +11:00
Romeo Van Snick
1a7017612c Use types from pyodide 2025-10-07 15:41:05 +11:00
Romeo Van Snick
4420d0c963 Add pyodide 2025-10-07 15:28:16 +11:00
Romeo Van Snick
3a00a330bc Handle errored out workers 2025-10-07 15:21:56 +11:00
Romeo Van Snick
22211b18e8 Fix types 2025-10-07 15:10:14 +11:00
Romeo Van Snick
bc5bcff995 Improve waitFor error handling 2025-10-07 15:05:51 +11:00
Romeo Van Snick
27456e9669 Split up code further 2025-10-07 14:42:30 +11:00
Romeo Van Snick
13854b5c49 Work of shared types for Worker and Manager 2025-10-07 14:35:36 +11:00
Romeo Van Snick
143ed4974c Simplify packages 2025-10-07 14:20:37 +11:00
Romeo Van Snick
bca7756059 Move pyodide worker into a separate folder 2025-10-07 14:18:49 +11:00
Romeo Van Snick
186aa9e644 Add types to Pyodide worker 2025-10-07 10:19:48 +11:00
Romeo Van Snick
1c92dfb462 Proxy webpack dev server 2025-10-07 10:13:18 +11:00
Romeo Van Snick
9cae2a5080 Use worker in webpack 2025-10-07 10:13:18 +11:00
Romeo Van Snick
127b23d986 Add e2e test for Python runner 2025-10-06 19:49:00 +11:00
Romeo Van Snick
62917d13bc Handle python shared libraries 2025-10-03 18:12:49 +10:00
Romeo Van Snick
47720ac7dc Allow adding custom libraries to Pyodide 2025-10-03 17:59:51 +10:00
Romeo Van Snick
003c9e63b3 Remove Pyodide status indicator 2025-10-03 17:57:56 +10:00
Romeo Van Snick
5c9d18b96a Render error traceback in a more readable way 2025-10-03 17:48:42 +10:00
Romeo Van Snick
054c0477c0 Remove DataFetcher 2025-10-03 17:43:08 +10:00
Romeo Van Snick
c8da77672c Remove any 2025-10-03 17:41:41 +10:00
Romeo Van Snick
7360cd88b6 Remove pyodide dependency 2025-10-03 17:38:53 +10:00
Romeo Van Snick
55c789fa26 Remove downlaod script for pyodide 2025-10-03 17:34:36 +10:00
Romeo Van Snick
a93959a4c5 Pass args as kwargs and wrap them in a dataframe 2025-10-03 17:33:52 +10:00
Romeo Van Snick
0e1bfe79f2 Add helper to fetch sample data and use that instead of the service 2025-10-03 17:26:27 +10:00
Romeo Van Snick
1efe3a5675 Move transform related wrapper out of python worker pool 2025-10-03 17:04:41 +10:00
Romeo Van Snick
6ecbad3323 Move Python transform test to hooks 2025-10-03 16:58:17 +10:00
Romeo Van Snick
8ece3416e3 Handle abortion properly 2025-10-03 16:54:35 +10:00
Romeo Van Snick
c360c2f457 Add useRunPython hook and use that in the test python hook 2025-10-03 16:51:45 +10:00
Romeo Van Snick
63b43a98d5 Improve python script by wrapping columns in JSON 2025-10-03 16:11:10 +10:00
Romeo Van Snick
d4f385694f Handle newlines in stdout/stderr 2025-10-03 16:02:40 +10:00
Romeo Van Snick
a3d7c7e9f3 Handle errors in script 2025-10-03 15:53:30 +10:00
Romeo Van Snick
96ab264d7a Pick worker that is ready in pool 2025-10-03 13:38:49 +10:00
Romeo Van Snick
59ebd75cec Remove unused imports 2025-10-03 13:28:04 +10:00
Romeo Van Snick
1ff9264e4c Disable undefined variable lint 2025-10-03 09:58:57 +10:00
Romeo Van Snick
692acf2531 Rename manager to pool 2025-10-03 09:56:39 +10:00
Romeo Van Snick
e0d12b32e4 Make packages configurable for the worker 2025-10-03 09:55:21 +10:00
Romeo Van Snick
b47e6f4313 Import packages when initializing 2025-10-03 09:47:17 +10:00
Romeo Van Snick
bdd9dccdc9 Do not include micropip 2025-10-02 22:55:10 +10:00
Romeo Van Snick
35d5f824f9 Remove unused context 2025-10-02 22:54:44 +10:00
Romeo Van Snick
c99b613fb3 Add cancellation to pyodide worker 2025-10-02 22:54:44 +10:00
Romeo Van Snick
5fc1f7309f Distinguish worker and workermanager 2025-10-02 22:54:44 +10:00
Romeo Van Snick
b02eb58a79 Remove initialize step altogether 2025-10-02 22:31:51 +10:00
Romeo Van Snick
337f5bb867 Automatically terminate worker after run 2025-10-02 22:21:40 +10:00
Romeo Van Snick
958390151e Handle errors in the worker 2025-10-02 22:20:08 +10:00
Romeo Van Snick
09377ed5e9 Remove crazy serialization code 2025-10-02 22:15:48 +10:00
Romeo Van Snick
8334d3d91b Simplify worker flow 2025-10-02 22:06:49 +10:00
Romeo Van Snick
66f7eb7039 Wrap case in block 2025-10-02 18:55:14 +10:00
Romeo Van Snick
d228328a29 Load packages on initialization 2025-10-02 18:47:10 +10:00
Romeo Van Snick
cd8d1a8348 Remove unused loadPackages handler 2025-10-02 18:38:24 +10:00
Romeo Van Snick
0c0b1f7a4b Clear globals 2025-10-02 18:36:16 +10:00
Romeo Van Snick
4e168d7e8c Use pyodide builtins to capture stdout/stderr 2025-10-02 18:36:03 +10:00
Romeo Van Snick
8b92275ceb Enable Python debugger by default 2025-10-02 17:09:20 +10:00
Romeo Van Snick
9f04f3ce31 Remove rspack changes 2025-10-02 17:05:17 +10:00
Romeo Van Snick
3ce8af616d Remove unused @pyodide/webpack-plugin 2025-10-02 17:04:47 +10:00
Romeo Van Snick
577aa9ee51 Format worker 2025-10-02 16:52:44 +10:00
Romeo Van Snick
5b9d0ce9fd Format table values 2025-10-02 14:30:18 +10:00
Romeo Van Snick
e800c0673d Improve error / output renderer 2025-10-02 14:18:59 +10:00
Nicolo-Maria
5a7469143b poc: pyodie test mode 2025-10-01 12:31:22 +02:00
1344 changed files with 44100 additions and 13066 deletions

View File

@@ -25,6 +25,7 @@
:reduce-without-init {:level :warning}
:redundant-call {:level :warning}
:redundant-fn-wrapper {:level :warning}
:redundant-str-call {:level :warning}
:self-requiring-namespace {:level :warning}
:single-key-in {:level :warning}
:unsorted-imports {:level :warning}
@@ -489,6 +490,8 @@
metabase.util.malli/defn- schema.core/defn
metabase.util.malli/fn schema.core/fn
metabase.util.namespaces/import-fns potemkin/import-vars
metabase.util.performance/doseq clojure.core/doseq
metabase.util.performance/for clojure.core/for
metabase.util/with-timer-ms clojure.core/fn
metabuild-common.core/with-open-jar-file-system clojure.core/let
metabuild-common.files/with-open-jar-file-system clojure.core/let
@@ -519,6 +522,7 @@
metabase-enterprise.advanced-permissions.models.permissions.application-permissions-test/with-new-group-and-current-graph hooks.common/with-two-top-level-bindings
metabase-enterprise.audit-app.pages-test/with-temp-objects hooks.common/with-one-binding
metabase-enterprise.cache.config-test/with-temp-persist-models hooks.common/with-seven-bindings
metabase-enterprise.metabot-v3.tools.dependencies-test/with-dependent-transforms! hooks.common/with-two-bindings
metabase-enterprise.semantic-search.db.connection/with-migrate-tx hooks.common/let-one-with-optional-value
metabase-enterprise.serialization.test-util/with-temp-dpc hooks.toucan2.tools.with-temp/with-temp
metabase-enterprise.transforms-python.drivers-test/with-test-table hooks.common/with-two-bindings
@@ -715,6 +719,8 @@
:name metabase-lib}
{:pattern "^metabase\\.lib\\..*"
:name metabase-lib-excluding-legacy-mbql}
{:pattern "^metabase\\.legacy-mbql\\..*"
:name legacy-mbql-namespaces}
;;
;; QP and driver source namespaces: `metabase.query-processor.*`, `metabase-enterprise.sandbox.query-processor.*`,
;; and `metabase.driver.*`, excluding `-test` namespaces.
@@ -729,7 +735,7 @@
;;
;; driver namespaces, including tests
;;
{:pattern "metabase\\.driver.*$"
{:pattern "metabase\\.driver(?:-api)?.*$"
:name driver-namespaces}
;;
;; Perf-sensitive namespaces are currently the union of metabase.lib.*, driver namespaces, and QP (without tests).
@@ -775,7 +781,14 @@
clojure.core/eval {:message "Don't use eval outside of tests"}}
:discouraged-namespace
{metabase.query-processor.store {:message "Please do not use the QP Store outside of legacy QP or driver code. Use MBQL 5/Lib or lib.metadata.jvm/applicaton-database-metadata-provider instead."}}}}
{metabase.legacy-mbql.jvm-util {:message "Avoid legacy MBQL utils, use Lib instead"}
metabase.legacy-mbql.normalize {:message "Avoid legacy MBQL normalization, use MBQL 5 + lib/normalize instead"}
metabase.legacy-mbql.predicates {:message "Avoid legacy MBQL utils, use Lib instead"}
metabase.legacy-mbql.schema {:message "Avoid the legacy MBQL schema, use MBQL 5 + lib.schema instead"}
metabase.legacy-mbql.schema.helpers {:message "Avoid the legacy MBQL schema, use MBQL 5 + lib.schema instead"}
metabase.legacy-mbql.schema.macros {:message "Avoid the legacy MBQL schema, use MBQL 5 + lib.schema instead"}
metabase.legacy-mbql.util {:message "Avoid legacy MBQL utils, use Lib instead"}
metabase.query-processor.store {:message "Please do not use the QP Store outside of legacy QP or driver code. Use MBQL 5/Lib or lib.metadata.jvm/applicaton-database-metadata-provider instead."}}}}
printable-namespaces
{:linters
@@ -817,20 +830,70 @@
toucan2.core {:message "Don't use application database inside Lib code"}}}}
metabase-lib-excluding-legacy-mbql
{:linters
{:discouraged-var
{metabase.legacy-mbql.util/unique-name-generator {:message "Use metabase.lib.util/unique-name-generator or non-truncating-unique-name-generator"}}}
{}
:discouraged-namespace
{metabase.legacy-mbql.js {:message "Avoid legacy MBQL utils in Lib; move things into Lib if needded."}
metabase.legacy-mbql.jvm-util {:message "Avoid legacy MBQL utils in Lib; move things into Lib if needded."}
metabase.legacy-mbql.predicates {:message "Avoid legacy MBQL utils in Lib; move things into Lib if needded."}
metabase.legacy-mbql.util {:message "Avoid legacy MBQL utils in Lib; move things into Lib if needded."}}}
legacy-mbql-namespaces
{:linters
{:discouraged-namespace
{metabase.legacy-mbql.jvm-util {:level :off}
metabase.legacy-mbql.normalize {:level :off}
metabase.legacy-mbql.predicates {:level :off}
metabase.legacy-mbql.schema {:level :off}
metabase.legacy-mbql.schema.helpers {:level :off}
metabase.legacy-mbql.schema.macros {:level :off}
metabase.legacy-mbql.util {:level :off}
metabase.query-processor.store {:level :off}}
;; the `metabase.legacy-mbql` stuff is all deprecated, so we don't need to warn inside the module about other stuff
;; in the module being marked deprecated or discouraged.
:deprecated-namespace {:level :off}
:deprecated-var {:level :off}}}
driver-namespaces
{:linters
{:discouraged-var
{metabase.driver/database-supports? {:level :off}}}}
{metabase.driver/database-supports? {:level :off}}
;; don't warn about the legacy MBQL namespaces being deprecated or discouraged in driver code now, we don't have a
;; real alternative YET so it's not a helpful warning.
:discouraged-namespace
{metabase.legacy-mbql.jvm-util {:level :off}
metabase.legacy-mbql.normalize {:level :off}
metabase.legacy-mbql.predicates {:level :off}
metabase.legacy-mbql.schema {:level :off}
metabase.legacy-mbql.schema.helpers {:level :off}
metabase.legacy-mbql.schema.macros {:level :off}
metabase.legacy-mbql.util {:level :off}
metabase.query-processor.store {:level :off}}
:deprecated-namespace
{:exclude
[metabase.driver.common.parameters
metabase.driver.common.parameters.dates
metabase.driver.common.parameters.operators
metabase.driver.common.parameters.parse
metabase.driver.common.parameters.values
metabase.legacy-mbql.jvm-util
metabase.legacy-mbql.normalize
metabase.legacy-mbql.predicates
metabase.legacy-mbql.schema
metabase.legacy-mbql.schema.helpers
metabase.legacy-mbql.schema.macros
metabase.legacy-mbql.util
metabase.query-processor.store]}
:deprecated-var
{:exclude
{metabase.legacy-mbql.schema.helpers/is-clause? {:namespaces ["metabase\\.driver.*"]}
metabase.legacy-mbql.schema.helpers/mbql-clause? {:namespaces ["metabase\\.driver.*"]}
metabase.legacy-mbql.util/query->source-table-id {:namespaces ["metabase\\.driver.*"]}
metabase.legacy-mbql.util/aggregation-at-index {:namespaces ["metabase\\.driver.*"]}
metabase.legacy-mbql.util/assoc-field-options {:namespaces ["metabase\\.driver.*"]}
metabase.legacy-mbql.util/expression-with-name {:namespaces ["metabase\\.driver.*"]}
metabase.legacy-mbql.util/field-options {:namespaces ["metabase\\.driver.*"]}
metabase.legacy-mbql.util/negate-filter-clause {:namespaces ["metabase\\.driver.*"]}
metabase.legacy-mbql.util/normalize-token {:namespaces ["metabase\\.driver.*"]}
metabase.legacy-mbql.util/update-field-options {:namespaces ["metabase\\.driver.*"]}}}}}
performance-sensitive
{:linters
@@ -865,16 +928,7 @@
metabase.lib.core/->legacy-MBQL {:level :off}}}}
qp-source-namespaces
{:linters
{:discouraged-namespace
{metabase.legacy-mbql.js {:message "Avoid legacy MBQL namespaces in the QP, use Lib instead"}
metabase.legacy-mbql.jvm-util {:message "Avoid legacy MBQL namespaces in the QP, use Lib instead"}
metabase.legacy-mbql.normalize {:message "Avoid legacy MBQL namespaces in the QP, use Lib instead"}
metabase.legacy-mbql.predicates {:message "Avoid legacy MBQL namespaces in the QP, use Lib instead"}
metabase.legacy-mbql.schema {:message "Avoid legacy MBQL namespaces in the QP, use Lib instead"}
metabase.legacy-mbql.schema.helpers {:message "Avoid legacy MBQL namespaces in the QP, use Lib instead"}
metabase.legacy-mbql.schema.macros {:message "Avoid legacy MBQL namespaces in the QP, use Lib instead"}
metabase.legacy-mbql.util {:message "Avoid legacy MBQL namespaces in the QP, use Lib instead"}}}}
{}
general-qp-and-driver-test-namespaces
{:linters

View File

@@ -119,9 +119,9 @@
metabase.analyze.query-results}
:uses #{config
driver
legacy-mbql
lib
models
query-processor
sync
util}}
@@ -329,6 +329,7 @@
collections
{:team "UX West"
:api #{metabase.collections.api
metabase.collections.core
metabase.collections.models.collection
metabase.collections.models.collection.root}
:uses #{api
@@ -344,6 +345,7 @@
permissions
premium-features
queries
remote-sync
request
revisions
search
@@ -594,7 +596,6 @@
metabase.legacy-mbql.schema
metabase.legacy-mbql.util}
:uses #{lib
models
types
util}}
@@ -621,6 +622,7 @@
metabase.lib.query
metabase.lib.schema
metabase.lib.schema.actions
metabase.lib.schema.aggregation
metabase.lib.schema.binning
metabase.lib.schema.common
metabase.lib.schema.constraints
@@ -709,8 +711,7 @@
models
{:team "DevEx"
:api #{metabase.models.dispatch
metabase.models.humanization
:api #{metabase.models.humanization
metabase.models.init
metabase.models.interface
metabase.models.resolution
@@ -783,7 +784,6 @@
:uses #{api
app-db
classloader
legacy-mbql
lib
lib-be
models
@@ -806,6 +806,7 @@
lib
models
premium-features
remote-sync
request
settings
util
@@ -847,7 +848,6 @@
app-db
channel
config
driver
premium-features
settings
task
@@ -921,7 +921,6 @@
eid-translation
embedding
events
legacy-mbql
lib
lib-be
models
@@ -1020,6 +1019,14 @@
users
util}}
remote-sync
{:team "UX West"
:api #{metabase.remote-sync.core
metabase.remote-sync.init}
:uses #{api
models
premium-features}}
request
{:team "UX West"
:api #{metabase.request.core
@@ -1098,7 +1105,8 @@
segments
{:team "Querying"
:api #{metabase.segments.api}
:api #{metabase.segments.api
metabase.segments.schema}
:uses #{api
events
legacy-mbql
@@ -1147,7 +1155,6 @@
app-db
channel
config
driver
events
login-history
request
@@ -1303,6 +1310,8 @@
:uses #{analytics
api
collections
config
events
models
util}}
@@ -1320,10 +1329,8 @@
:uses #{analytics
api
appearance
collections
driver
events
legacy-mbql
lib
model-persistence
models
@@ -1490,6 +1497,7 @@
queries
query-permissions
query-processor
segments
settings
util
warehouse-schema}}
@@ -1710,7 +1718,7 @@
enterprise/dependencies
{:team "Querying"
:api #{metabase-enterprise.dependencies.api
#_metabase-enterprise.dependencies.core
metabase-enterprise.dependencies.core
metabase-enterprise.dependencies.init}
:uses #{analyze
api
@@ -1726,15 +1734,18 @@
premium-features
queries
query-processor
revisions
settings
task
util}}
util
enterprise/documents}}
enterprise/documents
{:team "UX West"
:api #{metabase-enterprise.documents.api
metabase-enterprise.documents.core
metabase-enterprise.documents.init}
metabase-enterprise.documents.init
metabase-enterprise.documents.prose-mirror}
:uses #{activity-feed
api
app-db
@@ -1838,6 +1849,7 @@
lib
lib-be
models
native-query-snippets
permissions
premium-features
pulse
@@ -1854,7 +1866,10 @@
util
warehouse-schema
warehouses
enterprise/documents}}
enterprise/dependencies
enterprise/documents
enterprise/transforms
enterprise/transforms-python}}
enterprise/permission-debug
{:team "UX West"
@@ -1872,6 +1887,24 @@
:uses #{premium-features
util}}
enterprise/remote-sync
{:team "UX West"
:api #{metabase-enterprise.remote-sync.api
metabase-enterprise.remote-sync.core
metabase-enterprise.remote-sync.init}
:uses #{analytics
api
app-db
collections
events
models
premium-features
settings
startup
task
util
enterprise/serialization}}
enterprise/sandbox
{:team "UX West"
:api #{metabase-enterprise.sandbox.api.routes
@@ -1880,6 +1913,7 @@
app-db
audit-app
driver
events
legacy-mbql
lib
models
@@ -1941,6 +1975,7 @@
{:team "Workflows"
:api #{metabase-enterprise.serialization.api
metabase-enterprise.serialization.cmd
metabase-enterprise.serialization.core
metabase-enterprise.serialization.v2.backfill-ids}
:uses #{analytics
api
@@ -2004,6 +2039,7 @@
metabase-enterprise.transforms.core
metabase-enterprise.transforms.init
metabase-enterprise.transforms.instrumentation
metabase-enterprise.transforms.interface
metabase-enterprise.transforms.util}
:uses #{analytics
api
@@ -2014,21 +2050,22 @@
lib-be
models
premium-features
queries
query-processor
request
search
settings
sync
task
task-history
util
enterprise/transforms-python}}
util}}
enterprise/transforms-python
{:team "Querying"
:api #{metabase-enterprise.transforms-python.api
metabase-enterprise.transforms-python.execute
metabase-enterprise.transforms-python.init}
:uses #{api
:uses #{analytics
api
app-db
config
driver

View File

@@ -4,7 +4,6 @@ FROM mcr.microsoft.com/vscode/devcontainers/java:21
RUN ( curl -fsSL https://deb.nodesource.com/setup_22.x | bash ) \
&& export DEBIAN_FRONTEND=noninteractive \
&& apt-key adv --refresh-keys --keyserver keyserver.ubuntu.com \
&& apt-get update && apt-get -y install --no-install-recommends nodejs yarn rlwrap fontconfig
# install Clojure

View File

@@ -1,5 +1,4 @@
.babel_cache
docs/*
target/*
.circleci
.cpcache

View File

@@ -136,7 +136,7 @@ module.exports = {
},
env: {
browser: true,
es6: true,
es2020: true,
commonjs: true,
jest: true,
"jest/globals": true,
@@ -203,6 +203,7 @@ module.exports = {
"frontend/src/metabase/admin/**/*",
"frontend/src/metabase/setup/**/*",
"enterprise/frontend/src/metabase-enterprise/whitelabel/**/*",
"enterprise/frontend/src/metabase-enterprise/embedding/**/*",
"frontend/lint/**/*",
"*.stories.*",
"**/.storybook/*",

View File

@@ -17,8 +17,6 @@ runs:
- name: Prepare backend environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: cross-branch-migrations
- name: Run backend on base branch
run: |

View File

@@ -0,0 +1,27 @@
name: Get cache keys
description: |
Get deterministic cache keys for Maven and Node.js caches based on the centrally controlled cache prefix,
and the suffix based on the runner OS and the current week of the year.
outputs:
m2-cache-key:
description: "The cache key for the Maven cache."
value: ${{ steps.keys-factory.outputs.m2-cache-key }}
node-cache-key:
description: "The cache key for the Node.js cache."
value: ${{ steps.keys-factory.outputs.node-cache-key }}
runs:
using: "composite"
steps:
- name: Generate and output cache keys
id: keys-factory
run: |
M2_CACHE_PREFIX='M2'
NODE_CACHE_PREFIX='node-modules'
WEEK_OF_YEAR=$(/bin/date "+%G-%V")
CACHE_SUFFIX="${{ runner.os }}-$WEEK_OF_YEAR"
echo "m2-cache-key=$M2_CACHE_PREFIX-$CACHE_SUFFIX" >> $GITHUB_OUTPUT
echo "node-cache-key=$NODE_CACHE_PREFIX-$CACHE_SUFFIX" >> $GITHUB_OUTPUT
shell: bash

View File

@@ -1,7 +1,7 @@
name: Prepare back-end environment
description: |
Prepare the backend. Installs jdk, Clojure, and fetches the cache for m2. The CI config fetchs `ci-test-config.json`
from master and lets us ignore tests at the var level if they are flaking.
Prepare the backend. Installs jdk, Clojure, and fetches the cache for m2.
The CI config fetches `ci-test-config.json` from master and lets us ignore tests at the var level if they are flaking.
inputs:
java-version:
required: true
@@ -9,10 +9,6 @@ inputs:
clojure-version:
required: true
default: '1.12.0.1488'
m2-cache-key:
description: 'Key to cache M2 packages from Maven Central'
required: true
default: 'm2'
runs:
using: "composite"
@@ -28,21 +24,20 @@ runs:
run: |
curl -O https://download.clojure.org/install/linux-install-${{ inputs.clojure-version }}.sh &&
sudo bash ./linux-install-${{ inputs.clojure-version }}.sh
- name: Fetch CI config
shell: bash
run: |
curl -o ci-test-config.json https://raw.githubusercontent.com/metabase/metabase/refs/heads/master/ci-test-config.json
- name: Check to see if dependencies should be cached
if: ${{ contains(github.event.head_commit.message, '[ci nocache]') }}
run: echo "Commit message includes [ci nocache]; dependencies will NOT be cached"
shell: bash
- name: Get M2 cache
uses: actions/cache@v4
if: ${{ !contains(github.event.head_commit.message, '[ci nocache]') }}
- name: Get M2 cache key
uses: ./.github/actions/get-cache-keys
id: get-cache-keys
- name: Restore M2 cache
uses: actions/cache/restore@v4
with:
path: |
~/.m2
~/.gitlibs
key: ${{ runner.os }}-${{ inputs.m2-cache-key }}-${{ hashFiles('**/deps.edn') }}
restore-keys: |
${{ runner.os }}-${{ inputs.m2-cache-key }}-
key: ${{ steps.get-cache-keys.outputs.m2-cache-key }}

View File

@@ -22,16 +22,16 @@ runs:
chrome-version: 1097615
id: setup-chrome
- name: Check to see if dependencies should be cached
if: ${{ contains(github.event.head_commit.message, '[ci nocache]') }}
run: echo "Commit message includes [ci nocache]; dependencies will NOT be cached"
- name: Get current week of year
id: get-date
run: |
echo "week-of-year=$(/bin/date "+%G-%V")" >> $GITHUB_OUTPUT
shell: bash
- name: Get Cypress cache
uses: actions/cache@v4
if: ${{ !contains(github.event.head_commit.message, '[ci nocache]') }}
with:
path: ~/.cache/Cypress
key: ${{ runner.os }}-Cypress-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-Cypress-${{ steps.get-date.outputs.week-of-year }}
- name: Ensure that Cypress executable is ready
run: |
yarn cypress install

View File

@@ -3,6 +3,10 @@ inputs:
node-version:
description: "The version of Node.js to use, overriding .nvmrc"
required: false
apply-patches:
description: "Whether to patch frontend dependencies with patch-package."
required: true
default: 'true'
runs:
using: "composite"
steps:
@@ -12,26 +16,32 @@ runs:
node-version: ${{ inputs.node-version }} # this overrides, if present
node-version-file: ".nvmrc"
- name: Check to see if dependencies should be cached
if: ${{ contains(github.event.head_commit.message, '[ci nocache]') }}
run: |
echo "Commit message includes [ci nocache]; dependencies will NOT be cached"
yarn cache clean
shell: bash
- name: Get M2 cache
uses: actions/cache@v4
if: ${{ !contains(github.event.head_commit.message, '[ci nocache]') }}
with:
path: ~/.m2
key: ${{ runner.os }}-cljs-${{ hashFiles('**/shadow-cljs.edn') }}
- name: Get cache keys
uses: ./.github/actions/get-cache-keys
id: get-cache-keys
- name: Get node_modules cache
uses: actions/cache@v4
- name: Restore M2 cache
uses: actions/cache/restore@v4
with:
path: |
~/.m2
~/.gitlibs
key: ${{ steps.get-cache-keys.outputs.m2-cache-key }}
- name: Restore node_modules cache
uses: actions/cache/restore@v4
id: node-modules-cache
if: ${{ !contains(github.event.head_commit.message, '[ci nocache]') }}
with:
path: node_modules
key: ${{ runner.os }}-node-modules-${{ hashFiles('**/yarn.lock', '**/patches/*.patch') }}
key: ${{ steps.get-cache-keys.outputs.node-cache-key }}
- run: yarn install --frozen-lockfile --prefer-offline
# postinstall lifecycle hook can be dangerous in CI so we only run it locally (see package.json)
# If a job wants to patch packages, it does so explicitly in the CI. This setting is opt-out.
# For example, we never want to cache node_modules with patches already applied so cache-generator.yml skips that step.
- name: Clean install
run: yarn install --frozen-lockfile --prefer-offline
shell: bash
- name: Patch frontend dependencies
if: inputs.apply-patches == 'true'
run: yarn patch-package
shell: bash

View File

@@ -7,8 +7,6 @@ runs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Compile CLJS
run: yarn build-pure:cljs

View File

@@ -15,8 +15,6 @@ runs:
steps:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: driver
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
if: ${{ inputs.build-static-viz == 'true' }}

41
.github/actions/update-cache/action.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Update cache
description: |
Update a GitHub Actions cache based on a provided path and key.
If a cache entry already exists for the given key, it is first removed.
This ensures immutability of cache entries, and prevents runtime errors.
inputs:
path:
description: "The path(s) to cache, separated by newlines."
required: true
key:
description: "The cache key to use."
required: true
runs:
using: "composite"
steps:
- name: Check if the cache entry exists
id: cache-lookup
uses: actions/cache/restore@v4
with:
path: ${{ inputs.path }}
key: ${{ inputs.key }}
lookup-only: true # Important bit: the action will not fetch anything, just check for the cache existence.
- name: Delete the cache entry if it exists
if: ${{ steps.cache-lookup.outputs.cache-hit == 'true' }}
run: |
echo "Cache entry found for key '${{ inputs.key }}'. Deleting it to ensure immutability."
gh api \
--method DELETE \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/${{ github.repository }}/actions/caches?key=${{ inputs.key }}
env:
GH_TOKEN: ${{ github.token }}
shell: bash
- name: Save the new cache entry
uses: actions/cache/save@v4
with:
path: ${{ inputs.path }}
key: ${{ inputs.key }}

View File

@@ -55,4 +55,3 @@ runs:
variant: ${{ inputs.variant || inputs.output-name }}
org-slug: metabase
token: ${{ inputs.trunk-api-token }}
continue-on-error: true

View File

@@ -18,6 +18,7 @@ const specialTestConfigs = [
specs: DEFAULT_SPEC_PATTERN,
},
{ name: "mongo", tags: "@mongo", specs: DEFAULT_SPEC_PATTERN },
{ name: "python", tags: "@python", specs: DEFAULT_SPEC_PATTERN },
];
/**

View File

@@ -11,7 +11,7 @@ describe("buildMatrix", () => {
it("should calculate correct regular chunks with default parameters", () => {
const result = testBuildMatrix("./e2e/test/scenarios/**/*.cy.spec.*", 30);
expect(result.regularChunks).toBe(27);
expect(result.regularChunks).toBe(26);
});
it("should create correct number of configuration objects", () => {
@@ -21,10 +21,10 @@ describe("buildMatrix", () => {
});
it("should apply default specs path when empty entry is provided", () => {
const result = testBuildMatrix("", 5);
const result = testBuildMatrix("", 6);
expect(result.regularChunks).toBe(2);
expect(result.config.length).toBe(5);
expect(result.config.length).toBe(6);
});
it("should name regular test groups sequentially", () => {
@@ -39,13 +39,14 @@ describe("buildMatrix", () => {
});
it("should handle case when input chunks equals special tests count", () => {
const result = testBuildMatrix("./e2e/test/scenarios/**/*.cy.spec.*", 3);
const result = testBuildMatrix("./e2e/test/scenarios/**/*.cy.spec.*", 4);
expect(result.regularChunks).toBe(0);
expect(result.config.length).toBe(3);
expect(result.config.length).toBe(4);
expect(result.config[0].name).toBe("embedding-sdk");
expect(result.config[1].name).toBe("oss-subset");
expect(result.config[2].name).toBe("mongo");
expect(result.config[3].name).toBe("python");
});
it("should correctly calculate regularChunks for non-default spec pattern", () => {
@@ -83,9 +84,10 @@ describe("buildMatrix", () => {
it("should return special test configs when default spec pattern is provided", () => {
const result = testBuildMatrix("./e2e/test/scenarios/**/*.cy.spec.*", 50);
expect(result.config[47].name).toBe("embedding-sdk");
expect(result.config[48].name).toBe("oss-subset");
expect(result.config[49].name).toBe("mongo");
expect(result.config[46].name).toBe("embedding-sdk");
expect(result.config[47].name).toBe("oss-subset");
expect(result.config[48].name).toBe("mongo");
expect(result.config[49].name).toBe("python");
});
it("should not return special test configs when non-default spec pattern is provided", () => {

19
.github/team.json vendored
View File

@@ -38,8 +38,7 @@
"members": [
"piranha",
"crisptrutski",
"spalt08",
"kulyk"
"spalt08"
]
},
{
@@ -54,7 +53,10 @@
"label": ".Team/DevEx",
"members": [
"camsaul",
"escherize"
"dpsutton",
"escherize",
"fraserdrops",
"nemanjaglumac"
]
},
{
@@ -70,14 +72,6 @@
"lbrdnk"
]
},
{
"name": "Product Growth",
"label": ".Team/ProductGrowth",
"members": [
"nemanjaglumac",
"andsalves"
]
},
{
"name": "Cloud",
"label": "cloud",
@@ -104,7 +98,8 @@
"edpaget",
"deniskaber",
"alxnddr",
"bpander"
"bpander",
"andsalves"
]
},
{

View File

@@ -23,7 +23,7 @@ jobs:
uses: actions/github-script@v7
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
script: | #js
const fs = require('fs');
const teamConfig = JSON.parse(fs.readFileSync('.github/team.json', 'utf-8'));
const prAuthor = context.payload.pull_request.user.login;
@@ -65,10 +65,3 @@ jobs:
issue_number: prNumber,
labels: [team.label]
});
return team.projectUrl || null;
- uses: actions/add-to-project@v0.5.0
if: ${{ steps.auto-assign.outputs.result != 'null' }}
with:
project-url: ${{ steps.auto-assign.outputs.result }}
github-token: ${{ steps.generate-token.outputs.token }}

View File

@@ -15,8 +15,6 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cloverage"
- name: Build static viz frontend
run: yarn build-static-viz
env:

View File

@@ -21,8 +21,6 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: 'kondo'
- name: Run clj-kondo
run: ./bin/mage kondo
@@ -35,8 +33,6 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "eastwood"
- run: clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test:eastwood
name: Run Eastwood linter
@@ -112,7 +108,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: be-tests
java-version: "${{ matrix.java-version }}"
# Depending on which files changed, we might either have to build static-viz
# from scratch or download the previously built artifact
@@ -180,8 +175,6 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare backend
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: be-check
# TODO -- we should probably also check WITHOUT ee -- do a check with only OSS namespaces on the classpath
- name: Check namespaces
run: clojure -M:ee:drivers:check
@@ -195,8 +188,6 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: 'cljfmt'
- name: Run cljfmt
run: ./bin/mage cljfmt-all --force-check

View File

@@ -16,8 +16,6 @@ jobs:
- name: Prepare back-end environment
timeout-minutes: 5
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: 'build-scripts'
- name: Run build and release script tests
run: clojure -X:dev:drivers:build:build-dev:build-test:ci

99
.github/workflows/cache-generator.yml vendored Normal file
View File

@@ -0,0 +1,99 @@
# This workflow is the single source of truth for generating and updating various caches used by our CI pipeline.
# It sets the fresh cache each Monday but provides a manual trigger to update it on-demand.
#
# All other jobs only restore from this cache; *they never update it*!
# They should always use `actions/cache/restore@v4` because `actions/cache@v4` would attempt to save the cache.
#
# Our agreed-upon strategy is to use a deterministic cache key based on the week of the year.
# Jobs can utilize the prior week's cache if the current week's cache is not found.
#
#
# PRINCIPLES:
# - The cache is never wrong!
# - Caches are immutable once created.
# - Caches are for speeding up builds, not for correctness.
# - It is faster to download a large cache than to re-resolve missing dependencies.
#
#
# DESIGN:
#
# 1. Prepare
# - A job first prepares the local environment (e.g., installs JDK, Clojure, Node.js, etc.)
# - This fetches the dependencies from the cache (if it exists) and warms up the local cache for this workflow.
# 2. Resolve
# - The next step pre-resolves all dependencies, ensuring that the local cache is fully populated and up-to-date.
# 3. Update
# - The final step saves the local cache back to GitHub Actions cache with a deterministic key.
# - If a cache entry already exists for that key, it is deleted first to ensure immutability.
#
name: Cache Generator
on:
schedule:
- cron: '0 3 * * 1' # Mondays at 03:00 UTC
workflow_dispatch: # manually update the cache
concurrency:
group: cache-generator
cancel-in-progress: true
jobs:
get-cache-keys:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Get cache keys
uses: ./.github/actions/get-cache-keys
id: get-cache-keys
outputs:
m2-cache-key: ${{ steps.get-cache-keys.outputs.m2-cache-key }}
node-cache-key: ${{ steps.get-cache-keys.outputs.node-cache-key }}
generate-m2-cache:
runs-on: ubuntu-22.04
timeout-minutes: 15
needs: get-cache-keys
env:
M2_CACHE_KEY: ${{ needs.get-cache-keys.outputs.m2-cache-key }}
steps:
- uses: actions/checkout@v4
- name: Prepare backend
uses: ./.github/actions/prepare-backend
# Add or remove aliases to affect the cache size and its contents.
# Adjust to taste, then redeploy this workflow.
- name: Pre-resolve dependencies
run: clojure -A:build:dev:ee:ee-dev:drivers:drivers-dev:cljs -P
- name: Update M2 cache
uses: ./.github/actions/update-cache
with:
path: |
~/.m2
~/.gitlibs
key: ${{ env.M2_CACHE_KEY }}
generate-node-modules-cache:
runs-on: ubuntu-22.04
timeout-minutes: 15
needs: get-cache-keys
env:
NODE_CACHE_KEY: ${{ needs.get-cache-keys.outputs.node-cache-key }}
steps:
- uses: actions/checkout@v4
# `prepare-frontend` action (1) prepares Node.js and (2) fetches the node_modules cache if it exists.
# It then (3) runs `yarn install --frozen-lockfile --prefer-offline` which ensures the local cache is fully populated.
# IMPORTANT: Caching node_modules after patches are already applied will break any PR that attempts to either:
# - upgrade a patched library
# - change a patch
# Hence why we explicitly exclude patches from the cache (controlled by the `apply-patches` action input).
- name: Install front-end dependencies
uses: ./.github/actions/prepare-frontend
with:
apply-patches: 'false'
- name: Update node_modules cache
uses: ./.github/actions/update-cache
with:
path: node_modules
key: ${{ env.NODE_CACHE_KEY }}

View File

@@ -40,8 +40,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Compile CLJS
run: NODE_ENV=development yarn build-pure:cljs
- name: Publish to Chromatic

View File

@@ -2,18 +2,14 @@ name: "Claude Code Review"
on:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}-claude-code-review
cancel-in-progress: true
env:
EXCLUDED_PR_AUTHORS: '["kamilmielnik", "romeovs"]'
jobs:
review:
if: github.event.pull_request.draft == false && !contains(fromJSON(env.EXCLUDED_PR_AUTHORS), github.event.pull_request.user.login) }}
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
permissions:
contents: read

View File

@@ -38,7 +38,5 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: 'cljs'
- name: Run Cljs tests
run: yarn run test-cljs

View File

@@ -1,25 +1,28 @@
name: Test coverage
name: Frontend Test Coverage
on:
workflow_dispatch:
schedule:
- cron: '40 1 * * *' # every day at 1:40
jobs:
fe-test-coverage:
runs-on: ubuntu-22.04
timeout-minutes: 30
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Run frontend unit tests
run: yarn run test-unit --silent --coverage
run: |
yarn run test-unit \
--silent \
--coverage \
--testTimeout=60000
- name: Upload coverage to codecov.io
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
files: ./coverage/lcov.info
flags: front-end

View File

@@ -9,10 +9,6 @@ on:
description: "The branch to check out and create a PR against"
required: true
type: string
m2_cache_key_suffix:
description: "A unique suffix for the Maven cache key"
required: true
type: string
secrets:
automation_token:
description: "A token with permissions to create branches and PRs"
@@ -37,8 +33,6 @@ jobs:
- name: Prepare backend environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "auto-update-docs-${{ inputs.m2_cache_key_suffix }}"
- name: Generate environment variables documentation
id: generate_env_docs

View File

@@ -11,6 +11,5 @@ jobs:
uses: ./.github/workflows/docs-generate-base.yml
with:
target_branch: "master"
m2_cache_key_suffix: "master"
secrets:
automation_token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}

View File

@@ -11,6 +11,5 @@ jobs:
uses: ./.github/workflows/docs-generate-base.yml
with:
target_branch: "release-x.56.x"
m2_cache_key_suffix: "release"
secrets:
automation_token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}

View File

@@ -1020,72 +1020,75 @@ jobs:
upload-logs: ${{ steps.test-driver.outcome == 'failure' }}
logs-artifact-suffix: ${{ matrix.job.name }} ${{ matrix.version.name }}
be-tests-snowflake-ee:
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
job:
- name: Driver Tests
test-args: >-
:only-tags [:mb/driver-tests]
:exclude-tags [:mb/transforms-python-test]
# dan sutton 2025-10-23: disable snowflake because of account
# issues. https://linear.app/metabase/issue/DEV-997/reenable-snowflake-in-ci. Note that the transforms tests were
# disabled previously
# be-tests-snowflake-ee:
# if: ${{ !inputs.skip }}
# runs-on: ubuntu-22.04
# timeout-minutes: 60
# strategy:
# fail-fast: false
# matrix:
# job:
# - name: Driver Tests
# test-args: >-
# :only-tags [:mb/driver-tests]
# :exclude-tags [:mb/transforms-python-test]
# DS 2025-09-26 temporarily disabled while we diagnose flakes
# - name: Transforms Python Tests
# test-args: >-
# :only-tags [:mb/transforms-python-test]
# needs-python-runner: true
env:
CI: 'true'
DRIVERS: snowflake
MB_SNOWFLAKE_TEST_USER: METABASE CI
MB_SNOWFLAKE_TEST_ACCOUNT: ${{ secrets.MB_SNOWFLAKE_TEST_ACCOUNT }}
MB_SNOWFLAKE_TEST_PASSWORD: ${{ secrets.MB_SNOWFLAKE_TEST_PASSWORD }}
MB_SNOWFLAKE_TEST_WAREHOUSE: ${{ secrets.MB_SNOWFLAKE_TEST_WAREHOUSE }}
MB_SNOWFLAKE_TEST_PK_USER: METABASE PK
MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY }}
MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY_2: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY_2 }}
MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY }}
MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY_2: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY_2 }}
# env:
# CI: 'true'
# DRIVERS: snowflake
# MB_SNOWFLAKE_TEST_USER: METABASE CI
# MB_SNOWFLAKE_TEST_ACCOUNT: ${{ secrets.MB_SNOWFLAKE_TEST_ACCOUNT }}
# MB_SNOWFLAKE_TEST_PASSWORD: ${{ secrets.MB_SNOWFLAKE_TEST_PASSWORD }}
# MB_SNOWFLAKE_TEST_WAREHOUSE: ${{ secrets.MB_SNOWFLAKE_TEST_WAREHOUSE }}
# MB_SNOWFLAKE_TEST_PK_USER: METABASE PK
# MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY }}
# MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY_2: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PRIVATE_KEY_2 }}
# MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY }}
# MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY_2: ${{ secrets.MB_SNOWFLAKE_TEST_PK_PUBLIC_KEY_2 }}
# RSA Role testing:
MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_DEFAULT_USER: RSA_ROLE_TEST_DEFAULT_USER
MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_CUSTOM_USER: RSA_ROLE_TEST_CUSTOM_USER
MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_ROLE: RSA_ROLE_TEST_ROLE
MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_DB: RSA_ROLE_TEST_DB
name: Snowflake ${{ matrix.job.name }}
steps:
- uses: actions/checkout@v4
- name: Setup python-runner
if: ${{ matrix.job.needs-python-runner == true }}
uses: ./.github/actions/setup-python-runner
with:
metabase-automation-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
- name: Test Snowflake driver
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-snowflake-ee'
test-args: ${{ matrix.job.test-args }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit/
output-name: ${{ github.job }}
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
- name: Cleanup python-runner
if: ${{ always() && matrix.job.needs-python-runner == true }}
uses: ./.github/actions/cleanup-python-runner
with:
upload-logs: ${{ steps.test-driver.outcome == 'failure' }}
logs-artifact-suffix: ${{ matrix.job.name }} ${{ matrix.version.name }}
# # RSA Role testing:
# MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_DEFAULT_USER: RSA_ROLE_TEST_DEFAULT_USER
# MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_CUSTOM_USER: RSA_ROLE_TEST_CUSTOM_USER
# MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_ROLE: RSA_ROLE_TEST_ROLE
# MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_DB: RSA_ROLE_TEST_DB
# name: Snowflake ${{ matrix.job.name }}
# steps:
# - uses: actions/checkout@v4
# - name: Setup python-runner
# if: ${{ matrix.job.needs-python-runner == true }}
# uses: ./.github/actions/setup-python-runner
# with:
# metabase-automation-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
# - name: Test Snowflake driver
# id: test-driver
# uses: ./.github/actions/test-driver
# with:
# junit-name: 'be-tests-snowflake-ee'
# test-args: ${{ matrix.job.test-args }}
# - name: Upload Test Results
# uses: ./.github/actions/upload-test-results
# if: always()
# with:
# input-path: ./target/junit/
# output-name: ${{ github.job }}
# bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
# aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
# aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
# aws-region: ${{ vars.AWS_REGION }}
# trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
# - name: Cleanup python-runner
# if: ${{ always() && matrix.job.needs-python-runner == true }}
# uses: ./.github/actions/cleanup-python-runner
# with:
# upload-logs: ${{ steps.test-driver.outcome == 'failure' }}
# logs-artifact-suffix: ${{ matrix.job.name }} ${{ matrix.version.name }}
be-tests-sparksql-ee:
needs: determine-driver-skips
@@ -1349,7 +1352,8 @@ jobs:
- be-tests-postgres
- be-tests-presto-jdbc-ee
- be-tests-redshift-ee
- be-tests-snowflake-ee
# dan: disabled for account reasons. https://linear.app/metabase/issue/DEV-997/reenable-snowflake-in-ci
# - be-tests-snowflake-ee
- be-tests-sparksql-ee
- be-tests-sqlite-ee
- be-tests-sqlserver

View File

@@ -112,7 +112,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: uberjar
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
- name: Prepare front-end environment

View File

@@ -83,7 +83,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: uberjar
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
- name: Build uberjar with ./bin/build.sh
@@ -144,8 +143,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Retrieve Embedding SDK dist artifact
uses: actions/download-artifact@v4

View File

@@ -167,7 +167,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: uberjar
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
- name: Build uberjar with ./bin/build.sh
@@ -179,7 +178,11 @@ jobs:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
- name: Build Embedding SDK package
run: yarn build-embedding-sdk-package
run: |
# Remove the matchers to not report false positives on every PR
# unrelated to embedding (EMB-765)
echo "::remove-matcher owner=tsc::"
yarn build-embedding-sdk-package
- name: Prepare Embedding SDK artifact
uses: actions/upload-artifact@v4

View File

@@ -65,6 +65,7 @@ jobs:
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
- name: Setup python-runner
if: ${{ inputs.name == 'python' }}
env:
METABASE_AUTOMATION_USER_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
run: ./.github/scripts/setup-python-runner.sh
@@ -139,9 +140,14 @@ jobs:
run: |
echo "Running tests with specs: $SPEC_PATH"
node e2e/runner/run_cypress_ci.js e2e \
--env grepTags="-@mongo+-@flaky+-@OSS+-@skip",grepOmitFiltered=true \
--env grepTags="-@mongo+-@python+-@flaky+-@OSS+-@skip",grepOmitFiltered=true \
--spec "$SPEC_PATH" \
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
# Trunk Quarantine controls the final state of the run in the CI!
# Even if this step fails, we let it pass and then `trunk-io/analytics-uploader` determines whether to fail or to
# pass the whole job, based on the quarantine list.
# We only want to "continue on error" (ignore failures) when the Trunk upload is active - i.e. not on drafts!
continue-on-error: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.draft == true) }}
- name: Run Tagged EE Cypress tests on ${{ inputs.name }}
if: ${{ inputs.specs }}
@@ -154,18 +160,25 @@ jobs:
--env grepTags="${{inputs.tags && format('{0}+-@skip', inputs.tags) || '-@skip'}}",grepOmitFiltered=true \
--spec "$SPEC_PATH" \
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
# Trunk Quarantine controls the final state of the run in the CI!
# Even if this step fails, we let it pass and then `trunk-io/analytics-uploader` determines whether to fail or to
# pass the whole job, based on the quarantine list.
# We only want to "continue on error" (ignore failures) when the Trunk upload is active - i.e. not on drafts!
continue-on-error: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.draft == true) }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit
# Related to our custom upload to S3
output-name: e2e-${{ inputs.name }}
variant: e2e-tests
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
# Related to Trunk uploader
variant: e2e-tests
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
- name: Upload Cypress Artifacts upon failure

View File

@@ -40,10 +40,12 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Build Embedding SDK package
run: yarn build-embedding-sdk-package
run: |
# Remove the matchers to not report false positives on every PR
# unrelated to embedding (EMB-765)
echo "::remove-matcher owner=tsc::"
yarn build-embedding-sdk-package
- name: Prepare Embedding SDK artifact
uses: actions/upload-artifact@v4
with:

View File

@@ -43,8 +43,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Build cljs
run: yarn build:cljs
- name: Stress-test ${{ github.event.inputs.spec }} ${{ github.event.inputs.burn_in }} times

View File

@@ -35,8 +35,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Restore ESLint cache
uses: actions/cache@v4
with:
@@ -65,8 +63,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- run: yarn build-pure:cljs
name: Compile CLJS
- run: yarn type-check-pure
@@ -90,10 +86,11 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Run frontend unit tests
run: yarn run test-unit --silent --shard=${{ matrix.shard }}/${{ env.SHARDS }}
# We want Trunk to still receive test reports even if this job fails.
# It will filter out the quarantined tests, and will control the job exit code based on the analysis.
continue-on-error: true
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always() && github.event_name != 'workflow_dispatch'
@@ -116,8 +113,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Run frontend timezones tests
run: yarn run test-timezones

View File

@@ -22,8 +22,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- run: yarn test-unit frontend/src/metabase/querying/expressions/pratt/fuzz.lexifier.unit.spec.ts
env:
MB_FUZZ: 1
@@ -38,8 +36,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- run: yarn test-unit frontend/src/metabase/querying/expressions/fuzz.compiler.unit.spec.ts
env:
MB_FUZZ: 1
@@ -54,8 +50,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- run: yarn test-unit frontend/src/metabase/querying/expressions/fuzz.string.unit.spec.ts
env:
MB_FUZZ: 1

View File

@@ -40,8 +40,6 @@ jobs:
ref: ${{ inputs.ref }}
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: generative-query-test
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend

View File

@@ -38,8 +38,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: 'i18n'
- name: Install xgettext if necessary
run: |
if ! command -v xgettext > /dev/null; then

View File

@@ -20,8 +20,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Compile CLJS
run: yarn build-pure:cljs

View File

@@ -47,8 +47,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Compile CLJS
run: NODE_ENV=development yarn build-pure:cljs

View File

@@ -2,7 +2,7 @@ name: Mage Tests
on:
pull_request:
paths: ["mage/**", "test/mage/**"]
paths: ["mage/**"]
jobs:
# run mage tests even if the rest of be isnt needed
@@ -13,8 +13,6 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: 'kondo'
- name: Setup Babashka
uses: turtlequeue/setup-babashka@v1.7.0
with:
@@ -24,4 +22,4 @@ jobs:
- name: bb task list
run: bb tasks
- name: Run mage tests
run: bb ./test/mage/runtests.clj
run: bb ./mage/test/mage/runtests.clj

View File

@@ -16,7 +16,5 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: lint-migrations
- name: Verify Liquibase Migrations
run: ./bin/mage lint-migrations

View File

@@ -254,8 +254,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "release-sdk"
- name: Run unit tests
run: yarn embedding-sdk:test-unit
@@ -277,8 +275,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "release-sdk"
- name: Bump published npm package version
# NOTE: this should happen before "Build SDK bundle" as we inject SDK version into the code during build step

View File

@@ -49,8 +49,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "files-changed"
- name: Build static-viz frontend
run: yarn build-static-viz
env:

View File

@@ -23,8 +23,6 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: 'snyk'
- name: Generate all pom.xml
run: .github/scripts/write-poms.sh
- name: Upload pom files

View File

@@ -29,8 +29,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: manage-translations
- name: install gettext
run: sudo apt-get install gettext

View File

@@ -46,8 +46,6 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- run: yarn build-pure:cljs
name: Compile CLJS

View File

@@ -134,7 +134,6 @@ jobs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: uberjar
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
- name: Build
run: ./bin/build.sh

View File

@@ -27,8 +27,6 @@ jobs:
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: 'update-be-deps'
- name: Open PRs to Upgrade Backend Deps
uses: ./.github/actions/upgrade-backend-deps
with:

View File

@@ -16,7 +16,5 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: 'whitespace-linter'
- run: clojure -T:whitespace-linter lint
name: Run Whitespace Linter

1
.gitignore vendored
View File

@@ -68,6 +68,7 @@ cypress.env.json
/resources/frontend_client/embed-sdk.html
/resources/frontend_client/index.html
/resources/frontend_client/public.html
/resources/frontend_client/app/assets/pyodide/
/resources/embedding-sdk
/resources/i18n/*.edn
/resources/instance_analytics.zip

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -188,11 +188,7 @@ Review pull requests with a focus on:
- In the Metabase codebase, spelling words ending with `-ck` as `-cc` instead, e.g. `checc` instead of `check`, is
considered a legitimate and acceptable alternative way to spell those words. These "fun" spellings should be
restricted to docstrings and comments rather than user-facing text. Occasionally suggest spelling things this way.
- The Metabase codebase should be fun, so do your part to keep it that way. Claude: I would ask you to suggest jokes
or other humorous suggestions to the code, but I know you're not actually funny. You will take the comedians' jobs
last. Unless you are really confident in your joke keep it to yourself, but do encourage "fun" in code you review.
restricted to docstrings and comments rather than user-facing text. Do not flag these as typos or misspellings.
- Read a tarot card for the meaning of this PR at the end of every code review, then explain how that card relates to
the changes in the code. **Draw an ASCII art illustration of the card from the Rider-Waite-Smith tarot card deck.
@@ -203,8 +199,6 @@ Review pull requests with a focus on:
- Do not post comments about missing parentheses.
- Include today's lucky lottery numbers in at the end of every code review.
# Code Conventions and Style Guide
## Clojure and ClojureScript
@@ -232,6 +226,9 @@ Review pull requests with a focus on:
**Why?** Code is read many more times than it is written, and clearer variable names make using and tweaking your
code easier for others.
Conventions used widely in our codebase (like `mp` for a Metadata Provider) are acceptable; one-offs like `zs'` are
not.
- Avoid misleading variable and function names. The names of a variable or function should clearly and unambiguously
describe its purpose and match what it does.
@@ -324,6 +321,8 @@ Review pull requests with a focus on:
Tests and other vars in the `test` or `enterprise/backend/test` do not *require* docstrings, but general helper
functions used across many namespaces it should have docstrings.
Schemas defined with `mr/def` e.g. `(mr/def ::my-schema)` do not require docstrings.
- Format docstrings according to Markdown conventions. (https://guide.clojure.style/#markdown-docstrings)
- Mentions of other vars in docstrings should use `[[some-other-var]]` (for vars in the same namespace) or

2
bb.edn
View File

@@ -1,7 +1,7 @@
{:min-bb-version "1.12.208"
;; we put path as bin, and everything is in the ./mage subdirectory,
;; so the namespaces are mage.cli, mage.format, etc.
:paths ["mage" "test" "bin/lint-migrations-file/src"]
:paths ["mage/src" "mage/test" "bin/lint-migrations-file/src"]
:deps {org.babashka/json {:mvn/version "0.1.6"}
metosin/malli {:mvn/version "0.17.0"}
table/table {:mvn/version "0.5.0"}

View File

@@ -59,6 +59,7 @@
"net.thisptr" {"jackson-jq" {:resource "apache2_0.txt"}}
"org.antlr" {"antlr-runtime" {:resource "BSD.txt"}
"antlr4-runtime" {:resource "BSD.txt"}}
"org.eclipse.jgit" {"org.eclipse.jgit" {:resource "BSD.txt"}}
"org.eclipse.jetty" {"jetty-webapp" {:resource "EPL.txt"}}
"org.eclipse.jetty.toolchain" {"jetty-jakarta-servlet-api" {:resource "EPL.txt"}}
"org.eclipse.jetty.ee9.websocket" {"jetty-ee9-websocket-jetty-api" {:resource "EPL.txt"}

48
bin/download-pyodide.sh Executable file
View File

@@ -0,0 +1,48 @@
#! /usr/bin/env bash
DEST_DIR="resources/frontend_client/app/assets"
REQUIRED_FILES=(
"pyodide/pyodide-lock.json"
"pyodide/pyodide.asm.js"
"pyodide/pyodide.asm.wasm"
"pyodide/pyodide.js"
"pyodide/python_stdlib.zip"
"pyodide/micropip-0.10.1-py3-none-any.whl"
"pyodide/numpy-2.2.5-cp313-cp313-pyodide_2025_0_wasm32.whl"
"pyodide/pandas-2.3.1-cp313-cp313-pyodide_2025_0_wasm32.whl"
"pyodide/python_dateutil-2.9.0.post0-py2.py3-none-any.whl"
"pyodide/pytz-2025.2-py2.py3-none-any.whl"
"pyodide/packaging-24.2-py3-none-any.whl"
"pyodide/six-1.17.0-py2.py3-none-any.whl"
)
PYODIDE_VERSION="0.28.3"
DOWNLOAD_URL="https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/pyodide-${PYODIDE_VERSION}.tar.bz2"
function all_files_exist() {
for FILE in "${REQUIRED_FILES[@]}"; do
TEST_FILE="$DEST_DIR/$FILE"
if [ ! -f "$TEST_FILE" ]; then
return 1
fi
done
return 0
}
if all_files_exist; then
echo "Pyodide files already exist, skipping download"
exit 0
fi
echo "Downloading Pyodide $PYODIDE_VERSION into $DEST_DIR"
echo "This might take a while"
rm -rf "$DEST_DIR/pyodide"
mkdir -p "$DEST_DIR"
curl -Ls "$DOWNLOAD_URL" | tar xvfj - -C "$DEST_DIR" ${REQUIRED_FILES[@]}

View File

@@ -85,7 +85,7 @@
hiccup/hiccup {:mvn/version "2.0.0"} ; HTML templating
inflections/inflections {:mvn/version "0.15.0"} ; Clojure/Script library used for prularizing words
instaparse/instaparse {:mvn/version "1.5.0"} ; Make your own parser
io.github.camsaul/toucan2 {:mvn/version "1.0.567"}
io.github.camsaul/toucan2 {:mvn/version "1.0.568"}
io.github.eerohele/pp {#_#_:git/tag "2024-11-13.77" ; super fast pretty-printing library
:git/sha "4998a1fdd9d3713d7034d04509e9212204773bf2"
:git/url "https://github.com/eerohele/pp"}
@@ -108,7 +108,7 @@
org.bouncycastle/bcprov-jdk18on]}
metabase/throttle {:mvn/version "1.0.2"} ; Tools for throttling access to API endpoints and other code pathways
methodical/methodical {:mvn/version "1.0.127"} ; drop-in replacements for Clojure multimethods and adds several advanced features
metosin/malli {:mvn/version "0.19.1"} ; Data-driven Schemas for Clojure/Script and babashka
metosin/malli {:mvn/version "0.19.2"} ; Data-driven Schemas for Clojure/Script and babashka
nano-id/nano-id {:mvn/version "1.1.0"} ; NanoID generator for generating entity_ids
net.cgrand/macrovich {:mvn/version "0.2.2"} ; utils for writing macros for both Clojure & ClojureScript
net.clojars.wkok/openai-clojure {:mvn/version "0.23.0"
@@ -170,6 +170,7 @@
org.eclipse.jetty/jetty-unixdomain-server {:mvn/version "12.0.25"}
org.eclipse.jetty.ee9/jetty-ee9-servlet {:mvn/version "12.0.24"}
org.eclipse.jetty.ee9.websocket/jetty-ee9-websocket-jetty-server {:mvn/version "12.0.25"}
org.eclipse.jgit/org.eclipse.jgit {:mvn/version "7.3.0.202506031305-r"}; Java implementation of Git version control system
org.flatland/ordered {:mvn/version "1.15.12"} ; ordered maps & sets
org.graalvm.polyglot/js-community {:mvn/version "24.2.2" :extension "pom"} ; JavaScript engine
org.graalvm.polyglot/polyglot {:mvn/version "24.2.2"} ; GraalVM platform, required by JS engine
@@ -662,7 +663,7 @@
:ns-regex
["^metabase\\..*" "^metabase-enterprise\\..*"]
;; don't instrument Postgres/MySQL driver namespaces, because we don't current run tests for them
;; don't instrument Postgres/MySQL driver namespaces, because we don't currently run tests for them
;; as part of recording test coverage, which means they can give us false positives.
;;
;; regex literals aren't allowed in EDN. We parse them in `./test/cloverage.clj`

View File

@@ -348,7 +348,9 @@
(do
;; prevent things like dereferencing metabase.api.common/*current-user-permissions-set* from triggering the check
;; by calling `next-method` *twice*. To reduce the performance impact, just call it with the first instance.
(maybe-realize (next-method model strategy k [(first instances)]))
;; we do this for each model because e.g. we may have one `:RootCollection` and several `:Collection`s.
(doseq [[_instance-model instances] (group-by t2/model instances)]
(maybe-realize (next-method model strategy k [(first instances)])))
;; Now we can actually run the hydration with the full set of instances and make sure no more DB calls happened.
(t2/with-call-count [call-count]
(let [res (maybe-realize (next-method model strategy k instances))]

View File

@@ -88,13 +88,16 @@
[zloc :- ::zloc]
(when (= (z/tag zloc) :list)
(let [first-child (z/down zloc)]
(and (= (z/tag first-child) :token)
(require-symbols (z/sexpr first-child))))))
(when (= (z/tag first-child) :token)
;; Check all child symbols on the line since `require` might be called in a threading macro
;; like (-> 'ns require)
(some require-symbols (z/child-sexprs zloc))))))
(mu/defn- find-required-namespace :- [:maybe simple-symbol?]
"Given a `zloc` pointing to one of the children of something like `(require ...)` find a required namespace symbol."
[zloc :- ::zloc]
(when-let [symbol-loc (z/find-depth-first zloc #(and (= (z/tag %) :token)
(symbol? (z/sexpr %))
(not= (z/sexpr %) 'quote)))]
(let [symb (z/sexpr symbol-loc)]
(if (qualified-symbol? symb)

View File

@@ -7,12 +7,15 @@
(deftest ^:parallel find-required-namespaces-test
(are [s expected] (= (quote expected)
(#'dev.deps-graph/find-required-namespaces (z/of-string s)))
"(require 'malli.generator)" #{malli.generator}
"(require (quote malli.generator))" #{malli.generator}
"(classloader/require 'a 'b)" #{a b}
"(requiring-resolve 'a/b 'c/d)" #{a c}
"(require '[malli.generator :as mg])" #{malli.generator}
"(require '[malli.generator])" #{malli.generator}))
"(require 'malli.generator)" #{malli.generator}
"(require (quote malli.generator))" #{malli.generator}
"(classloader/require 'a 'b)" #{a b}
"(requiring-resolve 'a/b 'c/d)" #{a c}
"(require '[malli.generator :as mg])" #{malli.generator}
"(require '[malli.generator])" #{malli.generator}
"(-> 'malli.generator requiring-resolve)" #{malli.generator}))
;; TODO: reader conditionals don't work properly
; "(#?(:clj requiring-resolve :cljs resolve) 'malli.generator)" #{malli.generator}))
(deftest ^:parallel find-requires-test
(are [s expected] (= (quote expected)
@@ -21,6 +24,12 @@
((require '[malli.generator])
(requiring-resolve 'whatever/x))
"(-> 'whatever requiring-resolve)"
((-> 'whatever requiring-resolve))
; "(#?(:clj requiring-resolve :cljs resolve) 'malli.generator)"
; ((#?(:clj requiring-resolve :cljs resolve) 'malli.generator))
;; should ignore comments.
"(do #_(require '[malli.generator]))"
()

View File

@@ -946,7 +946,11 @@ redirect_from:
}, {
"$ref" : "#/components/schemas/metabase.lib.schema.common.options"
}, {
"$ref" : "#/components/schemas/metabase.lib.schema.id.segment"
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
}, {
"$ref" : "#/components/schemas/metabase.lib.schema.id.segment"
} ]
} ]
},
"mbql.clause.share" : {
@@ -3298,7 +3302,7 @@ redirect_from:
"metabase.analyze.query-results.ResultsMetadata" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.legacy-column-metadata"
"$ref" : "#/components/schemas/metabase.query-processor.schema..result-metadata.column"
},
"description" : "value must be an array of valid results column metadata maps.",
"optional" : true
@@ -3606,6 +3610,225 @@ redirect_from:
"description" : "schema for a valid legacy MBQL :tag clause",
"allOf" : [ ]
},
"metabase.legacy-mbql.schema..expression.options" : {
"description" : "Options for a legacy `:expression` ref in MBQL 4 are the same as in MBQL 5, except that `:lib/uuid` is optional and\n it cannot be empty.",
"default" : { },
"type" : "object",
"properties" : {
"base-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"database-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"display-name" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"effective-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"lib/uuid" : {
"type" : "string",
"minLength" : 36,
"maxLength" : 36
},
"name" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"semantic-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.semantic-or-relation-type"
},
"temporal-unit" : {
"$ref" : "#/components/schemas/metabase.lib.schema.temporal-bucketing.unit"
}
}
},
"metabase.legacy-mbql.schema..legacy-column-metadata.binning-info" : {
"type" : "object",
"properties" : {
"bin_width" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.bin-width"
},
"binning_strategy" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.strategy"
},
"num_bins" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.num-bins"
},
"strategy" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.strategy"
}
},
"required" : [ "strategy" ]
},
"metabase.legacy-mbql.schema..legacy-column-metadata.qualified-keys" : {
"type" : "object",
"properties" : {
"lib/external-remap" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata..column.remapping.external"
},
"lib/source-column-alias" : {
"description" : "Name for a column as returned/projected by the previous stage of the query or source Table/source Card. The\n left-hand side (LHS) of\n\n SELECT lhs AS rhs",
"type" : "string"
},
"lib/type" : {
"default" : "metadata/column",
"const" : "metadata/column"
},
"lib/source-uuid" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.uuid"
},
"qp/implicit-field?" : {
"type" : "boolean"
},
"lib/ref-name" : {
"type" : "string"
},
"lib/deduplicated-name" : {
"type" : "string",
"description" : "The simply-deduplicated name that was historically used in QP results metadata (originally calculated by\n the [[metabase.query-processor.middleware.annotate]] middleware, now calculated\n by [[metabase.lib.middleware.result-metadata]]). This just adds suffixes to column names e.g. `ID` and `ID` become\n `ID` and `ID_2`, respectively. Kept around because many old field refs use this column name."
},
"lib/original-expression-name" : {
"type" : "string",
"minLength" : 1
},
"lib/card-id" : {
"description" : "Valid Card ID",
"type" : "integer",
"minimum" : 1
},
"lib/expression-name" : {
"type" : "string",
"minLength" : 1
},
"lib/breakout?" : {
"type" : "boolean"
},
"metabase.lib.field/temporal-unit" : {
"type" : "string",
"enum" : [ "day", "day-of-month", "day-of-week", "day-of-year", "default", "hour", "hour-of-day", "millisecond", "minute", "minute-of-hour", "month", "month-of-year", "quarter", "quarter-of-year", "second", "second-of-minute", "week", "week-of-year", "year", "year-of-era" ]
},
"metabase.lib.field/binning" : {
"description" : "Schema for `:binning` options passed to a `:field` clause.",
"allOf" : [ {
"type" : "object",
"properties" : {
"strategy" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.strategy"
}
},
"required" : [ "strategy" ]
}, {
"oneOf" : [ {
"type" : "object",
"properties" : {
"strategy" : {
"const" : "default"
}
},
"required" : [ "strategy" ]
}, {
"type" : "object",
"properties" : {
"bin-width" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.bin-width"
},
"strategy" : {
"const" : "bin-width"
}
},
"required" : [ "strategy", "bin-width" ]
}, {
"type" : "object",
"properties" : {
"num-bins" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.num-bins"
},
"strategy" : {
"const" : "num-bins"
}
},
"required" : [ "strategy", "num-bins" ]
} ]
} ]
},
"lib/model-display-name" : {
"type" : "string"
},
"lib/internal-remap" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata..column.remapping.internal"
},
"metabase.lib.join/join-alias" : {
"type" : "string",
"minLength" : 1
},
"lib/original-binning" : {
"description" : "Schema for `:binning` options passed to a `:field` clause.",
"allOf" : [ {
"type" : "object",
"properties" : {
"strategy" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.strategy"
}
},
"required" : [ "strategy" ]
}, {
"oneOf" : [ {
"type" : "object",
"properties" : {
"strategy" : {
"const" : "default"
}
},
"required" : [ "strategy" ]
}, {
"type" : "object",
"properties" : {
"bin-width" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.bin-width"
},
"strategy" : {
"const" : "bin-width"
}
},
"required" : [ "strategy", "bin-width" ]
}, {
"type" : "object",
"properties" : {
"num-bins" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.num-bins"
},
"strategy" : {
"const" : "num-bins"
}
},
"required" : [ "strategy", "num-bins" ]
} ]
} ]
},
"lib/original-join-alias" : {
"type" : "string",
"minLength" : 1
},
"lib/original-display-name" : {
"type" : "string"
},
"lib/source" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata..column.source"
},
"lib/ref-display-name" : {
"type" : "string"
},
"lib/original-name" : {
"type" : "string",
"description" : "The original name of the column as it appeared in the very first place it came from (i.e., the physical name of the\n column in the table it appears in). This should be the same as the `:lib/source-column-alias` for the very first\n usage of the column.\n Allowed to be blank because some databases like SQL Server allow blank column names."
},
"lib/desired-column-alias" : {
"description" : "Name we should use as a column alias for a column in this stage of a query. The desired column alias in stage N\n becomes the source column alias in stage N+1. The right-hand side (RHS) in\n\n SELECT lhs AS rhs",
"type" : "string"
}
}
},
"metabase.legacy-mbql.schema./" : {
"description" : "schema for a valid legacy MBQL :tag clause",
"allOf" : [ ]
@@ -3824,47 +4047,65 @@ redirect_from:
"enum" : [ "iso", "us", "instance" ]
},
"metabase.legacy-mbql.schema.FieldOptions" : {
"allOf" : [ {
"type" : "object",
"properties" : {
"base-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"binning" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.binning",
"description" : "Replaces `binning-strategy`.\n\n Using binning requires the driver to support the `:binning` feature."
},
"inherited-temporal-unit" : {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.DateTimeUnit"
},
"join-alias" : {
"$ref" : "#/components/schemas/metabase.lib.schema.join.alias",
"description" : "Replaces `joined-field`.\n\n `:join-alias` is used to refer to a FieldOrExpression from a different Table/nested query that you are EXPLICITLY\n JOINING against."
},
"source-field" : {
"description" : "Replaces `fk->`.\n\n `:source-field` is used to refer to a FieldOrExpression from a different Table you would like IMPLICITLY JOINED to\n the source table.\n\n If both `:source-field` and `:join-alias` are supplied, `:join-alias` should be used to perform the join;\n `:source-field` should be for information purposes only.",
"$ref" : "#/components/schemas/metabase.lib.schema.id.field"
},
"source-field-join-alias" : {
"description" : "The join alias of the source field used for an implicit join.",
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"source-field-name" : {
"description" : "The name or desired alias of the field used for an implicit join.",
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"temporal-unit" : {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.DateTimeUnit",
"description" : "`:temporal-unit` is used to specify DATE BUCKETING for a FieldOrExpression that represents a moment in time of\n some sort.\n\n There is no requirement that all `:type/Temporal` derived FieldOrExpressions specify a `:temporal-unit`, but for\n legacy reasons `:field` clauses that refer to `:type/DateTime` FieldOrExpressions will be automatically \"bucketed\"\n in the `:breakout` and `:filter` clauses, but nowhere else. Auto-bucketing only applies to `:filter` clauses when\n values for comparison are `yyyy-MM-dd` date strings. See the `auto-bucket-datetimes` middleware for more details.\n `:field` clauses elsewhere will not be automatically bucketed, so drivers still need to make sure they do any\n special datetime handling for plain `:field` clauses when their FieldOrExpression derives from `:type/DateTime`."
}
"default" : { },
"type" : "object",
"properties" : {
"binning" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.binning"
},
"inherited-temporal-unit" : {
"$ref" : "#/components/schemas/metabase.lib.schema.temporal-bucketing.unit"
},
"database-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"metabase.lib.field/original-temporal-unit" : {
"$ref" : "#/components/schemas/metabase.lib.schema.temporal-bucketing.unit"
},
"display-name" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"source-field-name" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"effective-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"base-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"lib/uuid" : {
"type" : "string",
"minLength" : 36,
"maxLength" : 36
},
"name" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"metabase.lib.field/original-effective-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"source-field" : {
"$ref" : "#/components/schemas/metabase.lib.schema.id.field"
},
"join-alias" : {
"$ref" : "#/components/schemas/metabase.lib.schema.join.alias"
},
"lib/original-binning" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.binning"
},
"temporal-unit" : {
"$ref" : "#/components/schemas/metabase.lib.schema.temporal-bucketing.unit"
},
"source-field-join-alias" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"semantic-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.semantic-or-relation-type"
}
}, {
"description" : "If `:base-type` is specified, the `:temporal-unit` must make sense, e.g. no bucketing by `:year`for\n a `:type/Time` column.",
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.validate-temporal-unit"
}, {
"description" : "You cannot use `:binning` keys like `:strategy` in the top level.",
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.no-binning-options-at-top-level"
} ]
},
"description" : "Options for an MBQL 4 `:field` ref are the same as MBQL 5, except that `:lib/uuid` is not required and it cannot be\n empty.",
"optional" : true
},
"metabase.legacy-mbql.schema.FieldOrExpressionDef" : {
"description" : "Schema for anything that is accepted as a top-level expression definition, either an arithmetic expression such as a\n `:+` clause or a `:field` or `:value` clause.",
@@ -4757,7 +4998,6 @@ redirect_from:
"description" : "schema for a valid legacy MBQL :tag clause",
"allOf" : [ ]
}, {
"description" : "Fields using names rather than integer IDs are required to specify `:base-type`.",
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.require-base-type-for-field-name"
} ]
},
@@ -4854,6 +5094,17 @@ redirect_from:
"field_ref" : {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.Reference"
},
"lib/external-remap" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata..column.remapping.external"
},
"lib/source-column-alias" : {
"description" : "Name for a column as returned/projected by the previous stage of the query or source Table/source Card. The\n left-hand side (LHS) of\n\n SELECT lhs AS rhs",
"type" : "string"
},
"lib/type" : {
"default" : "metadata/column",
"const" : "metadata/column"
},
"fingerprint" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata.fingerprint.fingerprint"
},
@@ -4861,31 +5112,187 @@ redirect_from:
"$ref" : "#/components/schemas/metabase.lib.schema.metadata..column.visibility-type"
},
"base_type" : {
"default" : "type/*",
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"lib/source-uuid" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.uuid"
},
"qp/implicit-field?" : {
"type" : "boolean"
},
"lib/ref-name" : {
"type" : "string"
},
"id" : {
"$ref" : "#/components/schemas/metabase.lib.schema.id.field"
},
"lib/deduplicated-name" : {
"type" : "string",
"description" : "The simply-deduplicated name that was historically used in QP results metadata (originally calculated by\n the [[metabase.query-processor.middleware.annotate]] middleware, now calculated\n by [[metabase.lib.middleware.result-metadata]]). This just adds suffixes to column names e.g. `ID` and `ID` become\n `ID` and `ID_2`, respectively. Kept around because many old field refs use this column name."
},
"lib/original-expression-name" : {
"type" : "string",
"minLength" : 1
},
"name" : {
"type" : "string"
},
"lib/card-id" : {
"description" : "Valid Card ID",
"type" : "integer",
"minimum" : 1
},
"lib/expression-name" : {
"type" : "string",
"minLength" : 1
},
"lib/breakout?" : {
"type" : "boolean"
},
"metabase.lib.field/temporal-unit" : {
"type" : "string",
"enum" : [ "day", "day-of-month", "day-of-week", "day-of-year", "default", "hour", "hour-of-day", "millisecond", "minute", "minute-of-hour", "month", "month-of-year", "quarter", "quarter-of-year", "second", "second-of-minute", "week", "week-of-year", "year", "year-of-era" ]
},
"metabase.lib.field/binning" : {
"description" : "Schema for `:binning` options passed to a `:field` clause.",
"allOf" : [ {
"type" : "object",
"properties" : {
"strategy" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.strategy"
}
},
"required" : [ "strategy" ]
}, {
"oneOf" : [ {
"type" : "object",
"properties" : {
"strategy" : {
"const" : "default"
}
},
"required" : [ "strategy" ]
}, {
"type" : "object",
"properties" : {
"bin-width" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.bin-width"
},
"strategy" : {
"const" : "bin-width"
}
},
"required" : [ "strategy", "bin-width" ]
}, {
"type" : "object",
"properties" : {
"num-bins" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.num-bins"
},
"strategy" : {
"const" : "num-bins"
}
},
"required" : [ "strategy", "num-bins" ]
} ]
} ]
},
"semantic_type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.semantic-or-relation-type"
},
"display_name" : {
"type" : "string"
},
"lib/model-display-name" : {
"type" : "string"
},
"lib/internal-remap" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata..column.remapping.internal"
},
"converted_timezone" : {
"$ref" : "#/components/schemas/metabase.lib.schema.expression.temporal.timezone-id"
},
"source" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata..column.legacy-source"
},
"metabase.lib.join/join-alias" : {
"type" : "string",
"minLength" : 1
},
"binning_info" : {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema..legacy-column-metadata.binning-info"
},
"lib/original-binning" : {
"description" : "Schema for `:binning` options passed to a `:field` clause.",
"allOf" : [ {
"type" : "object",
"properties" : {
"strategy" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.strategy"
}
},
"required" : [ "strategy" ]
}, {
"oneOf" : [ {
"type" : "object",
"properties" : {
"strategy" : {
"const" : "default"
}
},
"required" : [ "strategy" ]
}, {
"type" : "object",
"properties" : {
"bin-width" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.bin-width"
},
"strategy" : {
"const" : "bin-width"
}
},
"required" : [ "strategy", "bin-width" ]
}, {
"type" : "object",
"properties" : {
"num-bins" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.num-bins"
},
"strategy" : {
"const" : "num-bins"
}
},
"required" : [ "strategy", "num-bins" ]
} ]
} ]
},
"effective_type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"lib/original-join-alias" : {
"type" : "string",
"minLength" : 1
},
"lib/original-display-name" : {
"type" : "string"
},
"unit" : {
"$ref" : "#/components/schemas/metabase.lib.schema.temporal-bucketing.unit"
},
"lib/source" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata..column.source"
},
"lib/ref-display-name" : {
"type" : "string"
},
"lib/original-name" : {
"type" : "string",
"description" : "The original name of the column as it appeared in the very first place it came from (i.e., the physical name of the\n column in the table it appears in). This should be the same as the `:lib/source-column-alias` for the very first\n usage of the column.\n Allowed to be blank because some databases like SQL Server allow blank column names."
},
"lib/desired-column-alias" : {
"description" : "Name we should use as a column alias for a column in this stage of a query. The desired column alias in stage N\n becomes the source column alias in stage N+1. The right-hand side (RHS) in\n\n SELECT lhs AS rhs",
"type" : "string"
}
},
"required" : [ "base_type", "display_name", "name" ]
@@ -4926,7 +5333,6 @@ redirect_from:
"description" : "schema for a valid legacy MBQL :tag clause",
"allOf" : [ ]
},
"metabase.legacy-mbql.schema.no-binning-options-at-top-level" : { },
"metabase.legacy-mbql.schema.not" : {
"description" : "schema for a valid legacy MBQL :tag clause",
"allOf" : [ ]
@@ -4987,7 +5393,9 @@ redirect_from:
"description" : "schema for a valid legacy MBQL :tag clause",
"allOf" : [ ]
},
"metabase.legacy-mbql.schema.require-base-type-for-field-name" : { },
"metabase.legacy-mbql.schema.require-base-type-for-field-name" : {
"description" : "Fields using names rather than integer IDs are required to specify `:base-type`."
},
"metabase.legacy-mbql.schema.round" : {
"description" : "schema for a valid legacy MBQL :tag clause",
"allOf" : [ ]
@@ -5069,7 +5477,6 @@ redirect_from:
"description" : "schema for a valid legacy MBQL :tag clause",
"allOf" : [ ]
},
"metabase.legacy-mbql.schema.validate-temporal-unit" : { },
"metabase.legacy-mbql.schema.value" : {
"description" : "schema for a valid legacy MBQL :tag clause",
"allOf" : [ ]
@@ -6247,6 +6654,7 @@ redirect_from:
"$ref" : "#/components/schemas/metabase.lib.schema.metadata.deduplicated-name"
},
"base-type" : {
"default" : "type/*",
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"lib/original-expression-name" : {
@@ -6523,6 +6931,7 @@ redirect_from:
"$ref" : "#/components/schemas/metabase.lib.schema.metadata.deduplicated-name"
},
"base-type" : {
"default" : "type/*",
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
"lib/original-expression-name" : {
@@ -6744,6 +7153,19 @@ redirect_from:
"metabase.lib.schema.parameter..target.legacy-field-ref" : {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.field"
},
"metabase.lib.schema.parameter..template-tag.tag-name" : {
"oneOf" : [ {
"type" : "object",
"properties" : {
"id" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
}
},
"required" : [ "id" ]
}, {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
} ]
},
"metabase.lib.schema.parameter..variable.target" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.lib.schema.parameter..target.legacy-field-ref"
@@ -6756,7 +7178,7 @@ redirect_from:
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"metabase.lib.schema.parameter.parameter" : {
"description" : "Schema for the *value* of a parameter (e.g. a Dashboard parameter or a native query template tag) as passed in as\n part of the `:parameters` list in a query.",
"description" : "Schema for the *value* of a parameter (e.g. a Dashboard parameter or a native query template tag) as passed in as\n part of the `:parameters` list in a query.\n\n Note that this is different from the parameter declarations that are saved as part of Dashboards and Cards; for THAT\n schema refer to `:metabase.parameters.schema/parameter`.",
"allOf" : [ {
"type" : "object",
"properties" : {
@@ -6802,12 +7224,6 @@ redirect_from:
"$ref" : "#/components/schemas/metabase.lib.schema.parameter.text-tag"
}, {
"$ref" : "#/components/schemas/metabase.lib.schema.parameter..target.legacy-field-ref"
}, {
"$ref" : "#/components/schemas/metabase.lib.schema.parameter..target.legacy-field-ref"
}, {
"$ref" : "#/components/schemas/metabase.lib.schema.parameter..target.legacy-field-ref"
}, {
"$ref" : "#/components/schemas/metabase.lib.schema.parameter..target.legacy-field-ref"
} ]
},
"metabase.lib.schema.parameter.template-tag" : {
@@ -6816,17 +7232,7 @@ redirect_from:
"prefixItems" : [ {
"const" : "template-tag"
}, {
"oneOf" : [ {
"type" : "object",
"properties" : {
"id" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
}
},
"required" : [ "id" ]
}, {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
} ]
"$ref" : "#/components/schemas/metabase.lib.schema.parameter..template-tag.tag-name"
} ]
},
"metabase.lib.schema.parameter.text-tag" : {
@@ -6853,6 +7259,7 @@ redirect_from:
} ]
},
"metabase.lib.schema.parameter.widget-type" : {
"description" : "The type of widget to display in the FE UI for the user to use to pick values for this parameter.",
"type" : "string",
"enum" : [ "none", "number", "text", "date", "boolean", "date/single", "id", "category", "location/city", "location/state", "location/zip_code", "location/country", "date/range", "date/month-year", "date/quarter-year", "date/relative", "date/all-options", "temporal-unit", "number/!=", "number/<=", "number/=", "number/>=", "number/between", "string/!=", "string/=", "string/contains", "string/does-not-contain", "string/ends-with", "string/starts-with", "boolean/=" ]
},
@@ -6977,6 +7384,9 @@ redirect_from:
"display-name" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"source-field-name" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"effective-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
@@ -7004,6 +7414,9 @@ redirect_from:
"temporal-unit" : {
"$ref" : "#/components/schemas/metabase.lib.schema.temporal-bucketing.unit"
},
"source-field-join-alias" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"semantic-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.semantic-or-relation-type"
}
@@ -7029,6 +7442,9 @@ redirect_from:
"display-name" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"source-field-name" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"effective-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.base-type"
},
@@ -7056,6 +7472,9 @@ redirect_from:
"temporal-unit" : {
"$ref" : "#/components/schemas/metabase.lib.schema.temporal-bucketing.unit"
},
"source-field-join-alias" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.non-blank-string"
},
"semantic-type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.common.semantic-or-relation-type"
}
@@ -7376,8 +7795,8 @@ redirect_from:
"enum" : [ "snippet", "card", "dimension", "number", "text", "date", "boolean", "temporal-unit" ]
},
"metabase.lib.schema.template-tag.widget-type" : {
"type" : "string",
"enum" : [ "none", "number", "text", "date", "boolean", "date/single", "id", "category", "location/city", "location/state", "location/zip_code", "location/country", "date/range", "date/month-year", "date/quarter-year", "date/relative", "date/all-options", "temporal-unit", "number/!=", "number/<=", "number/=", "number/>=", "number/between", "string/!=", "string/=", "string/contains", "string/does-not-contain", "string/ends-with", "string/starts-with", "boolean/=" ]
"description" : "Schema for valid values of `:widget-type` for a `:metabase.lib.schema.template-tag/field-filter` template tag.",
"$ref" : "#/components/schemas/metabase.lib.schema.parameter.widget-type"
},
"metabase.lib.schema.temporal-bucketing..unit.date" : {
"type" : "string",
@@ -8150,6 +8569,12 @@ redirect_from:
"parameters" : {
"$ref" : "#/components/schemas/metabase.parameters.schema.parameters"
},
"result_metadata" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata.lib-or-legacy-column"
}
},
"type" : {
"$ref" : "#/components/schemas/metabase.lib.schema.metadata..card.type"
}
@@ -8218,6 +8643,10 @@ redirect_from:
} ]
} ]
},
"metabase.query-processor.schema..result-metadata.column" : {
"description" : "A single result metadata column as returned by the Query Processor.",
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.legacy-column-metadata"
},
"metabase.query-processor.schema.export-format" : {
"description" : "Schema for valid export formats for downloading query results.",
"type" : "string",
@@ -10652,21 +11081,6 @@ redirect_from:
"pattern" : "^[A-Za-z0-9_\\-]{21}$"
} ]
}
}, {
"in" : "query",
"name" : "ignore_view",
"required" : false,
"schema" : {
"type" : "boolean"
}
}, {
"in" : "query",
"name" : "context",
"required" : false,
"schema" : {
"type" : "string",
"enum" : [ "collection" ]
}
}, {
"in" : "query",
"name" : "legacy-mbql",
@@ -15927,6 +16341,94 @@ redirect_from:
"tags" : [ "/api/ee/dependencies" ]
}
},
"/api/ee/dependencies/graph" : {
"get" : {
"summary" : "GET /api/ee/dependencies/graph",
"description" : "TODO: This endpoint is supposed to take an :id and :type of an entity (currently :table, :card, :snippet,\n or :transform) and return the entity with all its upstream and downstream dependencies that should be fetched\n recursively. :edges match our :model/Dependency format. Each node in :nodes has :id, :type, and :data, and :data\n depends on the node type. For :table, there should be :display_name. For :card, there should be :name\n and :type. For :snippet -> :name. For :transform -> :name.",
"parameters" : [ {
"in" : "query",
"name" : "id",
"required" : false,
"schema" : {
"type" : "integer",
"minimum" : 1
},
"description" : "value must be an integer greater than zero."
}, {
"in" : "query",
"name" : "type",
"required" : false,
"schema" : {
"type" : "string",
"enum" : [ "table", "card", "snippet", "transform" ]
}
} ],
"responses" : {
"2XX" : {
"description" : "Successful response"
},
"4XX" : {
"description" : "Client error response"
},
"5XX" : {
"description" : "Server error response"
}
},
"tags" : [ "/api/ee/dependencies" ]
}
},
"/api/ee/dependencies/graph/dependents" : {
"get" : {
"summary" : "GET /api/ee/dependencies/graph/dependents",
"description" : "TODO: This endpoint is supposed to take an :id and :type of an entity (currently :table, :card, :snippet,\n or :transform) and return the entity with all its upstream and downstream dependencies that should be fetched\n recursively. :edges match our :model/Dependency format. Each node in :nodes has :id, :type, and :data, and :data\n depends on the node type. For :table, there should be :display_name. For :card, there should be :name\n and :type. For :snippet -> :name. For :transform -> :name.",
"parameters" : [ {
"in" : "query",
"name" : "id",
"required" : true,
"schema" : {
"type" : "integer",
"minimum" : 1
},
"description" : "value must be an integer greater than zero."
}, {
"in" : "query",
"name" : "type",
"required" : true,
"schema" : {
"type" : "string",
"enum" : [ "table", "card", "snippet", "transform" ]
}
}, {
"in" : "query",
"name" : "dependent_type",
"required" : true,
"schema" : {
"type" : "string",
"enum" : [ "table", "card", "snippet", "transform" ]
}
}, {
"in" : "query",
"name" : "dependent_card_type",
"required" : false,
"schema" : {
"type" : "string",
"enum" : [ "question", "model", "metric" ]
}
} ],
"responses" : {
"2XX" : {
"description" : "Successful response"
},
"4XX" : {
"description" : "Client error response"
},
"5XX" : {
"description" : "Server error response"
}
},
"tags" : [ "/api/ee/dependencies" ]
}
},
"/api/ee/document/" : {
"get" : {
"summary" : "GET /api/ee/document/",
@@ -25429,7 +25931,7 @@ redirect_from:
"type" : "array",
"items" : {
"type" : "string",
"enum" : [ "dashboard", "table", "dataset", "segment", "collection", "document", "database", "action", "indexed-entity", "metric", "card" ]
"enum" : [ "dashboard", "table", "dataset", "segment", "collection", "transform", "document", "database", "action", "indexed-entity", "metric", "card" ]
}
}
}, {

View File

@@ -49,4 +49,4 @@ Metabase also has a paid version that ships with all of the bells and whistles (
- [Metabase Pro](https://www.metabase.com/product/pro)
- [Metabase Enterprise](https://www.metabase.com/product/enterprise)
You can self-host this paid version, or have have us host it for you on Metabase Cloud for no additional cost. We don't charge more because we believe you'll have such a better experience that it'll be easier for us to support you.
You can self-host this paid version, or have us host it for you on Metabase Cloud for no additional cost. We don't charge more because we believe you'll have such a better experience that it'll be easier for us to support you.

View File

@@ -26,7 +26,7 @@ Companies with large number of users can talk to sales about our [Enterprise pla
Though we bill you monthly, we calculate how much you owe each day. So, say you're on the [Starter plan](https://www.metabase.com/pricing/). Your monthly bill would include:
- $100 flat payment for the month. This payment additionally covers the first five people who use your Metabase that month. If you have fewer than five people using your Metabase, your bill will still be $100 that month.
- Each additional person costs \$6, prorated for how many days their [accounts were available](#what-counts-as-a-user-account) that month. So if an account only existed for the last 10 days of your 30 day billing period, you'd only be charged for those 10 days, not for the full 30 days. Same goes if you deactivated an account prior to the end of the billing period, you'll only be charged for the days when the account was available for use during that billing period. Basically, you only ever pay for all accounts in your Metabase that haven't been deactivated yet.
- Each additional person costs \$6, prorated for how many days their [accounts were available](#what-counts-as-a-user-account) that month. So if an account only existed for the last 10 days of your 30 day billing period, you'd only be charged for those 10 days, not for the full 30 days. Same goes if you deactivated an account before the end of the billing period, you'll only be charged for the days when the account was available for use during that billing period. Basically, you only ever pay for all accounts in your Metabase that haven't been deactivated yet.
## How annual billing works

View File

@@ -98,7 +98,7 @@ title: API changelog
When setting `archived` to `false`, you may optionally also provide a `collection_id` (for Dashboards or Cards) or a
`parent_id` (for Collections). In this case, the entity will be re-parented to the specified Collection when it is
moved from the Trash. If a new `collection_id` or `parent_id` is not provided, the entity will be moved back to its
original location if possible. If this is not possible (for example, the original location is also in the Trash) an
original location if possible. If this is impossible (for example, the original location is also in the Trash) an
error will occur.
- `/api/metric`
@@ -130,7 +130,7 @@ NOTE: These endpoint changes were added in 0.49.3, and a bug in `GET /api/embed/
The above endpoints now accept the `format_rows` query parameter. It is an optional boolean parameter that will default to `true` if not included in the request.
When `format_rows` is `true`, the export will have formatting applied such that the values match what they appear as in the app.
When `format_rows` is `false`, formatting is not applied and exports will behave as they did prior to 0.49.0.
When `format_rows` is `false`, formatting is not applied and exports will behave as they did before 0.49.0.
The value of `format_rows` has no effect when exporting xlsx files.

View File

@@ -48,6 +48,12 @@ title: Driver interface changelog
you can pass to [[metabase.lib.core/order-by]] -- for example a Lib `:metadata/column` or an [MBQL 5]
`metabase.driver-api.core/order-by-clause`.
- `metabase.driver-api.core/nest-query` no longer automatically calls `metabase.driver-api.core/add-alias-info` on its
results, but it also no longer expect its input to have this information. If you were using both of these tools in
your driver, make change the order in which the are applied so `nest-query` happens first, followed by
`add-alias-info`. Note that drivers deriving from `:sql` do not need to make any changes, since this is done by the
base `:sql` driver implementation.
## Metabase 0.56.3
- Added the driver multi-method `driver/describe-database*` that drivers should now implement instead of `driver/describe-database`.
@@ -100,7 +106,7 @@ title: Driver interface changelog
- Added a feature `:multi-level-schema` for drivers that support hierarchical levels between database and schema. Such as databricks' catalog. Defaults to false.
- Added the multi-method `adjust-schema-qualification` that allows drivers to to qualify, or unqualify table schemas based on enabling or disabling multi-level-schema support. Drivers may need to implement `sql.qp/->honeysql [driver ::h2x/identifier]` to properly quote fully qualified schemas.
- Added the multi-method `adjust-schema-qualification` that allows drivers to qualify, or unqualify table schemas based on enabling or disabling multi-level-schema support. Drivers may need to implement `sql.qp/->honeysql [driver ::h2x/identifier]` to properly quote fully qualified schemas.
- Added the multi-method `float-dbtype` which returns the name of the float type we coerce to for coercion strategies and the `float()` custom expression function.
@@ -241,7 +247,7 @@ title: Driver interface changelog
for better performance when saving Questions. Refer to the method docstring for more information and where to find
an example implementation.
- Prior to 0.51.0, to generate SQL queries with inline parameters, Metabase would generate a parameterized SQL string,
- Before 0.51.0, to generate SQL queries with inline parameters, Metabase would generate a parameterized SQL string,
then attempt to parse the SQL replace and replace `?` placeholders with inline values from the driver method
`metabase.driver.sql.util.unprepare/unprepare-value`. In 0.51.0+, Metabase instead generates these queries using
Honey SQL 2's `:inline` option, eliminating the need to parse and replace `?` placeholders. As such, the
@@ -319,7 +325,7 @@ title: Driver interface changelog
- Similarly, `metabase.test.data.sql-jdbc.execute/execute-sql!` and helper functions like
`metabase.test.data.sql-jdbc.execute/sequentially-execute-sql!` are now called with a `java.sql.Connection`
instead of both a `DatabaseDefinition` and either `:server` or `:db` _context_; the appropriate connection type is
created automatically and passed in in the calling code. Update your method implementations and usages
created automatically and passed in the calling code. Update your method implementations and usages
accordingly.
- Added method `metabase.test.data.interface/dataset-already-loaded?` to check if a test dataset has already been
@@ -452,7 +458,7 @@ title: Driver interface changelog
- New feature `:identifiers-with-spaces` has been added to indicate where a driver supports identifiers like table or
column names that contains a space character. Defaults to `false`.
- New feature `:uuid-type` has been added to indicate that this database is able to distinguish and filter against UUIDs.
- New feature `:uuid-type` has been added to indicate that this database can distinguish and filter against UUIDs.
Only a few database support native UUID types. The default is `false`.
## Metabase 0.49.22
@@ -576,7 +582,7 @@ title: Driver interface changelog
new function takes a Field as returned by `lib.metadata/field`, i.e. a `kebab-case` map.
- Tests should try to avoid using any of the `with-temp` helpers or application database objects; instead, use the
metadata functions above and and the helper _metadata providers_ in `metabase.lib`, `metabase.lib.test-util`, and
metadata functions above and the helper _metadata providers_ in `metabase.lib`, `metabase.lib.test-util`, and
`metabase.query-processor.test-util` for mocking them, such as `mock-metadata-provider`,
`metabase-provider-with-cards-for-queries`, `remap-metadata-provider`, and `merged-mock-metadata-provider`.
@@ -831,7 +837,7 @@ differences between the library versions.
#### Breaking Changes in 0.46.0 related to the Honey SQL 2 transition
**Note: these breaking changes will hopefully be fixed before 0.46.0 ships. This will be updated if they are.**
**Note: we expect these breaking changes to be fixed before 0.46.0 ships. This will be updated if they are.**
The classes `metabase.util.honeysql_extensions.Identifer` and `metabase.util.honeysql_extensions.TypedHoneySQLForm`
have been moved to `metabase.util.honey_sql_1.Identifer` and `metabase.util.honey_sql_1.TypedHoneySQLForm`,

View File

@@ -139,7 +139,7 @@ Documents work best for:
Dashboards work best for:
- Regular analysis. Numbers you want to keep an eye on every day, week, or month.
- Regular analysis. Numbers you want to monitor every day, week, or month.
- Filtering results across multiple charts.
- More control over presentation.

View File

@@ -22,16 +22,18 @@ Currently you can choose to embed:
- A question (chart). You can embed both questions built with the query builder and questions built with SQL.
- Full graphical [query builder](../questions/query-builder/editor.md) to enable people to build their own charts and explorations.
- A browser to navigate collections and open dashboards or questions.
- [AI chat interface](./sdk/ai-chat.md).
## Quickstart
You can also follow the setup guide directly in Metabase in **Admin > Embedding > Setup guide**. We're recording the steps here for convenience.
You can also follow the setup guide directly in Metabase in **Admin settings > Embedding > Setup guide**. We're recording the steps here for convenience.
### 1. Enable Embedded Analytics JS
1. In Metabase, go to **Admin > Embedding > Modular embedding**.
1. In Metabase, go to **Admin settings > Embedding > Modular embedding**.
2. Toggle on **Embedded Analytics JS**.
3. Under **Cross-Origin Resource Sharing (CORS)**, add the URLs of the websites where you want to embed Metabase (such as `https://*.example.com`). For testing embeds, you can use `localhost` which is always included in CORS policy.
4. If you are embedding Metabase components in a domain that's different from your Metabase's domain (including when you're testing the app locally but use Metabase Cloud), go to **Admin settings > Embedding > Security** and set **SameSite cookie** to **None**.
### 2. Create a new embed
@@ -40,10 +42,13 @@ You can also follow the setup guide directly in Metabase in **Admin > Embedding
If you're planning to embed an existing question or dashboard, you can instead go straight to that question or dashboard, click on the **Share** button, and choose **Embedded Analytics JS**.
2. Choose the _type_ of entity to embed:
- Dashboard
- Question
- Chart
- Exploration (which will embed the Metabase query builder)
- Browser
- Metabot question (which will embed AI chat)
3. Next, select the entity you want to embed. For browser, pick the collection you want people to start from.
Once you've selected what you want to embed, click Next to customize your embed.
@@ -54,7 +59,7 @@ The exact customization options you see will depend on what type of entity you'r
![Customizing embeds](./images/embed-flow-options.png)
You'll also be be able to pick brand, text, and background color used for all your embeds. To configure other colors (e.g. secondary colors, query builder colors etc), as well as font, you can specify a [theme](#theming) in your embed code snippet.
You'll also be able to pick brand, text, and background color used for all your embeds. To configure other colors (e.g. secondary colors, query builder colors etc), as well as font, you can specify a [theme](#theming) in your embed code snippet.
All the customization options you select in this interactive flow will be reflected in the parameter values in the embed code, so you'll be able to adjust them later by editing the embed snippet.
@@ -124,7 +129,7 @@ Here's an example of a script:
Note the `defer` attribute and the reference to your Metabase URL in the script that loads `embed.js` library.
If you're embedding multiple entities on the same page, you only need to include the `<script>` tags once globally.
If you're embedding multiple entities in a single page, you only need to include the `<script>` tags once globally.
You can also generate the code snippet for Embedded Analytics JS interactively in Metabase through **Admin > Embedding > Setup guide > Embed in your code**. Check out the [quickstart](#quickstart).
@@ -150,7 +155,7 @@ When you're creating a new embed using **Admin > Embedding > Setup guide > Embed
To define the configuration that applies to every embed on the page, use the `defineMetabaseConfig()` function. Its parameters include:
- `instanceUrl: "https://your-metabase-url"` (required): the URL of your Metabase instance, like https://youlooknicetoday.metabaseapp.com
- `instanceUrl: "https://your-metabase-url"` (required): the URL of your Metabase instance, like `https://youlooknicetoday.metabaseapp.com`
- `theme: {...}` (optional): [appearance options for the embeds](#theming).
@@ -354,7 +359,7 @@ To render a dashboard:
### Question
To render a question (chart).
To render a question (chart):
```html
<metabase-question question-id="1"></metabase-question>
@@ -375,9 +380,9 @@ To render a question (chart).
- `is-save-enabled` (default is false)
- `target-collection` - this is to enforce saving into a particular collection. Values: regular ID, entity ID, `"personal”`, `"root”`
- ### Browser
### Browser
To render a collection browser so people can navigate a collection and open dashboards or questions.
To render a collection browser so people can navigate a collection and open dashboards or questions:
```html
<metabase-browser initial-collection="14" read-only="false"></metabase-browser>
@@ -390,3 +395,40 @@ To render a collection browser so people can navigate a collection and open dash
**Optional parameters:**
- `read-only` (default is true) – if true, people can interact with items (filter, summarize, drill-through) but cannot save. If false, they can create and edit items in the collection.
### Metabot
To render the AI chat interface:
```html
<metabase-metabot></metabase-metabot>
```
**Required parameters:**
None.
**Optional parameters:**
- `layout` (default is `auto`) – how should the browser position the visualization with respect to the chat interface. Possible values are:
- `auto` (default): Metabot uses the `stacked` layout on mobile screens, and a `sidebar` layout on larger screens.
- `stacked`: the question visualization stacks on top of the chat interface.
- `sidebar`: the question visualization appears to the left of the chat interface, which is in the right sidebar.
## Embedding Metabase in a different domain
If you want to embed Metabase in another domain (say, if Metabase is hosted at `metabase.yourcompany.com`, but you want to embed Metabase at `yourcompany.github.io`), you can tell Metabase to set the session cookie's SameSite value to "none".
You can set session cookie's SameSite value in **Admin settings** > **Embedding** > **Security** > **SameSite cookie setting**.
SameSite values include:
- **Lax** (default): Allows Metabase session cookies to be shared on the same domain. Used for production instances on the same domain.
- **None (requires HTTPS)**: Use "None" when your app and Metabase are hosted on different domains. Incompatible with Safari and iOS-based browsers.
- **Strict** (not recommended): Does not allow Metabase session cookies to be shared with embedded instances. Use this if you do not want to enable session sharing with embedding.
You can also set the [`MB_SESSION_COOKIE_SAMESITE` environment variable](../configuring-metabase/environment-variables.md#mb_session_cookie_samesite).
If you're using Safari, you'll need to [allow cross-site tracking](https://support.apple.com/en-tj/guide/safari/sfri40732/mac). Depending on the browser, you may also run into issues when viewing emdedded items in private/incognito tabs.
Learn more about [SameSite cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite).

View File

@@ -34,7 +34,7 @@ Check out the [Interactive embedding quick start](./interactive-embedding-quick-
If you're dealing with a [multi-tenant](https://www.metabase.com/learn/metabase-basics/embedding/multi-tenant-self-service-analytics) situation, check out our recommendations for [Configuring permissions for different customer schemas](../permissions/embedding.md).
If you have your app running locally, and you're using the Pro Cloud version, or hosting Metabase and your app in different domains, you'll need to set your Metabase environment's session cookie samesite option to "none".
If you have your app running locally, and you're using the Pro Cloud version, or hosting Metabase and your app in different domains, you'll need to set your Metabase environment's session cookie SameSite option to "none".
## Enabling interactive embedding in Metabase
@@ -128,13 +128,13 @@ Note that your interactive embed must be compatible with Safari to run on _any_
If you want to embed Metabase in another domain (say, if Metabase is hosted at `metabase.yourcompany.com`, but you want to embed Metabase at `yourcompany.github.io`), you can tell Metabase to set the session cookie's SameSite value to "none".
You can set session cookie's SameSite value in **Admin settings** > **Embedding** > **Interactive** > **SameSite cookie setting**.
You can set session cookie's SameSite value in **Admin settings** > **Embedding** > **Security** > **SameSite cookie setting**.
SameSite values include:
- **Lax** (default): Allows cookies to be sent when someone navigates to the origin site from an external site (like when following a link).
- **None**: Allows all cross-site requests. Incompatible with most Safari and iOS browsers, such as Chrome on iOS. If you set this environment variable to "None", you must use HTTPS in Metabase to prevent browsers from rejecting the request.
- **Strict** (not recommended): Never allows cookies to be sent on a cross-site request. Warning: this will prevent users from following external links to Metabase.
- **Lax** (default): Allows Metabase session cookies to be shared on the same domain. Used for production instances on the same domain.
- **None (requires HTTPS)**: Use "None" when your app and Metabase are hosted on different domains. Incompatible with Safari and iOS-based browsers.
- **Strict** (not recommended): Does not allow Metabase session cookies to be shared with embedded instances. Use this if you do not want to enable session sharing with embedding.
You can also set the [`MB_SESSION_COOKIE_SAMESITE` environment variable](../configuring-metabase/environment-variables.md#mb_session_cookie_samesite).

View File

@@ -9,7 +9,7 @@ redirect_from:
> Only admins can create public links and iframes.
Admins can create and share public links (URLs) for questions and dashboards. People can view them as standalone destinations (URLs) or as embedded iframes in another page or app. In both cases, the public item will display static (view-only) results of your question or dashboard, so visitors won't be able to drill-down into the underlying data on their own.
Admins can create and share public links (URLs) for questions and dashboards. People can view them as standalone destinations (URLs) or as embedded iframes in another page or app. In both cases, the public item will display static (view-only) results of your question or dashboard, so visitors won't be able to drill down into the underlying data on their own.
## Create a public link for a question

View File

@@ -25,6 +25,10 @@ You can check out a [demo of the AI chat component](https://embedded-analytics-s
{% include_file "{{ dirname }}/snippets/questions/ai-question.tsx" %}
```
## Props
{% include_file "{{ dirname }}/api/snippets/MetabotQuestionProps.md" snippet="properties" %}
## API reference
- [Component](./api/MetabotQuestion.html)

View File

@@ -102,7 +102,7 @@ From any Metabase page, click on the **gear** icon in the upper right and select
Turn on:
- Embedded analytics SDK (it's in in the **Modular** section)
- Embedded analytics SDK (it's in the **Modular** section)
- Static embedding
Otherwise, this whole thing is hopeless.

View File

@@ -65,6 +65,9 @@ const theme = defineMetabaseTheme({
// Color used to indicate dangerous actions and negative values/trends
negative: "#FF7979",
/** Color used to outline elements in focus */
focus: "#CAE1F7",
/** Color used for popover shadows */
shadow: "rgba(0,0,0,0.08)",

View File

@@ -51,7 +51,7 @@ yarn add @metabase/embedding-sdk-react@{next-major-version-number}-stable
See more on [SDK versions](./version.md).
### If there are deprecations or breaking changes changes, make the necessary changes to your application code
### If there are deprecations or breaking changes, make the necessary changes to your application code
Deprecations or breaking changes are rare, but if you do need to make changes, we'll mention it in the release notes for the new major version and have docs that walk you through the changes.

View File

@@ -174,7 +174,8 @@ This key is shared across all static embeds. Whoever has access to this key coul
Dashboards are a fixed aspect ratio, so if you'd like to ensure they're automatically sized vertically to fit their contents you can use the [iFrame Resizer](https://github.com/davidjbradshaw/iframe-resizer) script. Metabase serves a copy for convenience:
```html
<script src="https://metabase.example.com/app/iframeResizer.js"></script>
<script src="{your-metabase-url}/app/iframeResizer.js"></script>
<iframe
src="https://metabase.example.com/embed/dashboard/TOKEN"
onload="iFrameResize({}, this)"

View File

@@ -1,10 +1,11 @@
---
title: Delete and restore
summary: You can move questions, dashboards, models, and metrics to Trash where they can be restored or permanently deleted. Deleting items affects related content like dashboards and subscriptions. Other entities in Metabase can be deleted or archived, but won't show up in Trash.
---
# Delete and restore
Sometimes your questions, dashboards, models, or collections outlive their usefulness. You can send outdated items to **Trash**.
Sometimes your questions, dashboards, models, metrics, or collections outlive their usefulness. You can send outdated items to **Trash**.
![Move to trash](./images/move-to-trash.png)
@@ -104,7 +105,7 @@ What happens to related items when you delete a collection?
| ---------------------------------------------- | -------- | ------------------- | -------- |
| All items and subcollections in the collection | In Trash | N/A | Restored |
> You can't permanently delete collections
> You can't permanently delete collections.
## Permanently deleting items
@@ -117,7 +118,7 @@ To permanently delete an item:
3. Click on the checkbox next to the item to select it;
4. Select "Permanently delete". If you click this button, you won't be able to recover the item. It'll be lost to the void.
> You can't permanently delete collections
> You can't permanently delete collections.
## Deleting and restoring events and timelines
@@ -131,13 +132,11 @@ Snippets can be archived and unarchived. See [Archiving snippets](../questions/n
## Deleting segments
Segments can be retired. See [Retiring Segments](../data-modeling/segments.md#editing-and-retiring-segments).
You won't see retired Segments in Trash.
Segments can be retired. See [Retiring Segments](../data-modeling/segments.md#editing-and-retiring-segments). You won't see retired Segments in Trash.
## Deleting subscriptions and alerts
See [Deleting a subscription](../dashboards/subscriptions.md#deleting-a-subscription) and [Deleting alerts](../questions/alerts.md#editing-and-deleting-alerts).
See [Deleting a subscription](../dashboards/subscriptions.md#deleting-a-subscription) and [Deleting alerts](../questions/alerts.md#editing-deleting-and-unsubscribing-from-alerts).
## Deleting databases

View File

@@ -26,7 +26,7 @@ View changes to a question, dashboard or model and revert to previous versions.
## [Delete and restore items](./delete-and-restore.md)
Move outdated outdated questions, models, and dashboards to trash, or delete them permanently.
Move outdated questions, models, and dashboards to trash, or delete them permanently.
## [Data reference](./data-model-reference.md)

View File

@@ -117,7 +117,7 @@ If you've already been running Metabase with the default application database (H
Here's an example `docker-compose.yml` file for running Metabase with a PostgreSQL database `metabaseappdb`:
> This is an example file and and is not meant to be used when running Metabase in a production environment. Please refer to our guide about [How to run Metabase in production](https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation/metabase-in-production)
> This is an example file and is not meant to be used when running Metabase in a production environment. Please refer to our guide about [How to run Metabase in production](https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation/metabase-in-production)
```yml
services:
@@ -343,7 +343,7 @@ We currently support the following [environment variables](../configuring-metaba
In order for the Metabase container to read the files and use the contents as a secret, the environment variable name needs to be appended with a "\_FILE" as explained above.
> This is an example file and and is not meant to be used when running Metabase in a production environment. Please refer to our guide about [How to run Metabase in production](https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation/metabase-in-production).
> This is an example file and is not meant to be used when running Metabase in a production environment. Please refer to our guide about [How to run Metabase in production](https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation/metabase-in-production).
## Troubleshooting

View File

@@ -117,7 +117,7 @@ If you've already been running Metabase with the default application database (H
### Running Metabase as a service
We can use the [systemd](https://systemd.io/) initialization service to register a Metabase service that can be started and stopped automatically. Prior to executing this process, ensure that the Metabase container is operational. Then, utilize Podman's built-in feature to generate the service file as follows:
We can use the [systemd](https://systemd.io/) initialization service to register a Metabase service that can be started and stopped automatically. Before executing this process, ensure that the Metabase container is operational. Then, utilize Podman's built-in feature to generate the service file as follows:
```
sudo podman generate systemd --new --name metabase > metabase.service

View File

@@ -50,7 +50,7 @@ To add a user attribute manually:
4. Click **+ Add an attribute**.
5. Add the name of the user attribute under "Key". For example, "Department".
6. Add the value that applies to the specific person. For example, "Engineering".
7. Optional: [create a group](#creating-a-group) to organize people who will get get row and column security.
7. Optional: [create a group](#creating-a-group) to organize people who will get row and column security.
8. Add the person to the group.
You can also sync user attributes from your identity provider [via SSO](./start.md#authentication).

View File

@@ -6,14 +6,22 @@ title: Impersonation access
{% include plans-blockquote.html feature="Impersonation access" %}
> For now, impersonation access is only available for ClickHouse, MySQL, PostgreSQL, Redshift, Snowflake, and SQL Server. If you want to switch database _connections_ based on who is logged in, check out [Database routing](./database-routing.md).
> If you're using views in PostgresSQL, the row-level security policies on views will only work on Postgres versions 15 and higher.
This page covers the [View data](./data.md#view-data-permissions) permission level called Impersonation.
**Impersonation access** allows admins to "outsource" View data permissions to roles in your database. Admins can associate user attributes with database-defined roles and their privileges. If someone is in a group with their View data permission set to Impersonation, the person will be able to view and query data based on the privileges granted to the role specified by their user attribute.
## Databases that support impersonation
For now, impersonation access is only available for the following databases:
- ClickHouse
- MySQL
- PostgreSQL. If you're using views in PostgresSQL, the row-level security policies on views will only work on Postgres versions 15 and higher.
- Redshift
- Snowflake
- SQL Server.
If you want to switch database _connections_ based on who is logged in, check out [Database routing](./database-routing.md).
## Impersonation vs row and column security
### Impersonation sets permissions for questions written in both the SQL editor and the query builder
@@ -39,7 +47,7 @@ For impersonation access to work, you'll first need to set up roles in your data
### Set up Metabase database connection for impersonation
Impersonation uses database roles to run queries on your database, but there still needs to be a default role that that will be used to run operations like [sync, scans, and fingerprinting](../databases/sync-scan.md). So the user account that Metabase uses to [connect to your database](../databases/connecting.md) should have access to everything in that database that any Metabase group may need access to, as that database user account is what Metabase uses to sync table information.
Impersonation uses database roles to run queries on your database, but there still needs to be a default role that will be used to run operations like [sync, scans, and fingerprinting](../databases/sync-scan.md). So the user account that Metabase uses to [connect to your database](../databases/connecting.md) should have access to everything in that database that any Metabase group may need access to, as that database user account is what Metabase uses to sync table information.
You can then create roles in the database that have more restrictive access to the database (like row-level or table-level security). When the role is passed to the database using impersonation, the engine will return a subset of the data, or restrict the query altogether.
@@ -111,7 +119,7 @@ People in one group can have different attribute values, but must have the same
1. In Metabase, hit Cmd/Ctrl + K to bring up the command palette and search for **Permissions**, or go directly to **Admin settings** > **Permissions** > **Data**.
2. Select the group that you want to to associate with the database role you created.
2. Select the group that you want to associate with the database role you created.
3. Select the database to configure access to.

View File

@@ -29,13 +29,16 @@ Only admins and people with [settings access](../permissions/application.md#sett
To create an alert:
1. Save your question.
2. Click on the sharing icon in the top-right of the screen.
2. Click on the **three dots** in the top-right of the screen.
3. Select **Create an alert**.
4. Select what you want to be alerted about. The alert options will depend on the question's visualization. See [types of alerts](#types-of-alerts).
5. Select when you want Metabase to check the results. Metabase can check for results by the minute, hourly, daily, weekly, monthly, or on a custom schedule that you set using the Quartz [cron syntax](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html).
6. Select the alert's destination: [email](../configuring-metabase/email.md), [Slack](../configuring-metabase/slack.md), or to a [webhook](../configuring-metabase/webhooks.md) (only admins and people with [settings access](../permissions/application.md#settings-access) can create and send to webhooks).
7. Configure any other options (like [only sending the alert once](#send-a-one-time-alert)).
8. Click **Done**.
4. Select what you want to be alerted about (options depend on the question type):
- [When a question returns a result](#results-alerts) - for any question.
- [When a time series crosses a goal line](#goal-line-alerts) - for a line, bar, or area chart displaying a time series.
- [When a progress bar reaches or goes below its goal](#progress-bar-alerts) - for progress bars.
6. Select when you want Metabase to check the results: by the minute, hourly, daily, weekly, monthly, or on a custom schedule that you set using the Quartz [cron syntax](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html).
7. Select the alert's destination: [email](../configuring-metabase/email.md), [Slack](../configuring-metabase/slack.md), or to a [webhook](../configuring-metabase/webhooks.md) (only admins and people with [settings access](../permissions/application.md#settings-access) can create and send to webhooks).
8. Configure any other options (like [only sending the alert once](#send-a-one-time-alert)).
9. Click **Done**.
## Send a one-time alert
@@ -47,12 +50,6 @@ To test the alert, first make sure that the question returns results (if the que
Then hit the **Send now** button to trigger the alert.
## Types of alerts
- [Results alerts](#results-alerts): when a question returns any result.
- [Goal line alerts](#goal-line-alerts) when a time series crosses a goal line.
- [Progress bar alerts](#progress-bar-alerts): when a progress bar reaches or goes below its goal.
## Results alerts
Metabase can send you an alert on a schedule when one of your questions returns _any_ result. This kind of alert is also particularly useful if you have a question that doesn't _usually_ return any results, but you want to know when the question _does_ return results.
@@ -69,27 +66,22 @@ _Requires a [bar, line, or area chart](./visualizations/line-bar-and-area-charts
Goal line alerts are useful when you're doing things like tracking daily active users (DAU) and you want to know when you reach a certain number of DAU, or when you're tracking orders per week and you want to know whenever the number of orders ever goes below a certain threshold.
To start, you'll need a line, area, or bar chart displaying a number over time.
To create an alert when a time series crosses a goal line:
Next, you need to set up a goal line on your chart. Open up the visualization settings by clicking the **gear** icon in the bottom-left. Then click on the **Display** tab, and turn on the **Show goal** setting. Choose a value for your goal (and optionally a label) and click Done.
1. Create a line, area, or bar chart displaying a number over time.
2. Open up the visualization settings by clicking the **gear** icon in the bottom-left.
3. In the **Display** tab, turn on the **Show goal** setting.
4. Choose a value for your goal (and optionally a label) and click Done.
5. Save the question.
6. Click the **three dots** icon in top and select "Create alert"
You can choose:
You can choose:
- Whether you want Metabase to alert you when the time series goes above the goal line or when it goes below the goal line.
- Whether you want Metabase to alert you every time the time series crosses a goal line, or only the first time it crosses the goal line.
- How often you want Metabase to check to see if the goal line has been crossed.
- Whether you want Metabase to alert you when the time series goes above the goal line or when it goes below the goal line.
- Whether you want Metabase to alert you every time the time series crosses a goal line, or only the first time it crosses the goal line.
- How often you want Metabase to check to see if the goal line has been crossed.
Click Done, and your alert will be all set up!
If you need to edit or unsubscribe from the alert you set up, just click that same icon. You'll see the Edit and Unsubscribe buttons. This is also where you'll see alerts about this question that admins might have added you to.
Metabase will email you when:
- You set up an alert
- You've been unsubscribed from an alert
- One of your alerts has stopped working
- You unsubscribed from an alert
- An admin added you to an alert
7. Select the schedule and recepients for the alert, and click "Done"
## Progress bar alerts
@@ -97,11 +89,11 @@ _Requires the [progress bar visualization](./visualizations/progress-bar.md)._
If you want to set up an alert when a single number reaches a goal, you can use a progress bar visualization.
1. Create a question that returns a single number as its result,
2. Choose the Progress Bar chart type,
3. In Visualization settings, select a goal value
4. Save your question,
5. Create an alert by clicking on the Sharing icon in top right
1. Create a question that returns a single number as its result.
2. Choose the Progress Bar chart type.
3. In Visualization settings, select a goal value.
4. Save your question.
5. Create an alert by clicking the **three dots** in top right.
You'll see the options for when you want to get alerts about this progress bar:
@@ -109,9 +101,9 @@ You'll see the options for when you want to get alerts about this progress bar:
- Whether to alert only the first time the progress bar reaches the goal line, or every time
- How often you want Metabase to check to see if the goal has been reached.
## Editing and deleting alerts
## Editing, deleting, and unsubscribing from alerts
To edit or delete alerts on a question, click on the Sharing icon in the top right corner. What you can edit depends on whether you're an admin.
To edit or delete alerts on a question, click on the **three dots** icon in the top right corner and select **Edit alerts**. What you can edit depends on whether you're an admin.
Everyone:
@@ -124,6 +116,14 @@ Admins:
- Admins can add or remove recipients on any alert, even ones that they didn't create themselves.
- Admins can bulk manage alerts per person from the [People menu in Admin settings](../people-and-groups/managing.md#unsubscribe-from-all-subscriptions-and-alerts).
Metabase will email you when:
- You set up an alert
- You've been unsubscribed from an alert
- One of your alerts has stopped working
- You unsubscribed from an alert
- An admin added you to an alert
## Avoid changing the name of the alerted channel in Slack
Once you set up an alert to a Slack channel, avoid changing the name of that channel in Slack. If you rename the channel in Slack, but you want Metabase to continue to send alerts to that renamed channel, you'll need to update the alert in Metabase to point to the new channel name.

View File

@@ -61,7 +61,7 @@ If you use a datetime dimension in the **Group by** block, Metabase will accumul
![Cumulative count by category, source, and created at](../../images/cumulative-date-category.png)
If there are multiple datetime dimensions (including multiple groupings by the same datetime column), Metabase will accumulate along the the more granular dimension, regardless of their order. For example, if you're grouping by "Created At: Month" and "Viewed At: Week", Metabase will accumulate along "Viewed At: Week".
If there are multiple datetime dimensions (including multiple groupings by the same datetime column), Metabase will accumulate along the more granular dimension, regardless of their order. For example, if you're grouping by "Created At: Month" and "Viewed At: Week", Metabase will accumulate along "Viewed At: Week".
![Cumulative count by two datetime fields](../../images/cumulative-multiple-datetimes.png)

View File

@@ -91,5 +91,5 @@ Here's an incomplete list of example functions:
| -------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Postgres | `EXTRACT(WEEK FROM TIMESTAMP created_at)` | ISO algorithm |
| MySQL | `WEEKOFYEAR("2017-06-15")` | The first day of the week is Monday and the first week of the year has more than 3 days. Alternative functions exist. |
| BigQuery | `EXTRACT(WEEK FROM DATE ticreated_at)` | Weeks numbered from 0. Dates prior to the first Sunday of the year are in week 0. Alternative functions exist. |
| BigQuery | `EXTRACT(WEEK FROM DATE ticreated_at)` | Weeks numbered from 0. Dates before the first Sunday of the year are in week 0. Alternative functions exist. |
| Redshift | `DATE_PART(week, TIMESTAMP created_at)` | ISO algorithm |

View File

@@ -36,7 +36,7 @@ By default, Metabase will present steps in the same order as they appear in the
To create a query with a result that has the shape required for a funnel chart, you'll probably need to summarize your data.
If your (original, unaggregated) data already contains a field with the the step for every data point, you can build a simple query with a breakout by steps:
If your (original, unaggregated) data already contains a field with the step for every data point, you can build a simple query with a breakout by steps:
![A query in the query builder used to build a funnel chart](../images/build-a-funnel-query.png)

View File

@@ -2,7 +2,7 @@
title: Maps
redirect_from:
- /docs/latest/questions/sharing/visualizations/maps
description: "Maps in Metabase allow you to visualize geographical data either using coordinates or by region. Metabase gives you three types of maps : pin map for unaggregated data, grid map for histograms, and region map for distributions by regions like countries or states. You can also create custom maps."
description: "Maps in Metabase allow you to visualize geographic data either using coordinates or by region. Metabase gives you three types of maps : pin map for unaggregated data, grid map for histograms, and region map for distributions by regions like countries or states. You can also create custom maps."
---
# Maps
@@ -13,7 +13,7 @@ Metabase has three types of map visualization:
- [**Grid map**](#grid-map) for distributing a large number of points over a specified area.
- [**Region map**](#region-maps) for data broken out by regions, like countries or states. Metabase comes with two built-in maps, but you can upload your own custom regions.
When you select the **Map** visualization setting, Metabase will automatically try and pick the best kind of map to use based on the table or result set, as long as the columns with the geographical data have the [right metadata](../../data-modeling/metadata-editing.md).
When you select the **Map** visualization setting, Metabase will automatically try and pick the best kind of map to use based on the table or result set, as long as the columns with the geographic data have the [right metadata](../../data-modeling/metadata-editing.md).
![Map types](../images/map-types.png)
@@ -21,7 +21,7 @@ When you select the **Map** visualization setting, Metabase will automatically t
## Pin map
Pin maps display markers or tiles for individual data points on the map. They work best for displaying small amounts of unaggregated geographical data.
Pin maps display markers or tiles for individual data points on the map. They work best for displaying small amounts of unaggregated geographic data.
### Pin map data shape
@@ -59,11 +59,11 @@ To change the pin type:
By default, maps can't display more than 2,000 individual unaggregated data points, regardless of the pin type. This limit is the same for every chart displaying unaggregated data in Metabase. To increase the number of data points rendered on charts based on unaggregated queries, you can use the environment variable [`MB_UNAGGREGATED_QUERY_ROW_LIMIT`](../../configuring-metabase/environment-variables.md#mb_unaggregated_query_row_limit). This setting will affect data points on _all_ charts—not just the pin maps—so increasing the limit too much could significantly slow down your Metabase and your browswer.
If you need to display a large number of geographical data points, consider using a grid map to display the distribution instead.
If you need to display a large number of geographic data points, consider using a grid map to display the distribution instead.
## Grid map
Grid map is an aggregated version of the pin map — like a heatmap for the distribution of pins. Grid map breaks the the map into a grid based on latitude/longitude, and then colors each grid cell based on how many data points fall in it.
Grid map is an aggregated version of the pin map — like a heatmap for the distribution of pins. Grid map breaks the map into a grid based on latitude/longitude, and then colors each grid cell based on how many data points fall in it.
![Grid map](../images/grid-map.png)

View File

@@ -14,7 +14,7 @@ A **pie chart** can be used when breaking out a metric by a single dimension. In
Pie charts can be used to visualize a metric as part of a whole. Sunburst charts can be used to visualize hierarchical or nested data, or display multiple levels of categorization.
Pie and sunburst charts work best when when the number of possible breakout values is small, like accounts by plan. These charts should only be used to visualize metrics that add up to 100% (like count or sum of total).
Pie and sunburst charts work best when the number of possible breakout values is small, like accounts by plan. These charts should only be used to visualize metrics that add up to 100% (like count or sum of total).
Pie charts should be used to communicate a general sense of the relative sizes of breakouts. If precise comparison is important so people can see the exact differences between values, or you have more than a few breakouts (like customers per country), it's usually better to use a bar or row chart.

View File

@@ -102,4 +102,4 @@ There are special considerations when exporting pivot tables as XLSX files. See
- Pivot tables are only available for questions built with the query builder.
- The query builder question must have a summary block.
If you must use SQL, and your SQL query does not have parameters, you can save that SQL query , then use its [results as the starting point](../native-editor/writing-sql.md#explore-sql-question-results-using-the-query-builder) for a query builder question in order to build a question. The trick here is to do your aggregation and grouping in the query builder. That is, use the SQL question to grab the raw data you want to work with (maybe [create a model](../../data-modeling/models.md)), then start a new question in the query builder to filter, summarize, and group that data.
If you must use SQL, and your SQL query doesn't have parameters, you can save that SQL query , then use its [results as the starting point](../native-editor/writing-sql.md#explore-sql-question-results-using-the-query-builder) for a query builder question in order to build a question. The trick here is to do your aggregation and grouping in the query builder. That is, use the SQL question to grab the raw data you want to work with (maybe [create a model](../../data-modeling/models.md)), then start a new question in the query builder to filter, summarize, and group that data.

View File

@@ -12,7 +12,7 @@ redirect_from:
## When to use a progress bar
Progress bars are useful when you want to show the movement of a metric toward a goal, like assessing performance of a KPI, or tracking the percentage of of completion on a project.
Progress bars are useful when you want to show the movement of a metric toward a goal, like assessing performance of a KPI, or tracking the percentage of completion on a project.
Progress bars give you an option to set up an alert whenever the result of a question reaches the goal set in the progress bar settings. See [Progress bar alerts](../alerts.md#progress-bar-alerts).

View File

@@ -26,6 +26,6 @@ Or you could display one of the metrics on the chart, and include the other metr
Removing a metric will give you the option to add it as an additional metric to the tooltip. In the visualization settings, click on the **Display** tab, and add **Additional tooltip metrics**. Only metrics included in the summarization step of the question are available to add to the tooltip.
![Add additional tooltip metrics from the display tab. Only available when your chart has multiple multiple metrics](../images/metrics-in-tooltip.png)
![Add additional tooltip metrics from the display tab. Only available when your chart has multiple metrics](../images/metrics-in-tooltip.png)
Here we've kept the count on the chart, but now when you hover over a bar on the chart, the tooltip also includes the relevant average.

View File

@@ -128,13 +128,11 @@
"redux-auth-wrapper": "^2.1.0",
"redux-promise": "^0.6.0",
"redux-undo": "^1.1.0",
"regenerator-runtime": "^0.14.1",
"rehype-external-links": "^2.0.1",
"remark-gfm": "1.0.0",
"reselect": "^5.1.0",
"resize-observer-polyfill": "^1.5.1",
"screenfull": "^6.0.2",
"scroll-into-view-if-needed": "^3.1.0",
"server-text-width": "^1.0.2",
"simple-statistics": "^3.0.0",
"slugg": "^1.2.1",

View File

@@ -49,6 +49,7 @@ const CypressBackend = {
MB_DB_CONNECTION_URI: "", // ignore connection URI in favor of the db file
MB_CONFIG_FILE_PATH: "__cypress__", // ignore config.yml
MB_HTTP_CHANNEL_HOST_STRATEGY: "allow-all", // we use a local webhook service for testing
MB_IS_CYPRESS: "true", // custom flag so we can detect we're running in Cypress, used in tests.
};
/**

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