Compare commits

...

959 Commits

Author SHA1 Message Date
Nicola Mometto
5a43b2d35f further branch 2026-02-03 14:19:38 +00:00
Nicola Mometto
832f8ac44d wip: force run 2026-02-03 13:47:51 +00:00
Nicola Mometto
88bdc6c06c test other branch 2026-02-03 13:47:41 +00:00
Nicola Mometto
bdfc24938c wip: test pyarrow parsing 2026-01-28 09:54:26 +00:00
Romeo Van Snick
123f2dafd2 MBQL lib helpers for e2e tests (#68278)
* Rename file containing jsx to .jsx

* Add e2e helpers to build metadata provider

* Split up metadata helpers

* WIP

* Add more direct createTestQuestion helper

* Replace test

* Build cljs for tests

* Export type

* Only require entities in the state for getMetadata

* Just pass state to getMetadata

* Move EntitiesSchema to metabase/schema

* Wrap mbql e2e helpers in promise

* Split off getMetadataWithoutSettings

* Use getMetadataWithoutSettings to get metadata from state

* Build entities state manually

* Simplify wrapper

* Fix metadataProvider

* Add createTestJsQuery wrapper for cypress

* Use plain promises and fetch

* Allow passing GetMetadataOpts to createTest(Native)JsQuery directly

* Improve createTestQuestion types

* Make use of createTestJsQuery in test

* Reduce nest in createTestQuestion

* Use simplified createTestQuestion

* Split up mbql helpers

* Fix card metadata call

* Use correct card endpoint

* Pass missing options

* Convert another more complex test to createTestQuestion

* Fix types

* Use static ids for defaults to avoid import loop

* Fetch more tables by default

* Build cljs in embedding tests

* Build cljs in component tests

* Prepare backend env

* Add plugin so we can avoid building CLJS everywher

* Avoid building cljs where not needed

* Fix types

* Rename query helpers

* Split up helpers

* Compile cljs in stress tests
2026-01-26 19:54:16 +11:00
metabase-bot[bot]
16504fd3c8 [chore] Update E2E test timings with recent data (#68665)
Update E2E test timings with averaged data

Collected timing data from 7 days of test runs.
All specs with timing data were included (simple averages).

🤖 Generated automatically by update-e2e-timings workflow

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Actions <actions@github.com>
2026-01-26 21:50:07 +13:00
Romeo Van Snick
997b8d898e Respect abbreviate date style and be defensive around missing settings (#68661)
* Respect date_abbreviate when formatting date

* Respect abbreviate setting in month format too

* Add unit tests for abbreviated formats

* Add unit test for empty formatting settings

* Add repro for metabase#68574

* Add formatting settings unit tests
2026-01-26 15:50:42 +11:00
Alexander Polyankin
ceb518ab4b Dependency diagnostics - update the url, reset page on filter change, fix visibility checks (#68650) 2026-01-25 21:53:08 -05:00
Fraser
0ed6c4deed Link Claude Bugfix PR to Linear issue (#67710) 2026-01-26 10:44:24 +13:00
Sloan Sparger
6c09fca355 Fix NativeQueryEditor's action buttons (#68638)
fix position of buttons for native query editor
2026-01-24 20:34:41 +00:00
Aleksandr Lesnenko
049526c61c Cleanup (#68648)
cleanup
2026-01-24 09:40:18 -06:00
William
a799178420 Python transforms have dependencies (#68572)
The existing transform dependencies code only worked with query-based transforms (mbql or native).  This extends that
code to work with python transforms as well.
2026-01-24 02:34:24 -06:00
Maksym Yakubych
f7b82d5c54 fix: word wrap overflows row when reordering in dashboard table card (#68566) 2026-01-24 00:37:00 -03:00
Anderson
a51d1179d3 Disallow editing transforms when remote sync is read-only (#68380)
* Read-only: Adjust transform header menu options / Remove edit definition button / Run tab updates

* Make Settings tab read-only

* fix remote sync setup in e2e test

* Do not allow creating a new transform

* Make Python library not editable

* Hide edit definition in mbql transform view page

* Fix e2e

* Group e2e tests to improve performance
2026-01-24 01:52:27 +00:00
metamben
cbed2e45a8 Follow up on QUE-2999: move filtering to the database (#68635) 2026-01-23 23:45:05 +00:00
Timothy S. Dean
418d7a0317 Tweak data loading behavior for a test after MySQL 9.6.0 release (#68634)
Closes DEV-1289

### Description

Within the last day or two, `metabase.query-processor-test.remapping-test/self-referencing-test` began failing on MySQL Latest. I hypothesize this has to do with the [latest release](https://dev.mysql.com/doc/relnotes/mysql/9.6/en/news-9-6-0.html) fixing an unknown bug around batch inserts in InnoDB and the deprecation of a recusive [sic] fk-related flag.

The error is thrown not in the test conditions, but in the test setup -- MySQL apparently now checks foreign key constraints row-per-row even on a batch insert.

This adds a flag that the test can set which changes the test data-loading behavior to disable the FK check before insertion and re-enable it after.
2026-01-23 15:56:20 -07:00
Gabriel Moreno
3bce633480 Library empty state: display content in the page body (#68628)
* feat: create library empty state

* refactor: use new designs

* refactor: fix library creation

* fix: paper shadow

* fix: e2e
2026-01-23 18:49:35 -04:00
Gabriel Moreno
48327532c5 More Data Studio UX improvements & QoL fixes (#68546)
* fix(UXW-2752): remove unwanted padding on data structure fields tab group

* fix(UXW-2707): remove double border on job transforms section

* feat(UXW-2718): add horizontal layout for schedule controls

* feat(UXW-2709): fix spacing in the segments empty state

* fix(UXW-2780): long text overflow in user input

* fix(UXW-2710): set proper placeholder text on empty python library first load

* feat(UXW-2767): rename 'New collection' to 'Transform folder'

* refactor: blow grid & use `Ellipsified` instead
2026-01-23 18:03:17 -04:00
Anderson
26f71cfeb5 Fix SQL editor scrolling on Transform pages (#68107)
* Fix SQL editor scrolling on Transform pages

* Fix e2e test for question editor

* Fix python transform scrolling

* Fix lint

* Fix view-only transform content height
2026-01-23 18:42:24 -03:00
Braden Shepherdson
3d4e44b776 [deps] After a sync, re-analyze all dependents of updated tables (#68621)
Closes QUE-2984.

Adds an event handler for when a DWH sync is completed, which checks all its tables and fields for
their latest update times, and re-analyzes all cards which depend on tables updated since the last analysis.
2026-01-23 21:01:41 +00:00
Brad Anderson
86f3e524ba Fix UXW-2759 - Snippet edits in data studio are not saved (#68565) 2026-01-23 15:29:42 -05:00
Nathan Voxland
056d61238e If a dashboard is back to just one tab, auto-assign all cards to that tab (#68201) 2026-01-23 14:22:12 -06:00
Maksym Yakubych
926610da14 fix: custom Logo isn't loaded properly on User Invite Email (#68476) 2026-01-23 11:44:43 -08:00
Alexander Polyankin
75251f933a Fix text wrapping in dependencies (#68615) 2026-01-23 19:28:48 +00:00
Nemanja Glumac
d959d54aec Remove cache cleanup CI action (#68521) 2026-01-23 20:25:23 +01:00
Edward Paget
0933b7378f feat: support remote-syncing measures (#68392)
* feat: support remote-syncing measures

Add remote-sync support for measures, following the same pattern as segments:

- Add :model/Measure spec to remote-sync-specs with hybrid identity,
  parent-table eligibility, and event tracking
- Update measure permissions to check remote-sync/table-editable? for
  can-write? and can-create? (replacing superuser-only derive)
- Add batched hydration for :can_write on measures
- Add measures to serdes/descendants for Table so they export with parent
- Add tests for measure import/export tracking in impl_test.clj

On the Frontend creates a new data-driven approach to setting up the
middleware listener for changes that cause us to refresh dirty-state.

* fixup! typecheck
2026-01-23 13:17:01 -06:00
Edward Paget
e3b200b319 fix: flakey ec keypair test (#68591)
* fix: flakey ec keypair test

* fixup! do crypto in a delay
2026-01-23 13:15:00 -06:00
Edward Paget
fb9c0e4499 fix: derive events remote-sync needs in oss code (#68590) 2026-01-23 13:14:51 -06:00
Nemanja Glumac
40522b6cba Remove unused lodash types (#68593) 2026-01-23 19:26:18 +01:00
metamben
b6edd15de2 Stop reporting errors on archived or inaccessible entities (#68613)
Closes QUE-2999
2026-01-23 12:52:32 -05:00
lbrdnk
16042f45c7 Use macaw options, add parsed-query wrapped (#68466)
* Hoist macaw impl from query analyzer

* Use macaw-opts in bigquery module

* Use macaw-options in sqlserver

* Use macaw-options in sql driver

* Remove require

* Comment

* Test

* Update test

* Update macaw version

* Best effort support for bigquery

* Make test driver specific

* Remove final-not-reserved

* Not allowed on clickhouse only

* Clickhouse exception test

* best effort opts on api

* Remove final-non-reserved

* Remove requires

* driver.u/parsed-query

* Use parsed-query

* parsed-query

* ch test

* throw

* Lint against incorrect Macaw usage (#68568)

* Remove now unused function

* Shutdown loud exceptions for now

* Shutdown ch test

* Update test

---------

Co-authored-by: Chris Truter <crisptrutski@users.noreply.github.com>
2026-01-23 18:37:06 +01:00
Riley Thompson
b28ab0ec1d Revert ClickHouse from 0.9.5 to 0.8.4 (#68502)
* revert to 0.8.4

* disable test
2026-01-23 17:18:22 +00:00
github-actions[bot]
add8906504 Fix: Keyboard navigation annoyance in command palette (#67317)
Co-authored-by: Claude Code[bot] <noreply@anthropic.com>
Co-authored-by: Brad Anderson <brad@metabase.com>
2026-01-23 11:33:33 -05:00
dpsutton
3345365546 handle empty error message (#68581)
Fixes https://github.com/metabase/metabase/issues/68578

This issue is not about the stack overflow per-se but blowing up on a
string includes:

```javascript
{
  "app": "metabase",
  "time": "2026-01-22T12:08:53.660601485Z",
  "stream": "stderr",
  "app_version": "v1.57.10-X01",
  "message": "Exception in thread \"Thread-41\" java.lang.NullPointerException: Cannot invoke \"Object.toString()\" because \"s\" is null
at clojure.string$includes_QMARK_.invokeStatic(string.clj:377)
at clojure.string$includes_QMARK_.invoke(string.clj:373)
at metabase.app_db.cluster_lock$retryable_QMARK_.invokeStatic(cluster_lock.clj:27)
at metabase.app_db.cluster_lock$retryable_QMARK_.invoke(cluster_lock.clj:19)
at metabase.app_db.cluster_lock$do_with_cluster_lock.invokeStatic(cluster_lock.clj:87)
at metabase.app_db.cluster_lock$do_with_cluster_lock.invoke(cluster_lock.clj:65)
at metabase.app_db.cluster_lock$do_with_cluster_lock.invokeStatic(cluster_lock.clj:79)
at metabase.app_db.cluster_lock$do_with_cluster_lock.invoke(cluster_lock.clj:65)
at metabase.search.task.search_index$init_BANG_.invokeStatic(search_index.clj:36)
at metabase.search.task.search_index$init_BANG_.invoke(search_index.clj:32)
at clojure.lang.AFn.run(AFn.java:22)
at java.base/java.lang.Thread.run(Unknown Source)",
  "namespace": "hosting-eb9b3875e12d465a",
  "container": "metabase",
  "cluster": "metabase-1",
  "_p": "F"
}
```

The error message itself comes from a stackoverflow which perhaps does
not have a message? Either way, it's possible for this to be missing so
be a bit defensive
2026-01-23 10:04:56 -06:00
Sébastien
862dc50c64 Fix ChartTypeDropdown overflowing (#68455)
* Forcing overflow policy on ChartTypeDropdown

* tpyo

* refactoring to enable testing this with loki

* fixed story

* loki

* screenshot

* removed useless unit test
2026-01-23 16:08:37 +01:00
Nicola Mometto
0941091421 ensure common.py library is always available (#68603)
* fix: ensure common python library is always defined

* chore: e2e test

* fix: empty rollback

* fix: empty source

* fix: text
2026-01-23 15:01:18 +00:00
Alexander Polyankin
0bd69823a4 Show view_count for models and metrics in dependencies (#68588) 2026-01-23 17:42:57 +03:00
Alexander Polyankin
6a01533ca7 Use MBQL lib for matching field refs in ValueSourceModal in parameters (#68431) 2026-01-23 17:42:06 +03:00
Nemanja Glumac
7d18a1b5a6 Unset the premium token for E2E tests (#68533) 2026-01-23 13:54:21 +01:00
github-automation-metabase
0bf7e41984 Auto-update documentation for master (#68589)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-01-23 07:47:03 -05:00
Sébastien
95a25e4a3e fix proper bg color for embedded dashboards with custom theme (#68539) 2026-01-23 13:00:22 +01:00
Dan Stone
a2c4eef9de Revert the revert of column validation for incremental transforms (#68460)
Filter extract-columns endpoint to only return numeric and temporal columns
The extract-columns-from-query function is used to populate the incremental
filter dropdown for native SQL transforms. Previously it returned all columns
without filtering on type, leading to undefined behaviour when unsupported
column types were selected.

This change filters the results to only include columns with types supported
for incremental checkpointing:
- Temporal types (timestamp, timestamp with timezone)
- Numeric types (integer, float, decimal)

Text, boolean, and other unsupported types are now filtered out, matching
the behaviour of MBQL and Python transforms which already filter columns
client-side.

Updated documentation to clarify this endpoint is specifically for incremental
transform checkpoint column selection.

Also validates that transform POST/PUT conform to this rule and you are unable to update the transform to have
a filter column of an unsupported type.

Reverts the revert of https://github.com/metabase/metabase/pull/67686
2026-01-23 11:24:09 +00:00
Chris Truter
2f81937643 Fix data format for TODOs in style guides (#68598) 2026-01-23 13:13:30 +02:00
Sloan Sparger
48bf58b162 Cleanup from #68433 (#68481)
fix ai feedback that came after PR close :'/
2026-01-23 02:33:48 +00:00
Egor Grushin
761a7cf01e GDGT 1533 improve discoverability of python library in transforms UI (#68523) 2026-01-23 00:55:37 +00:00
Timothy S. Dean
8a76f71003 Remove find-column-for-name (#68382)
Remove find-column-for-name
2026-01-22 16:06:41 -07:00
Maksym Yakubych
fd90d13ae3 fix: custom brand color not consistently applied on Enterprise UI elements (#68484) 2026-01-22 22:56:00 +00:00
Maz Ameli
a62aab3f1b Rename Data Studio Library +New menu action labels (#68162)
* Rename Data Studio Library +New menu action labels

Update the menu item labels in the Data Studio Library's +New button:
- "Publish a table" → "Published table"
- "New snippet" → "Snippet"
- "New snippet folder" → "Snippet folder"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* prettier

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 22:39:54 +00:00
metamben
bafd49ee17 Add options to the /graph/dependents endpoint (#68573) 2026-01-22 21:58:19 +00:00
Edward Paget
1f0b461d6f feat: support remote sync transforms in FE (#68306)
* feat: support remote sync transforms in FE

1. Updates the DataStudioLayout to show transform dirty state

   We get the orange dot next to Transforms if transforms or transform
   collections are dirty.

2. Update the all changes view to include transforms

   Also includes their collection heirarchy if the transforms sync
   setting is enabled

3. Add the transforms sync setting

   To both the remote sync admin page and the Set up git sync modal in
   the data studio

* fixup! refresh transforms after sync

* fixup! data studio test feedback

* fixup! refactor failing test to troubleshoot debugging
2026-01-22 14:33:00 -06:00
metamben
1712274b85 Normalize transforms metadata (#68490) 2026-01-22 23:22:39 +03:00
Timofey Kachalov
ea203102e6 Don't show CORS settings in OSS/Starter editions (#68564) 2026-01-23 00:14:05 +04:00
Edward Paget
3c72591b17 feat: add Slack Connect SSO provider (#67955)
* feat: add Slack Connect SSO provider

Add enterprise Slack Connect SSO integration using the OIDC infrastructure:

- Slack Connect provider: OAuth2/OIDC flow for Slack workspace authentication
- Settings: configuration options for Slack client ID, secret, and auth modes
- User provisioning: automatic user creation from Slack identity
- API endpoints: SSO initiation and callback handling
- Analytics: usage tracking for Slack Connect feature

Slack Connect allows users to authenticate via their Slack workspace,
with support for both SSO-only and link-account authentication modes.

* fix: session reset after auth

* fixup! avoid email clash

* fixup! wrong value in sso settings

* fixup! cleanup tests

* fixup! fix test

---------

Co-authored-by: John Swanson <john.swanson@metabase.com>
2026-01-22 10:57:12 -08:00
github-automation-metabase
9a19a5e4f0 [chore] Update llms.txt for master (#68561)
Update llms.txt and llms-full.txt (master)

Regenerated llms.txt to include all markdown files from the docs/ directory.
Also generated llms-full.txt files for the embedding section.

🤖 Generated automatically by llms-txt-generate workflow

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Actions <actions@github.com>
2026-01-22 18:20:04 +00:00
Sloan Sparger
f387d4aca4 [Metabot] Add close button back to data studio sidebar (#68487)
allow metabot to be closed in data studio
2026-01-22 11:33:21 -06:00
github-automation-metabase
1bb6f6a74a Update translations 2026-01-22 (#68557)
* Update translation sources 2026-01-22

* Update translations

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-22 17:19:01 +00:00
Nicolò Pretto
2ad4292465 fix(embed-homepage): rename static embed to guest embed (#68338) 2026-01-22 16:37:02 +00:00
github-automation-metabase
37c3758748 Auto-update documentation for master (#68524)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-01-22 09:26:48 -05:00
Jeff Bruemmer
ae9cad5c58 docs - note on ee vs oss path (#68210) 2026-01-22 09:09:05 -05:00
John Swanson
bd14e14974 Reenable deactivated tenants when autoprovisioning (#67947)
Previously even when autoprovisioning was on, you could not log into a
deactivated tenant (either as a new user or an existing user with that
tenant).

This changes the behavior to be more consistent. Just as a deactivated
user can log in when provisioning is on (and their user gets
reactivated), a deactivated tenant's users can still log in, but doing
so reactivates the tenant.
2026-01-22 05:10:23 -08:00
Jakub Chodorowicz
85319217cd Gdgt 1273 add snowplow events to bulk metadata features (#68409)
* add data studio library filtering events

* add bulk properties and unpublish event

* add bulk sync events

* add search event

* add assertions on events in e2e tests

* add search debounce

* remove unncessery comment

* update event names

* track filter searches with data_studio_table_picker_search_performed

* refactor tracking function

* guard and log event only for ConcreteTableId

* log search when started fetching

* fix events not fired

* fix event not fired on first search
2026-01-22 12:30:26 +01:00
Nicola Mometto
240acb4782 add started-at filter to task runs page (#68279)
* WIP: add started-at filter

* fix: kondo

* fix tests

* GDGT-1520 add a started at filter

* GDGT-1520 add a comment

* GDGT-1520 fix typing issues

* GDGT-1520 addressing PR comments

* GDGT-1520 addressing PR comments

* GDGT-1520 fix a tests after changing a text

---------

Co-authored-by: Egor Grushin <egor@metabase.com>
2026-01-22 09:49:15 +00:00
Jakub Chodorowicz
e6bc40c223 add analytics skill (#68419) 2026-01-22 09:36:42 +01:00
bryan
76fcb4d573 Fix transforms module to trigger driver tests + promote pg (#68432) 2026-01-21 16:30:15 -07:00
Arkadi Yaroslavtsev
a92317dd27 Add Anchor Links to Documents (#67940)
* Add AnchorLinkButton component for document anchor links

- Add AnchorLinkButton component that copies URL to clipboard on click
- Shows 'Copied!' tooltip feedback using Mantine useClipboard hook
- Follows same pattern as CommentsButton for consistent styling
- Add unit tests for the component

* Add AnchorLinkMenu component for left-side anchor link hover

- Add AnchorLinkMenu floating menu for document blocks
- Uses createPortal for positioning (same pattern as CommentsMenu)
- Positioned on left side of blocks using floating-ui
- Shows/hides based on hover state via show prop
- Add unit tests for the component

* Add AnchorLinkMenu to document node views

- Add documentWithAnchor URL helper to generate shareable anchor URLs
- Update Heading, Paragraph, and Blockquote node views to render AnchorLinkMenu
- AnchorLinkMenu appears on the left side on hover
- CommentsMenu on the right side remains unchanged
- Each node view now uses two useFloating instances for positioning

* Add scroll-to-anchor for document URLs with hash

- Add E2E tests for anchor links functionality
- Implement scroll-to-anchor when navigating to document with #blockId hash
- Tests cover: hover shows anchor icon, copy to clipboard, scroll to block
- Regression test ensures CommentsMenu still works on right side

* Fix scroll-to-anchor dependency arrays for navigation edge cases

- Add documentId to scroll effect dependencies to re-run when navigating
  between documents with the same anchor hash
- Add location.hash to reset effect dependencies to properly reset flag
  when navigating via back button or changing anchors

* Fix accidental logo replacement and E2E blockquote test

- Restore original Metabase logo SVG (was replaced with red star debug graphic)
- Fix E2E test: use find('blockquote') instead of findByRole('blockquote')
  since native blockquote elements have no implicit ARIA role

* Fix scroll-to-anchor reliability and empty line behavior

- Implement retry mechanism for scroll-to-anchor to ensure target element exists
- Add highlight animation when scrolling to anchor
- Hide anchor link and comment menus on empty lines (Heading, Paragraph, Blockquote)

* Fix selector mismatch for scroll-to-anchor

- Add data-node-id attribute to NodeViewWrappers in Heading, Paragraph, and Blockquote
  extensions so they can be queried by DocumentPage
- Update DocumentPage to query using [data-node-id] selector instead of internal _id attribute
- Remove unused ID_ATTRIBUTE_NAME import in DocumentPage

* Fix highlight animation color variable

- Replace non-existent --mb-color-brand-alpha-25 with --mb-color-brand-light
- Ensure highlight animation is visible when scrolling to anchor

* added anchor links to lists and code blocks. some bugs fixes.

* make sure scroll-to-anchor observer is correctly initialized

- Refactor scroll-to-anchor logic to ensure smoother navigation
- Optimize highlight animation visibility during scrolling
- Adjust anchor link behavior on empty lines for better user experience

* small fixes

* clean up

* fixes and cleanup

* e2e test fixes

* fixed e2e test

* Leave anchor links only for header blocks

* Fix alignment

* Review fixes

* Fix unit tests

---------

Co-authored-by: Denis Berezin <denis.berezin@metabase.com>
2026-01-22 02:03:04 +03:00
bryan
087a317f70 Fix ci-report output formatting issues (#68505) 2026-01-21 15:50:57 -07:00
Denis Berezin
c63fd746d8 Uxw 2633 copy cells from table (#68429)
* UXW-2633 fix sorted table values copy-paste

* Add e2e test
2026-01-22 01:24:12 +03:00
dpsutton
f29a446aab fix materialized views test (#68509)
https://github.com/metabase/metabase/pull/68190 did:

> Treats a 0 value of n_live_tup as NULL, due to confusion reported when
> auto analyze thresholds have not been met on a table.

I think what's happening is this is trying to suss out "i don't know"
and not give misleading information. When there are no stats pg would
report there are 0 rows rather than saying i don't know. So we toss away
these unreliable 0 count estimations.

This test flakes 7% of the time. Our hypothesis is that stats are empty
7% of the time so this row count estimation now gets removed.

By default the schema is `:estimated_row_count (mt/malli=? [:maybe
:int])` which was being clobbered with
`{:estimated_row_count (mt/malli=? int?)}` So the fix is to just not
clobber
2026-01-21 16:07:45 -06:00
Edward Paget
d26bf4e454 feat: support transforms in remote sync (#68255)
* feat: support transforms in remote sync

1. Serialize Transforms as Collection Items

   Transforms were previously serialized as a top-level item, but this
   moves them to be serialized as a child of the collection they are
   member of. This also fixes an error in their serdes/dependencies
   implementation where it did not include the parent collection leading
   to deserialization issues.

2. Enforce Remote-Sync write rules

   Adds implementations of the model interface permissions methods for
   transforms that enforce the can-write? = false and can-create? =
   false rules when remote-sync is in read-only mode.

3. Add a setting to control whether transforms are synced

   Transforms are globally synced not synced via collections, so this
   adds a new boolean setting that controls whether they are synced on
   instances in read-write mode. Like all other content transforms are
   always synced from the remote source if the instance is in read-only
   mode.

4. Add a new spec-based configuration system for models

   Models we want to make remote-syncable have a complicated, but still
   data-driven system to allow you to specify their remote-sync behavior
   and have that automatically setup in a single place the
   `metabase-enterprise.remote-sync.spec` namespace.

* fixup! test with wrong folder

* fixup! not handling archived transform collections

* fixup! clean up aliases
2026-01-21 15:29:27 -06:00
Denis Berezin
7aa18ae448 Fix flaky test that uses readonly db that lacks permissions (#68417) 2026-01-22 00:15:27 +03:00
Timothy S. Dean
97da3d7c7b Migration follow-up fix to #68100 (#68498)
Move a migration from the v59 file to the v56 file, as we intend to backport it that far.
2026-01-21 14:15:12 -07:00
Aleksandr Lesnenko
10e8a68cf5 Data Analysts user group (#67770)
* basic analyst role

* analyst role

* Backend for data analyst role

* Fixup frontend to work with Backend

The dedicated analyst endpoints have been removed:
- `GET /api/user/analysts` -> Use `GET /api/user?is_data_analyst=true`
- `POST /api/user/analysts/:id` -> Use `PUT /api/user/:id` with `{ is_data_analyst: true }`
- `DELETE /api/user/analysts/:id` -> Use `PUT /api/user/:id` with `{ is_data_analyst: false }`

These hooks no longer exist:
- useListAnalystsQuery
- useAddAnalystMutation
- useRemoveAnalystMutation

New Patterns:

Listing analysts:
```
// Before
const { data } = useListAnalystsQuery();

// After
const { data } = useListUsersQuery({ is_data_analyst: true });
```

Adding an analyst:
```
// Before
await addAnalyst(userId).unwrap();

// After
await updateUser({ id: userId, is_data_analyst: true }).unwrap();
```

Removing an analyst:
```
// Before
await removeAnalyst(userId).unwrap();

// After
await updateUser({ id: userId, is_data_analyst: false }).unwrap();
```

Type Changes:

The field is_analyst has been renamed to is_data_analyst everywhere:

- User.is_data_analyst (was is_analyst)
- UpdateUserRequest.is_data_analyst (was is_analyst)
- ListUsersRequest.is_data_analyst (new field for filtering)

* kondo

* circular dep

* fix backend not compiling

* use the actual role

* analyst management, glossary access for admins

* various data studio access

* access to library

* drop custom analyst seats management ui

* automatic perms group

* fix tests

* specs

* permissions

* fix lints, add migration rollbacks

* data analysts can ALWAYS view table metadata

implemented for:

- search
- `table/can-read?`

* Also remove `can_access_data_model`

* Revert "Also remove `can_access_data_model`"

This reverts commit 03af432ccb.

* fix more tests

* more tests

* snapshots

* remove redundant checks

* everyone can see

* hide data analyst group for OSS

* Make data analysts a normal group on OSS

* Automatically provide data analysts with perms

Data analysts automatically get manage-table-metadata permissions on
every table/database.

* only disable setting some perms for data analysts

* kondo

* oops, one more kondo

* test fixes

* specs, fixes

* more specs, fixes

* cleanup

* more test fixes

* fix module config

* ci

* doh, fix test

* more test whack-a-mole

* move data analyst group to the top of perms views

* review

* ci

* Turn DA into a regular group when feature missing

instead of just on OSS.

The goal is:
- OSS: a previously existing Data Analysts group is a regular group with
configurable permissions. The real Data Analysts group is invisible and
has no members.
- EE without the token: same as above
- EE with the token: the real Data Analysts group is visible.

* oops, remove unnecessary require

* another one

* fix membership API

* fix a couple more tests

* macro gets a !

* fix `fetch-groups-test`

* ci

* ci

* ci

* ci

* fix collection perm in migration

---------

Co-authored-by: John Swanson <john.swanson@metabase.com>
2026-01-21 12:43:35 -08:00
Dan Meyer
209a34b102 ci: Enable fail-fast for BigQuery and Snowflake driver tests (#68199)
Add :fail-fast? true to BigQuery and Snowflake test-args, matching the
existing Redshift configuration. This stops test execution on first
failure, saving CI time and resources.
2026-01-21 20:27:03 +00:00
William
a6df84c136 Bump toucan2 version to fix dashboards sometimes failing to load (#68494)
If the first table mentioned by a dashboard has no fields (presumably because the table and its field are all
inactive), /api/dashboard/<id>/query_metadata would fail due to a toucan2 bug.  This bumps toucan2 to fix the bug and
adds a test to verify that this case now works.
2026-01-21 20:18:30 +00:00
Riley Thompson
adb9a5cbf4 Bump dependency analysis version (#68488)
bump dependency analysis version
2026-01-21 19:08:45 +00:00
Phoomparin Mano
d491eb6d51 Apply unified theme object to main app and modular embedding (#68169)
Co-authored-by: Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>
2026-01-22 01:30:13 +07:00
Cam Saul
0f20f4d2f0 Deduplicate field refs by ignoring :source-field-name unless it matters (#68166)
* Tentative fix for #67808 -- deduplicate by ignoring :source-field-name if possible

* Make sure `:fields` remains a vector

* Add note

* cljfmt
2026-01-21 11:13:14 -06:00
Maksym Yakubych
9304e6cb6e fix: page hangs without a loader when saving a PDF (#68385) 2026-01-21 13:37:44 -03:00
Riley Thompson
21f043d697 Return upstream breaking entities for dependencies (#68282)
* initial work

* fix test

* fix another test

* source entity malli schema

* clean up and add test

* add tests

* clean up

* fix tests

* drop finding_details column

* fix analysis version

* Update enterprise/backend/src/metabase_enterprise/dependencies/models/analysis_finding.clj

Co-authored-by: Timothy S. Dean <timothy.dean@metabase.com>

* use transaction

* use node-errors refactor suggestion

* use maybe-resolve-join

* add schemas

* add comment

* kondo

* fix test

* initial changes

* remove validate/ prefix

* replace name/message with detail in dependents_errors

* fix test

* kondo

* typo

* Clean up

* add back card types

* remove unused

* add back card types comment

* small adjustment

* Fixes

* Add links

* reuse existing query

* UI

* use detail

* clean up tests

* UI

* UI

* UI

* improve tests

* initial /dependents broken filtering

* UI

* UI

* UI

* UI

* UI

* UI

* UI

* UI

* return full analysis finding error from api

* accept multiple dependent_types and dependent_card_types

* sort by dependents errors

* fix dependents broken parameter test

* fix

* fixes

* fix sorting

* Fix

* fixes

* fixes

* fixes

* fix

* tests

* fixes

* fix

* fixes

* fixes

* fixes

* fixes

* fixes

* add transforms

* fixes

* fix

* Add views

* fixes

* fixes

* basic e2e test

* fixes

* tests

* tests

* tests

* tests

* tests

* fixes

* fixes

* fix mysql distinct counting

* fixes

* fixes

* fix count query

* handle emtpy error detail

* fix i18n parser

* initial pr comments

* refactor dependency-items-args

* address comments

* small changes

* fix flake

---------

Co-authored-by: Timothy S. Dean <timothy.dean@metabase.com>
Co-authored-by: Alexander Polyankin <alexander.polyankin@metabase.com>
2026-01-21 11:26:10 -05:00
Sloan Sparger
d6bb46208f [Metabot] Send transforms_codegen profile on transforms pages again (#68433) 2026-01-21 09:09:12 -06:00
Egor Grushin
e2f7cc9d86 GDGT-1516 add datetime formatting to Task Run Monitoring features (#68427) 2026-01-21 15:09:03 +00:00
Oleksandr Solovyov
0880e7297d fix incremental transform tests (#68470) 2026-01-21 17:04:54 +02:00
metamben
4f23bc973f Prevent exception in cleanup masking the original exception (#68371) 2026-01-21 14:49:43 +00:00
Anderson
1afabc3d01 Allow editing segments and measures when remote sync is read-only and table is unpublished (#68326)
* Still allow editing segments when table is not published

* Allow editing on measures when table is not published
2026-01-21 11:45:19 -03:00
github-automation-metabase
cdf5111a0d Auto-update documentation for master (#68447)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-01-21 09:13:34 -05:00
Timofey Kachalov
70cf127afd Remove linking between static and simple embedding settings when toggling guest embeds in Admin UI (#68231) 2026-01-21 16:20:30 +04:00
Oleksandr Solovyov
ac421d0a6d transforms: pass full object instead of re-querying db internally (#68456) 2026-01-21 11:45:23 +00:00
Dan Stone
9f5b23ecdd Custom ref schema that reuses the cache (#68379)
Add ref schema caching

Introduces a custom :ref IntoSchema that permits
reuse of Schema objects for references when safe to do so.

Early tests indicate a dramatic reduction in heap retention, after
loading a single dashboard, I see a 10x resident heap reduction from ~300MB to ~30MB.

It should also act as knot tie / runtime combinatorics limiter, so we should not see 'leaky' growth at runtime.

More work could be done as there are still _some_ gaps here.
- Bare pointers (keywords) can still lead to exponential allocation
- We do not cache when :documentation is present on the ref
  (as it would specialise the Schema object delivered for that specific reference)
2026-01-21 10:30:04 +00:00
Sébastien
f8551c9800 Fixed no-literal-metabase-strings eslint rule for export * from './MetabaseThing'; (#68411)
fixed eslint custom rule
2026-01-21 10:42:55 +01:00
Kamil Mielnik
4befb6089f Fix - It's not possible to continue editing a bad transform (#68415) 2026-01-21 09:08:12 +00:00
Romeo Van Snick
c902d22458 Contain layout for notebook preview (#68448)
* Contain layout for notebook preview

* Add repro for metabase#67903
2026-01-21 19:14:00 +11:00
Romeo Van Snick
7451ffcd93 Set max height to native editor and some other refactors (#67896)
* Desrtucture all this.props

* Convert to function component

* Remove the wrapper

* Forward ref in topbar

* Limit resize height

* Pass availableHeight to native query editor

* Move var to constants

* Add more padding

* Rename viewHeight to availableHeight

* Handle unset availableHeight

* Add availableHeight to QueryEditor

* Calculate availble height above the fold

* Resize editor when available size shrinks

* Remove layer of nesting

* Rename calc to get

* Pass availableHeight to sql editor in modal

* Remove resizableBoxProps prop

* Do not resize when closing editor

* Use runQuery from props when availabe

* Sort props and remove unused props

* Clean up setIsNativeEditorOpen

* Remove dispatch from NativeQueryEditor completely

* Move state change out of useEffect

* Pull out resizable box into separate component

* Simplify availableHeight prop

* Move resizable logic into separate component

* Clean up code

* Handle availableHeight being 0 initially

* Make minHeight take preference

* Avoid setting height to Infinity

* Add repro for metabase#59075

* Fix e2e test

* Do not use default export

* Add type to NativeQueryEditor

* Remove unused databases loader

* Remove unused ExplicitSize wrapper

* Remove enity loader wrappers

* Flatten props

* Fix setDatabaseQuery type

* Fix types

* Add className to NativeQueryEditor

* Fix types

* Pull out handler

* Manually update metadata when updating snippet

* Preserve sidebar state if need be

* Fix e2e test

* Fix mock exports

* Fix e2e test

* Do not overwrite availableHeight

* Remove viewHeight prop

* Increase limit

* Fix broken test

* Remove unneeded useHeightAboveFold helper
2026-01-21 06:47:32 +00:00
dpsutton
410471a4d0 Revert transforms changes recently (#68446)
* Revert "Filter incremental transform column listing to supported types only (#67686)"

This reverts commit 735b98d6f8.

* trigger driver changes
2026-01-21 03:16:13 +00:00
Nemanja Glumac
a2b3490355 Run codespell on schedule and auto-fix typos (#68444) 2026-01-21 00:14:41 +00:00
bryan
3b8e1ecaa4 Add mage ci-report command for CI failure analysis (#68319) 2026-01-20 22:23:40 +00:00
Maksym Yakubych
0176c399f9 fix: "Connect to Slack" CTA remains visible after Slack is configured (#68289) 2026-01-20 22:04:41 +00:00
dpsutton
2287567b12 Fix Horror Show fingerprint OOMs (#68391)
* Fix Horror Show fingerprint OOMs

This may likely fix many OOMs that others are seeing. Anyone with large
schema will likely benefit from this.

```clojure
(let [database (toucan2.core/select-one :model/Database :id 2)]
  (metabase.sync.analyze.fingerprint/fingerprint-fields-for-db!
    database (fn [s t] (println "synced " s "for " (:name t)))))
```

This is how we fingerprint fields. DB 2 here is "Horror Show", a
database with 200 tables, each of which has 900 fields in it. This
database has zero rows in it, it it just a large schema.

Syncing this recently has caused huge cpu spikes and then OOM errors
until the instance is killed.

Profiling locally with

```
MB_JETTY_PORT=3091 java "$(socket-repl 6091)" -Xmx2g -jar metabase.jar
```
and visual vm hooked up, I run

```clojure
(let [database (toucan2.core/select-one :model/Database :id 2)]
  (metabase.sync.analyze.fingerprint/fingerprint-fields-for-db!
    database (fn [s t] (println "synced " s "for " (:name t)))))
```

And observe this behavior:
The ram usage approaches the 2gb limit and then bounces there. The CPU
begins to spike erratically and spend 10% of its time in GC.

Taking a heap dump we can see that we have 2.8 million ResultSetMetaData
objects occuping 183 Mb.

The ResultSetMetaData are closed over and kept in the metadata of the
snake hating maps stored in the cached metadata provider.

This brings into stark relief one simple way to fix this: don't use a
caching metadata provider. This PR just raising the body of the
fingerprint-tables-for-db function to not include
`(qp.store/with-metadata-provider (u/the-id database)` . There is no
benefit to caching here as this is an enumeration of the database. It is
by design not meant to reuse anything. If we didn't OOM we would end up
with 200 tables and 200*900 = 180,000 fields in the cache, each of which
was accessed only once.

That is what this PR fixes.

I also followed one other thread: why are we holding so many
ResultSetMetaData objects in memory. This seems to come about from a
change in https://github.com/metabase/metabase/pull/62330 specifically
this line:
https://github.com/metabase/metabase/blob/master/src/metabase/lib_be/metadata/jvm.clj#L63

```clojure
(mu/defn instance->metadata
  "Convert a (presumably) Toucan 2 instance of an application database model with `snake_case` keys to a MLv2 style
  metadata instance with `:lib/type` and `kebab-case` keys."
  [instance      :- :map
   metadata-type :- :keyword]
  (let [normalize (if-let [schema (get metadata-type->schema metadata-type)]
                    (fn [instance]
                      (lib.normalize/normalize schema instance))
                    identity)]
    (-> instance
        (perf/update-keys memoized-kebab-key)
        (assoc :lib/type metadata-type)
        normalize
        u.snake-hating-map/snake-hating-map
        ;; the line below here captures the result coming back from
        ;; toucan and has a closure over
        ;; toucan2.jdbc.read/make-column-thunk which has a closure over
        ;; (.getMetaData rset)
        (vary-meta assoc :metabase/toucan-instance instance))))
```

As it stands without any changes, the instance gets quite unstable and
falls over. If you comment out the `var-meta` form above, the graph
returns to a very normal sawtooth graph of memory usage and
reclaimation. But central to this is that it does not need to retain any
of this memory at all. But without this metadata containing the instance
and db classes, we only cache the table and field data and the
fingerprinting can finish. When we cache this stuff and also
inadvertently keep these db classes, we quite quickly run out of
headroom and the instance becomes unstable and falls over.

* fix kondo lint (removes a legacy usage as well :) 💰
2026-01-20 14:58:56 -06:00
Sloan Sparger
d9b8b9a2c0 [Metabot] Bug fix - animation color for nlq loading state (#68149)
fix animation color for nlq loading state
2026-01-20 14:57:32 -06:00
dpsutton
17f473a9f1 bit more cleanup (#68300)
* bit more cleanup

kept having a few flakes, couldn't consistently get it to pass 45 times
in a row locally. So just simplify it. Don't worry about "in process"
stats. Trying to get the webserver paused in the middle of a request was
occasionally deadlocking, often flaking.

So just calculate the simple ones and it's fine

```clojure
statistics-handler-test=> (clojure.test/run-test server-stats-test)

Testing metabase.server.statistics-handler-test

Ran 1 tests containing 13 assertions.
0 failures, 0 errors.
{:test 1, :pass 13, :fail 0, :error 0, :type :summary}
statistics-handler-test=> (dotimes [_ 100](server-stats-test))
nil
```

Also got rid of the macro that really only existed to collect the forms
into an anonymous function. Everything in-lined and now don't need a
kondo hook, etc

* remove unused alias

* kondo the refers

* reintroduce in-flight metrics

these:
```
(is (prometheus-test/approx= 1 (value! :jetty/requests-active)))
(is (prometheus-test/approx= 1 (value! :jetty/dispatched-active)))
```

Require a mechanism that can pause a request while active, verify that
the requests-active and dispatched active are incremented, and then
carry on. This is all kinda trivial except getting it wrong can
deadlock. Here are 500 successful runs of this test:

```
statistics-handler-test=> (dotimes [_ 100] (server-stats-test))
nil
statistics-handler-test=> (dotimes [_ 100] (server-stats-test))
nil
statistics-handler-test=> (dotimes [_ 100] (server-stats-test))
nil
statistics-handler-test=> (dotimes [_ 100] (server-stats-test))
nil
statistics-handler-test=> (dotimes [_ 100] (server-stats-test))
nil
```
2026-01-20 14:53:30 -06:00
Noah Moss
110cb5bca7 Streaming API response schema for documentation (#68386)
* Streaming API response schema POC

* Narrow a couple schemas

* fix comment

* bump ci

* oops, fix schema placement

* address feedback
2026-01-20 19:30:28 +00:00
Timofey Kachalov
1149c3e30c feat(embed-js): Add a counter-like query parameter for EmbedJS iframe src to allow multiple iframes loading in parallel (#68420) 2026-01-20 22:49:53 +04:00
Dan Stone
735b98d6f8 Filter incremental transform column listing to supported types only (#67686)
Filter extract-columns endpoint to only return numeric and temporal columns

The extract-columns-from-query function is used to populate the incremental
filter dropdown for native SQL transforms. Previously it returned all columns
without filtering on type, leading to undefined behaviour when unsupported
column types were selected.

This change filters the results to only include columns with types supported
for incremental checkpointing:
- Temporal types (timestamp, timestamp with timezone)
- Numeric types (integer, float, decimal)

Text, boolean, and other unsupported types are now filtered out, matching
the behaviour of MBQL and Python transforms which already filter columns
client-side.

Updated documentation to clarify this endpoint is specifically for incremental
transform checkpoint column selection.

Also validates that transform POST/PUT conform to this rule and you are unable to update the transform to have
a filter column of an unsupported type.
2026-01-20 18:00:36 +00:00
Jakub Chodorowicz
359158e594 Gdgt 1312 adjust range selection to work also with schemas and dbs (#68280) 2026-01-20 18:17:50 +01:00
Edward Paget
9a5e8227d0 fix: failing transforms revision test (#68422) 2026-01-20 16:40:22 +00:00
github-actions[bot]
287665a6fa Fix: Actions attached to models inside of Library(synced collection) break remote sync (#68252)
Fixes #68215

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude Code[bot] <noreply@anthropic.com>
Co-authored-by: Ed Paget <ed@metabse.coma>
Co-authored-by: Edward Paget <edpaget@users.noreply.github.com>
2026-01-20 10:23:56 -06:00
Jeff Bruemmer
82f16a8528 docs - guest embed locked parameters (#68293) 2026-01-20 10:50:26 -05:00
github-automation-metabase
45b4b682cc Auto-update documentation for master (#68402)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-01-20 09:58:17 -05:00
Denis Berezin
7a96e1f142 UXW-2497 fix remote-sync flaky test (#68368) 2026-01-20 17:16:05 +03:00
Gabriel Moreno
a48f246c50 Add transform owners and show them in Data Studio (#67840)
* feat: add owner fields

* feat: hydrate owner property on transforms

* feat: extend `start-run` function to accept `user_id` and use it on scheduled transform runs

* feat: implement 'Ownership' section in transform settings page

* test: implement unit specs

* test: add e2e spec

* feat: show owner avatar in transforms list

* Minor clojure improvements

* test: simplify & extend e2e spec

* refactor: simplify avatar usage & change unassigned copy to "No owner"

* refactor: de-duplicate success & error messages

* test: add missing serialization test transform attributes

* test: fix e2e spec by scrolling into view first

* refactor: attribute manual runs to current user rather than owner

* refactor: cleanup

* tests: add missing user id parameter for jobs unit spec

---------

Co-authored-by: Nathan Voxland <nathan@metabase.com>
2026-01-20 10:07:33 -04:00
Sébastien
dd00b33545 Fix tracking event never set to default in embed (#68407)
* fix tracking event never set to default in embed

* added e2e
2026-01-20 14:35:08 +01:00
Jakub Chodorowicz
51eab9a902 add openapi check to ci pipeline (#67854)
openapi check with self healing, all hidden behind ci label
2026-01-20 14:31:43 +01:00
Dan Stone
4b47763109 Restore future in mock client calls so that interrupts are isolated from caller (#68408)
Ensure client-full-response uses future so that interrupts are isolated from caller

An intentional server side .interrupt might leak and cause subsequent
code to fail.

Prior to https://github.com/metabase/metabase/pull/65872 the
client-full-response used a with-timeout, which incidentally put the
http handler in a future (isolating the interrupt).

This commit restores the previous behaviour, in a more intentional way.
2026-01-20 12:59:56 +00:00
github-automation-metabase
d4960babe5 [chore] Update llms.txt for master (#68410)
Update llms.txt and llms-full.txt (master)

Regenerated llms.txt to include all markdown files from the docs/ directory.
Also generated llms-full.txt files for the embedding section.

🤖 Generated automatically by llms-txt-generate workflow

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Actions <actions@github.com>
2026-01-20 12:57:37 +00:00
Gabriel Moreno
3856fd989e Data Studio UX improvements & QoL fixes (#68320)
* fix(uxw-2711): dependency graph corner radius

* fix(uxw-2706): give snippets a default name

* feat(uxw-2750): use actual link elements for transform list page

* feat(uxw-2750): use actual links for library section layout items

* fix(uxw-2751): prevent transform cancel handler from wiping changes
2026-01-20 08:37:54 -04:00
Nicola Mometto
2ac5ed4fb0 add task-runs to usage analytics (#68288)
* feat: ad v_task_runs

* feat: update v_tasks view

* update permissions/test

* add views

* remove fieldusersettings from export, channels

* add task runs model
2026-01-20 10:39:56 +00:00
Sébastien
1b80d7dc16 Enable editing/creating native questions in the SDK (#68138)
* .

* .

* .

* edit is actually working

* add now works too

* fix

* added e2e test

* doc

* .

* added a wait to see if that helps

* better waits

* .

* addressed comments

* Apply suggestions from code review

Co-authored-by: Alex Yarosh <alexandra@metabase.com>

* test

* test

---------

Co-authored-by: Alex Yarosh <alexandra@metabase.com>
2026-01-20 08:37:11 +01:00
github-automation-metabase
34266fc636 Update translations 2026-01-20 (#68403)
* Update translation sources 2026-01-20

* Update translations

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-20 06:23:53 +00:00
Alexander Polyankin
e3ced91a43 Make filtering in the deps graph consistent with the task lists (#68373) 2026-01-20 03:36:05 +00:00
Anderson
a37b3fb0ec Implement read-only mode on Snippet detail page (#68268)
* Implement read-only on Snippet detail page

* Add more tests

* Fix mock

* translate string
2026-01-20 00:48:51 +00:00
Romeo Van Snick
1284c201b5 MBQL lib test helpers (#68168)
* Add test helper definition and implement joins

* Add support for fields clause

* Be explicit with types

* Pull out findJoinStrategy helper

* Pull out appenTestQueryStage

* Simplify helpers

* Move helper

* Allow disamiguating column name

* Fix rhs columns

* pull out createTestJoinClause

* Add filters

* Add aggregations

* Add breakouts

* Add expressions

* Add ordering

* Add limiting rows

* Make source optional

* Make provider the first argument

* Expand example in tests

* Automatically pick the base column if no table was specified

* Remove unused sourceMetadata argument where not needed

* Fix join metadata

* Improve types

* Add createNativeQuery and createNativeJsQuery helpers

* Use column groups to disambiguate instead of table name

* Test the results

* Deprecate createQuery

* Replace createQueryWithClauses with createTestQuery

* Add SAMPLE_PROVIDER

* Add helpers to build metadata provider

* Use displayName for groupName

* Remove raw mbql in test and replace it with Lib inspections
2026-01-20 11:04:16 +11:00
Nemanja Glumac
feb0c5b34a Add pre-commit hook to auto-fix unused requires flagged by clj-kondo (#68274)
This introduces a pre-commit hook that automatically removes unused require
statements detected by clj-kondo, preventing CI failures.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 00:10:01 +01:00
bryan
58e4025456 Fix flaky dataset-already-loaded?-test for Redshift (#68292) 2026-01-19 13:44:59 -07:00
bryan
9ceae0061a Fix mage doctor on Linux: use which instead of command -v (#68381)
`command` is a shell builtin that doesn't exist as a standalone binary on
Linux (only macOS has /usr/bin/command as a wrapper). When babashka tries
to execute `command -v git` directly via process/shell, it fails on Linux
because there's no `command` binary to run.

Using `which` instead works on both platforms since it's an actual binary.
2026-01-19 20:04:10 +01:00
metamben
2cb8a32def Add back typo fix removed by merge (#68375) 2026-01-19 20:00:32 +01:00
Edward Paget
59adba6f98 feat: generic oidc provider using auth-identity (#65872)
* feat: add generic OIDC provider infrastructure

Add OSS infrastructure for OIDC-based authentication providers:

- OIDC discovery: automatic endpoint discovery from issuer URL
- Token handling: ID token validation, parsing, and claim extraction
- State management: encrypted state cookies for CSRF protection
- Schema validation: Malli schemas for OIDC configuration and tokens
- Common utilities: shared HTTP and request utilities

This provides a foundation for enterprise SSO integrations that use
OIDC/OAuth2 flows (e.g., Slack Connect, generic OIDC providers).

* fixup! dead code clean up

There was a bunch of speculative code we didn't end up using when this
change from a 'configurable OIDC' to a just support slack course

* fixup! ttls for caches for jwks/discovery

fixup! check for open redirect when creating oidc state

* fixup! use valid-hosts? to check before making jwks/discovery requests

* fixup! don't use hardcoded jwt algo

* fixup! use java-time

* fixup! kondo

* fixup! use system.core not system.settings
2026-01-19 12:04:55 -06:00
Denis Berezin
1da7a523b8 Use proper link in public powered by metabase footer link (#68301)
* Use proper link in public powered by metabase footer link

* Fix tests

* Fix tests
2026-01-19 20:47:41 +03:00
Alexander Polyankin
6165e70718 Fix :view_count not returned for relevant entities in the dependencies graph (#68370) 2026-01-19 17:43:54 +00:00
metamben
1a2f012afe Show sensitive columns in the sandboxing UI (#66757)
* Show sensitive columns in the sandboxing UI

Closes #53378
2026-01-19 16:33:20 +00:00
Brad Anderson
c8b6f74578 UXW-2341 Add Caching tab for metrics in Data Studio (#66513) 2026-01-19 10:51:51 -05:00
metamben
905c5dde99 Report datetime insights even if columns is PK or FK (#67536)
Closes #35281
2026-01-19 15:10:27 +00:00
Alex Yarosh
913e0c9ee8 docs: IAM for RDS (#68349)
* Update IAM authentication details for RDS instances

Clarified the types of RDS instances that support IAM authentication.

* Update docs/databases/connections/aws-rds.md

* Update docs/databases/connections/aws-rds.md
2026-01-19 09:20:26 -05:00
github-automation-metabase
9eb6d7c74d Auto-update documentation for master (#68332)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-01-19 09:08:06 -05:00
Phoomparin Mano
a27a3d286b Fix flaky assertion for "sdk iframe embedding fires ready event after iframe is loaded" (#68336) 2026-01-19 19:45:38 +07:00
Nicola Mometto
03d26b2a19 fix spelling typo (#68342) 2026-01-19 11:46:08 +00:00
Dan Stone
4fa44b5fc7 Use Soft/Weak references for malli cache entries (#68076) 2026-01-19 10:51:25 +00:00
Nicola Mometto
2e3746de55 Task Run Monitoring (#68116)
* add task_run table and followup migrations

* fix: missing remarks

* feat: task-run model

* wip: logs and run-id in task_history model

* wip: endpoints

* chore: dead code

* simplify

* simplify

* Add log capture factory

* Move log capture to history

* feat: prevent running if nested

* Capture logs during task history

* Tests + fixes for log capture

* Avoid log aliases and kondo the discouraged c.t.logging ns

* style

* fix

* feat: wrap with with-task-run

* Add `:ts` timestamps to captured log entries

* Skip DEBUG/TRACE

* Add basic log truncation

* Test log truncation

* Fix sync tests

* Add :model/TaskRun resolution.clj entry

* GDGT-1497 add TaskRun UI part

* feat: hydrate-task-counts

* fix: nil protect limit/offset

* style

* fix: move with-task-run to core ns

* fix: ignore TaskRun from copy test

* fix: no need for name

* fix: typo

* wip

* fix: build-run-where-clause

* exclude task run from entity_id/deser

* feat: add with-run-id helpers

* chore: make complete-task-run idempotent

* feat: export more utils

* fix: support async notification/alerts

* kondo

* fix: test

* support legacy cards

* make sure we complete-task-run in send- sync

* add index to fk

* fix: current-run-id

* fix: move around

* add tests

* fix: needs keyword

* hook up to test endpoints too

* preserver ordering

* handle non hydrated

* add integration tests

* depend on no-op nested behavior, add comment

* fix

* fix: coerce

* GDGT-1497 add TaskRun UI part

* conform to logs format

* chore: add process_uuid

* GDGT-1497 add TaskRun UI part

* GDGT-1497 add TaskRun UI part

* feat: track uuid/updated_at in task run for orphan detection

* add unknown status

* feat: store updated_at/process on insert

* chore: use abandoned

* feat: orphan task

* make not nullable

* chore: add abandoned to FE

* fix

* feat: also abandon if exceeds max duration

* add integration test

* appease prettier

* GDGT-1497 add TaskRun UI part

* GDGT-1497 addressing PR comments

* GDGT-1497 fix url

* GDGT-1497 fix db name and db engine rendering

* GDGT-1497 extract TaskStatusBadge and TaskRunStatusBadge

* GDGT-1497 clean up

* fix typo

* feat: onDelete set null instead of cascade

* GDGT-1497 fix e2e tetst

* Update src/metabase/task_history/models/task_history.clj

Co-authored-by: Dan Stone <wotbrew@gmail.com>

* GDGT-1497 add new e2e tests

* GDGT-1497 fix eslint rules disabling in new e2e tests

* GDGT-1497 addressing PR comments

* fix out of order timestamps

* fix: missed two

* GDGT-1497 addressing PR comments

* GDGT-1497 fix ts issues

* GDGT-1497 fix flakey test

---------

Co-authored-by: Dan Stone <wotbrew@gmail.com>
Co-authored-by: Egor Grushin <egor@metabase.com>
2026-01-19 09:58:36 +00:00
Romeo Van Snick
46b0aa85a2 Fix broken loki test (#68334)
Update Loki Snapshots

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2026-01-19 09:48:08 +00:00
Gabriel Moreno
bb66df77e1 Add library stats to anonymous daily stats ping (#68071)
* feat: add library stats to anonymous daily stats ping

* test: add unit spec for library stats

* test: use the `mt/with-temp` macro
2026-01-16 18:31:25 -04:00
Eric Normand
293d47d3e8 Transforms job runs keep trying other transforms if one fails. (#68141)
Previously, when running a transform job (e.g., daily), it would fail if a single transform in the run failed. This PR makes it so that the job continues to run transforms that don't depend on any failed transform. As previously, if any transform in the run fails, the job is marked as failed.
2026-01-16 22:30:31 +00:00
Gabriel Moreno
3f1ff1ba60 Library empty state: expand Data, Metrics and SQL snippets (#68241)
* feat: add empty states for library items

* test: add e2e specs

* refactor: cleanup library section layout

* test: compact e2e specs into 2 major flows
2026-01-16 18:26:46 -04:00
Timothy S. Dean
e694056f0f Fix coercion for UNIX timestamp fields via implicit joins (#68164)
Addresses #67704.

When a UNIX timestamp is accessed through an implicit join, the coercion to DateTime wasn't being applied. The `allow-casting?` check requires `pos-int?` on `::source-table` to apply coercion. For implicit joins, `::source-table` is set to a string, so it was being skipped.

Fix: in `add-alias-info/add-source-to-field-ref`, wet the flag `:qp/allow-coercion-for-columns-without-integer-qp.add.source-table`. I cribbed this approach from the SparkSQL driver, when it has to rewrite a numeric ID with a string.
2026-01-16 15:26:26 -07:00
Gabriel Moreno
de171c2092 Make Python and SQL editing in Data Studio consistent (#68212)
* feat: configure initial read-only mode for python transforms

* refactor: hide UI elements in readonly mode

* refactor: move database selector to the topbar

* style: add in/out animations for bottom panel

* refactor: move common library controls to the topbar

* test: add unit specs for python transform editor sections

* test: add e2e spec

* fix: show correct run query button state after edits

* refactor: general cleanup & test trimming

* refactor: remove source controls

* refactor: trim down test mocks

* fix: pass missing `editable` flag to transform editor

* fix: types

* fix: e2e data source selector

* refactor: use `isEditMode` instead of `readOnly`
2026-01-16 18:12:20 -04:00
github-automation-metabase
fd2bf97c1f Auto-update documentation for master (#68219)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-01-16 16:44:55 -05:00
Denis Berezin
0bba5e8742 UXW-46 Safari smart scalar truncation (#68248)
* UXW-46 refactor solution

* Update Loki Snapshots

* Fix typecheck

* Fix e2e

* Refactor to simpler solution

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2026-01-17 00:43:41 +03:00
Nick Fitzpatrick
3302e9cafd Gdgt 912 update scalar second tab and configuration to support color (#67877)
* adding segment editor to scalar

* temp

* adding tooltip

* pretend i'm a clojure dev, disable tooltip when there are no segments

* adding unit test and story

* loki tests

* silly me

* I am a clojure god

* adjustments

* adding docstring, adjusting loki test

* combining scalar loki tests

* CardSegment -> ScalarSegment

* BE update, filter unvalid segments
2026-01-16 16:37:41 -04:00
Denis Berezin
18c485d06c Fix missing labels for bar chart (#68299)
* Fix missing label for cartesian

* Add e2e tests

* Add comment

* Update Loki Snapshots

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2026-01-16 22:54:53 +03:00
Aleksandr Lesnenko
68d40f2770 Ask for loki stress testing (#68302)
update docs, pr template
2026-01-16 14:51:09 -05:00
Nemanja Glumac
b92393b9f0 Enable codespell GitHub action for src folder (#68213) 2026-01-16 13:37:22 -06:00
Egor Grushin
83ca220730 GDGT-1419 warn when incremental edits break checkpoint auto selection (#67933) 2026-01-16 17:49:14 +00:00
Thomas Schmidt
ba7c5d1fc7 Require free text for ui-bug and other feedback types (#68234)
* Require free text for ui-bug and other feedback types

Add Yup validation to MetabotFeedbackModal that requires free text feedback when issue type is ui-bug or other. Issue types requiring free text are maintained in a constant array for easy extension.

* Address PR feedback: improve type safety and UX in feedback modal

- Replace 'as any' with proper TypeScript type assertion
- Fix type inconsistency between schema and initial value for issue_type
- Add dynamic label showing '(required)' when ui-bug or other is selected

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* pr feedback

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Sloan Sparger <sloansparger@gmail.com>
2026-01-16 11:34:12 -06:00
Nemanja Glumac
2cf11310a8 Fix untranslated string in an alert modal (#68287)
Co-authored-by: Joseph Adams <danielowenderefaka@gmail.com>
2026-01-16 17:53:24 +01:00
Riley Thompson
06d4da18c3 Surface analysis errors with upstream dependencies (#68092)
* initial work

* fix test

* fix another test

* source entity malli schema

* clean up and add test

* add tests

* clean up

* fix tests

* drop finding_details column

* fix analysis version

* Update enterprise/backend/src/metabase_enterprise/dependencies/models/analysis_finding.clj

Co-authored-by: Timothy S. Dean <timothy.dean@metabase.com>

* use transaction

* use node-errors refactor suggestion

* use maybe-resolve-join

* add schemas

* add comment

---------

Co-authored-by: Timothy S. Dean <timothy.dean@metabase.com>
2026-01-16 15:08:44 +00:00
John Swanson
44e118b5e3 Manage table metadata allows syncing table (#67868)
This is the permission we're correctly checking with the below
`api/check-403` but by using `warehouses/get-database` (which, btw, has
the MOST confusing possible arguments I've ever seen) we were throwing a
403 if we didn't have read access to the whole database (which
checks *create-queries* perms on the entire database).

We still need to exclude mirror databases. In the medium term there
might be a better way to do this - maybe we could somehow have two
different models, so `(t2/select :model/Database)` would always exclude
mirror databases, while `(t2/select
:model/DatabaseIncludingMirrorDatabase)` would return them? I dunno.
2026-01-16 06:13:15 -08:00
Gabriel Moreno
3a490774cc Fix the Glossary deduplication UX (#68243)
* feat: prevent duplicate glossary terms from being added

* test: add unit spec
2026-01-16 09:55:25 -04:00
Timofey Kachalov
d5ad9d6142 fix(embed-js): adjust experience reset logic to avoid unexpected experience resets (#68273) 2026-01-16 17:09:53 +04:00
William
eacff63768 Disable native sql validation (#68148)
Native sql validation is a bit too unreliable for general deployment at the moment, so we are disabling it for check_* endpoints and the broken entities list unless/until we can make it more reliable.

Co-authored-by: Alexander Polyankin <alexander.polyankin@metabase.com>
2026-01-16 11:28:04 +00:00
Timofey Kachalov
6cea29bace Fix wrong BG value in TableActionInputSearchableSelect (#68275) 2026-01-16 15:21:35 +04:00
Dan Stone
e3d6d76bf8 Hide 0 estimate row counts to avoid confusion (#68190)
Treats 0 n_live_tup as NULL, due to confusion reported when auto analyze
thresholds have not been met on a table.

To justify:
- You have a non-zero estimate (No change)
- A zero estimate but actually have rows (We now hide the estimate)
- A zero estimate and actually have zero rows (We now hide the estimate,
unfortunately)

This behaviour is considered on balance preferable to the behaviour now
where users will likely be confused, even thought we explicitly label
the field 'estimated'.

Other options considered that we might explore in the future:
- Forcing ANALYZE, e.g. on sync
- Bounded/LIMIT count
- Some policy based on last analyze timestamps
- Better tooltips or explaination on frontend

We should revisit in the future once we have a better idea for how
estimates should work across drivers (as its only postgres for now).
2026-01-16 09:03:21 +00:00
Timothy S. Dean
37243f5469 Delete invalid source-card-ids on native SQL questions (#68100)
When a user creates a question based on a model, `source_card_id` was set to the model's ID. If that question was later converted to native SQL, `source_card_id` wouldn't get cleared. This means that deleting the model would cause the question to be deleted even though they no longer have any relationship to one another.

The code fix won't help anyone whose data is already incorrect, so this adds a migration to correct the inconsistent data. I added an assertion to the t2 hook to catch this at dev time in the future. And ultimately, the delete cascade seems overkill, so there's a migration to replace that with SET NULL instead.
2026-01-15 16:19:13 -07:00
bryan
ad60b57c4a Fake sync for Redshift tests (branch-conditional, refactored) (#67603) 2026-01-15 15:53:45 -07:00
Anderson
fa924880ad Implement read-only on Library & Data Structure pages (#68209)
* Implement read-only on Library page

* Add some gorgeous unit tests

* Make segment and measures read-only / Add tests

* Apply read-only logic to measure list and segment list pages
2026-01-15 19:50:51 -03:00
Romeo Van Snick
bace1d68c5 Flake fix: allow clicking gridcells while animating (#68218)
Allow clicking while animating
2026-01-16 09:44:15 +11:00
Maksym Yakubych
0523cf2397 fix: dropdown menu in create/edit record on database table (#67807) 2026-01-15 17:51:15 -04:00
Alexander Polyankin
c75465cd07 FE fixes for upstream dependencies (#68254) 2026-01-15 16:44:08 -05:00
kevinkelleher12
a76e880fdd Fix filters not closing properly on native SQL questions (#68216) 2026-01-15 16:06:26 -05:00
Alexander Polyankin
032d1e9ea5 Add server-side sorting to broken & unreferenced items pages (#68221) 2026-01-15 19:59:14 +00:00
Oleksandr Yakushev
b2840f32f9 Replace amalloy/ring-buffer dependency with already included CircularFifoQueue (#66007) 2026-01-15 20:34:29 +02:00
Timofey Kachalov
499eacf3d1 Fix EE Starter Edition Embedding Admin page visuals (#68226) 2026-01-15 21:27:33 +04:00
Denis Berezin
23d9096d0b UXW-136 Fix issue with bar viz on filtered column (#67573)
* UXW-136 Fix issue with bar viz on filtered column

* Review fixes

* Refactor solution

* Review fix
2026-01-15 17:17:07 +00:00
Dan Stone
594cd0cc89 Remove ^:parallel meta for tests that search + hold locks (#68240)
A recent change to search permissions queries in [#67055](https://github.com/metabase/metabase/pull/67055) will cause H2 to use SYS locks during search operations. This is because H2 uses temporary tables to implement CTE's, and their creation/dropping requires global locks.

This commit removes some ^:parallel meta in an attempt to avoid test
flakes due to lock timeout.

This change is a bit speculative:

- It is not 100% confirmed that parallel tests are the only problem (e.g. some background task might also hold a lock)
- The tests changed are based on a cursory scan for search tests that
  hold transactions (mt/with-temp). There may be other tests.

The impact of the CTE lock behaviour in production searches is likely
minimal because:

a. Search queries will typically run in auto commit sessions and so lock
lifetime will be short
b. concurrent multi-user deployments are most likely not on H2.

Should keep an eye on both tests and any reports in production of lock
timeout errors / slow searches when using H2.
2026-01-15 17:05:14 +00:00
da
f3c0be5fc1 Log error instead of warning if a subscription is not sent through the channel rather than a warning (#68214)
* Why is it a warning when it should be an error?

* Fix error logging format in notification worker

* Improve error logging in notification send process

Fix silly mistakes that I do when I'm sleepy
2026-01-15 13:20:40 -03:00
Timofey Kachalov
950b555558 feat(sdk, embed-js): Add Content Translations for SDK InteractiveQuestion new query Editor (#68063) 2026-01-15 20:13:21 +04:00
Jeff Bruemmer
2e65eac90e docs- remove sample app (#68235)
remove sample app
2026-01-15 14:59:24 +00:00
Timofey Kachalov
c73ccb8be7 Cleanup additional space to properly build Sample Apps (#68229) 2026-01-15 17:31:59 +04:00
William
7976ad4f47 Refresh child card result metadata on card edit (#68043)
When a card is updated, look for all mbql child cards and recalculate their result metadata.  With models, calculate
what their "correct" result metadata is pre-update, use that to calculate user overrides, and then reapply those
overrides when computing the new result metadata.

This should fix a variety of bugs around users updating a model and then not seeing those change downstream.
2026-01-15 09:41:36 +00:00
Thomas Schmidt
825719067a Improve Metabot input and message scrolling UX (#68117)
- Add max-height and vertical scrolling to input area
- Fix newline preservation in multi-line messages
- Add horizontal scrolling for wide code blocks in messages
- Style code blocks with proper background, border, and custom scrollbar
- Reduce code font size to 0.6875rem for better proportion
- Increase user message bubble width to 90%
- Add inline code styling with background and border
2026-01-15 08:43:34 +00:00
Anderson
95af300c15 Disable git pull button when there are no changes to pull (#67968)
* Add /has-remote-changes endpoint to remote-sync API

Adds a new endpoint GET /api/ee/remote-sync/has-remote-changes that checks
if there are changes on the remote (Git) repository that can be pulled.

Response format:
{
  "has_changes": true,
  "remote_version": "abc123...",
  "local_version": "789xyz...",
  "cached": false
}

* Disable git pull button when there are no changes to pull

* Fix unit test

* Fix e2e

* Adjust conflict modal 'push' option to always force

* Fix conflict resolution options when switching branches

* Fix modal title not wrapping properly

* Fix long long modal title e2e issue

---------

Co-authored-by: Edward Paget <ed.paget@gmail.com>
2026-01-14 23:38:57 -03:00
Nemanja Glumac
d2f3648298 Remove embedding dev-related folders from Snyk (#68207) 2026-01-14 22:12:35 +01:00
Edward Paget
60093c461b Add /has-remote-changes endpoint to remote-sync API (#67924)
* Add /has-remote-changes endpoint to remote-sync API

Adds a new endpoint GET /api/ee/remote-sync/has-remote-changes that checks
if there are changes on the remote (Git) repository that can be pulled.

Response format:
{
  "has_changes": true,
  "remote_version": "abc123...",
  "local_version": "789xyz...",
  "cached": false
}

* Update api_test.clj
2026-01-14 14:25:41 -06:00
da
aab9fc000a Increase verbosity in the caching middleware (#68121)
* Increase verbosity in the caching middleware

* Fix linter

* Make it simpler

* Broke so many tests

* Make the linter happy

* Fix tests (going back to old implementation)
2026-01-14 17:22:58 -03:00
Timofey Kachalov
28baf73201 Cache Main App/Embed JS fonts (#68120) 2026-01-14 23:14:22 +04:00
Timofey Kachalov
2a70fd1794 fix(embed-js): Fix EmbedJS/SDK dashboard styles to properly display the EmbedJS branding footer (#68090) 2026-01-14 20:06:35 +04:00
github-actions[bot]
05105be4c7 Fix: Add Error state for incorrect CSV/TSV file upload type (#67150)
* Fix: Add Error state for incorrect CSV/TSV file upload type

Fixes #40589

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* make the AI code a bit better

---------

Co-authored-by: Claude Code[bot] <noreply@anthropic.com>
Co-authored-by: Ryan Laurie <iethree@gmail.com>
2026-01-14 15:53:57 +00:00
github-actions[bot]
c0663854c7 Fix: Having : as a special character in the DB name breaks the UI for Clickhouse (#68013) 2026-01-14 10:51:18 -05:00
Alexander Polyankin
fe4d26ab63 Fixes computing columns for Question -> Question -> Model on the FE (#68140) 2026-01-14 09:46:11 -05:00
Edward Paget
30cd48cc7c feat: add table/field/segment support to remote-sync (#67327)
Fully support remote-sync for data studio and make it easier to extend support for remote-sync to other models in the future.

    Supports serializing tables with their fields and segments via remote sync if they are published to a remote-synced collection.
    Supports dirty state tracking of tables, fields, and segments.
    Refetches dirty state when tables, fields, and segments are created/updated/deleted in the data studio
    Make sure the data studio still displays content when remote-sync is in read-only mode
    enforce that tables, fields, and segments published to remote-synced collections are not editable when remote-sync is in read-only mode.
    Deletes, tables, fields, and segments from the remote-sync repo when they are removed or archived.

This also creates two small abstractions to make it easier to add new models (like measures) to remote-sync when they are ready. The remote-sync.events models adds a defmodel-change-handler macro that setups handlers for -create, -update, -delete, events models can publish that the dirty state tracking will follow.

Right now the UI does not change when the data studio is in read-only mode, but all create/edit operations correctly return 403 if you try to modify things. I have a follow up branch to support disabling UI elements.

* feat: add dirty tracking for model changes

* feat: add table, field, segement to dirty state query

* feat: extract fields with tables and segments

when exporting a collection with a table we want to include its children
like fields and segments

* feat: allow importing/deleting tables

and segments and fields

* feat: add dirty tracking for field/segment

* feat: show path in git sync controls

* fix: skip archived segments in table descendants

* fix: view library when in read-only remote-sync

Allows users to still see library folder they can't edit when that
condition is caused by the library being remote-sync enabled and the
instance being in remote-sync mode.

* feat: use remote-sync status in table edit perms

* fix: don't use include_editable_data_model param

...in data studio so these will still load when remote sync is read-only.

* fix: always show dirty library state on removed

We can't track what collections a table was removed from so we just want
to show the library as dirty if any item has a 'removed' dirty state.

* chore: update modules config

* chore: fix kondos

* fix: only publish table update events on ee

otherwise a handler doesn't exist which causes them to throw

* fixup! whitespace

* refactor: make the table changes rendering simpler

* fixup! missing when

* fixup! tests shouldn't mock modules

* fix: make dirty tracking work with new implementation

* refactor: make the hydration step in events cleaner

* fix: make sure dirty returns lowercase

* fix: delete segments correctly

* fixup! remove extra module

* fixup! correct migration order

* fixup! FE lints and typecheck

* fixup! remove correct extraneous module

* Update enterprise/frontend/src/metabase-enterprise/remote_sync/components/ChangesLists/EntityLink.tsx

Co-authored-by: Anderson <ands.alves.nunes@gmail.com>

* fixup! PR feedback and tsc

* fixup! segment failing to redirect

* fixup! better fix for navigate after save

---------

Co-authored-by: Anderson <ands.alves.nunes@gmail.com>
2026-01-14 08:35:16 -06:00
Jeff Bruemmer
b3f62b6b6d note on slack notifications (#68153)
* note on slack notifications

* fix link
2026-01-14 09:23:07 -05:00
github-automation-metabase
50270bc649 Auto-update documentation for master (#68167)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-01-14 09:09:04 -05:00
Romeo Van Snick
b595e58985 Fix a broken model e2e test (#67499) 2026-01-14 15:07:53 +01:00
John Swanson
08b309f4c8 Fix perms checks for unarchiving collections (#67729)
* Fix perms checks for unarchiving collections

* use `can_restore` as single source of truth
2026-01-14 05:10:29 -08:00
John Swanson
db6808c754 Nicer error msg when trying to pull tenant colls (#67948)
Previously if you tried to pull from a remote sync repository that
contained tenant collections you would get an incomprehensible error
that didn't explain what was wrong.

[EMB-1104: Update error message when trying to pull Tenant collections with Tenants turned off](https://linear.app/metabase/issue/EMB-1104/update-error-message-when-trying-to-pull-tenant-collections-with)
2026-01-14 05:08:42 -08:00
John Swanson
ce252a2a8b include API keys when copying DBs (#67998)
[UXW-2690: Instance restored from a H2 snapshot is missing API keys](https://linear.app/metabase/issue/UXW-2690/instance-restored-from-a-h2-snapshot-is-missing-api-keys)
2026-01-14 05:08:27 -08:00
John Swanson
701b90bb9c Increase the unreturned cxn timeout for appdb (#67571)
For the data warehouses we can safely set a fixed
unreturnedConnectionTimeout to a fairly low number (5 minute default)
because we also have a default maximum query length for data warehouses,
which can't be exceeded anywhere.

For the application DB though, this isn't safe, as operations against it
can legitimately hold connections for extended periods - for example,
dump-to-h2 on large databases streams data for as long as it takes to
copy all rows.

Bumping this to 1 hour by default (configurable via
`MB_APPLICATION_DB_UNRETURNED_CONNECTION_TIMEOUT`).
2026-01-14 05:08:10 -08:00
John Swanson
16c291f753 Add support for transforms to collection items (#67832)
* add support for transforms

* tests and hide from non-superusers
2026-01-14 05:07:54 -08:00
dpsutton
a469da0955 simpler tests? you decide (#68144)
* simpler tests? you decide

* ignore discouraged var. just tests. don't need api docs

* avec-server -> with-server

originally there was another `with-server` and i didn't want to clobber
it until i was ready

* bit of cleanup

* cljfmt

* bit of linter appeasement
2026-01-13 16:39:38 -06:00
Nemanja Glumac
9a6393ff4a Enable codespell for dev folder (#68124) 2026-01-13 15:23:18 -07:00
Jeff Bruemmer
46bef2348b docs - skip txt (#68154)
skip txt
2026-01-13 17:10:42 -05:00
John Swanson
0266970fff Admins see personal collections for tenant users (#67949)
* Admins see personal collections for tenant users

[EMB-1110: As an Admin, I want to be able to see personal collections of external users](https://linear.app/metabase/issue/EMB-1110/as-an-admin-i-want-to-be-able-to-see-personal-collections-of-external)

This was already implemented on the BE. Claude helped with the FE but I
think it seems reasonable.

* CR resp

* Remove pagination
2026-01-13 13:17:40 -08:00
Riley Thompson
88ec74f7b3 Upgrade clickhouse to 0.9.5 (#67297) 2026-01-13 15:48:20 -05:00
bryan
b07c00001d Fix nested & misused is in tests found by new kondo version (#67939) 2026-01-13 13:08:40 -07:00
Gabriel Moreno
11e96da48b UXW-2666 Row chart tooltip doesn't reflect column rename (#68137)
* fix: prefer title_text over display_name

* test: add dimension key unit spec

* refactor: rename to `columnTitle`
2026-01-13 18:11:57 +00:00
Thomas Schmidt
5ab27ac0fb Support measures and segments for Metabot (#67368)
* Support measures and metrics for Metabot

* Add segment support to metric querying

* Minor clojure tweaks for metabot measures and segments poc (#67425)

* Handle measures and segments like metrics in table-details and card-details

Move these into the existing m/assoc-some and handle them in the same way as metrics

* Remove query->output-format

This was just a wrapper around lib/->pMBQL, but all these queries are already MBQL5 queries

* Metabot measures and segments cleanup and tests (#67488)

* some refactor

* draft some happy path tests

* use lib for creating measure and segment clauses

* fix tests

* fix some filter tests to use mbql5

* update more tests

* fix more tests

* fix model query syntax

* lint

* remove normalize call again

* add back normalize

* minor test cleanup

* address comments

* tweak another test

* add a query= helper that strips uuids, update a number of tests to use it

* add basic error handing for bad ids

* Minor cleanup

* address mike's comment

---------

Co-authored-by: appleby <86076+appleby@users.noreply.github.com>
Co-authored-by: Noah Moss <32746338+noahmoss@users.noreply.github.com>
Co-authored-by: Noah Moss <noahbmoss@gmail.com>
2026-01-13 12:50:17 -05:00
Alexander Polyankin
7cd7ef457a Broken & unreferenced entities - add pagination, expose tables (#68110) 2026-01-13 16:42:14 +00:00
Edward Paget
79f43e1259 fix: don't unset remote-sync settings on api req (#67605)
* fix: don't unset remote-sync settings on api req

...if request is partial. Fixes an issue where the token could be unset
when switching between read-write and read-only modes.

* add debugging

* remove debugging

* fixup! handle extra collection

* fixup! update syntax
2026-01-13 09:46:14 -06:00
Jakub Chodorowicz
739a915d5d Uxw 2596 color range on table crashes it if values span a large scale (#68022) 2026-01-13 16:39:04 +01:00
Anderson
5c6c075103 Improve design of no-owner state in data structure side panel (#67772)
* Improve design of no-owner state in data structure side panel

* fix e2e test
2026-01-13 12:12:03 -03:00
Denis Berezin
2d76c2fb74 Fix public powered by metabase footer link (#68069)
* Fix public powered by metabase footer link

* Fix tests
2026-01-13 17:43:47 +03:00
Jakub Chodorowicz
63be293945 Prg 160 add ssl grouping config (#67682)
Co-authored-by: Nicola Mometto <nicola.mometto@metabase.com>
2026-01-13 15:09:30 +01:00
Nemanja Glumac
221b76041d Enable codespell GH action for frontend (#68073) 2026-01-13 13:05:19 +00:00
Nemanja Glumac
8d4837c6b0 Remove deprecated moveDnDKitElement helper (#67604)
Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>
2026-01-13 13:49:49 +01:00
github-automation-metabase
7879a97840 [chore] Update llms.txt for master (#68113)
Update llms.txt and llms-full.txt (master)

Regenerated llms.txt to include all markdown files from the docs/ directory.
Also generated llms-full.txt files for the embedding section.

🤖 Generated automatically by llms-txt-generate workflow

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Actions <actions@github.com>
2026-01-13 09:49:53 +00:00
github-automation-metabase
4d820ce589 Auto-update documentation for master (#68105)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-01-12 20:35:29 -05:00
Nathan Voxland
cdcaaf5f33 If the entity id is unknown when calling the export API, throw an error (#68040) 2026-01-12 17:07:26 -06:00
bryan
a2e9d66d7a Disable regex lookaheads/lookbehinds for Snowflake driver (#68084) 2026-01-12 14:57:04 -07:00
github-actions[bot]
04d68a6a41 UXW-46 In Safari Scalar is truncated like a string rather than a number (#67207)
* Fix: In Safari, Reducing the Tile Size of a Number viz Might Result in the Number Being truncated like a String Rather than Rounded

Fixes #51082

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* UXW-46 refactor claude solution, implement proper fix

* Update Loki Snapshots

* Fix e2e tests

---------

Co-authored-by: Claude Code[bot] <noreply@anthropic.com>
Co-authored-by: Denis Berezin <denis.berezin@metabase.com>
Co-authored-by: Metabase Automation <github-automation@metabase.com>
2026-01-13 00:10:24 +03:00
Denis Berezin
ad87e0366a UXW-64 Fix table cell formatting for temporal breakout by week (#67477)
* UXW-64 Fix table cell formatting for temporal breakout by week

* Review fixes
2026-01-13 00:09:17 +03:00
Edward Paget
90ba3e39e7 feat: split can-read from can-query in data model (#67815)
* feat: split can-read from can-query in data model

Adds a new kind of permission type `can-query` that describes when a
user is allowed to query the data model vs `can-read` which encompasses
when a user can see the metadata of a query. This makes api calls to
read table metadata more straightforward and the eventual integration
with remote sync easier.

* feat: update api to use can-edit/can-query params

* fixup! allow can-write-metadata queries

* fixup! field test

* fixup! whitespace

* fixup! returning empty lists instead of 403

* fixup! schema response

* fixup! enforce query permissions where necessary

* fixup! add last tests

* fixup! can query filter before saved questions
2026-01-12 14:46:40 -06:00
Cam Saul
ee9ba65762 Introduce module :friends (#67292) 2026-01-12 11:54:04 -08:00
Cam Saul
469c2f4681 Minor cleanup: fix function with side effects name (#68044) 2026-01-12 18:29:26 +00:00
Maksym Yakubych
696d8eec73 fix: text selection inside card embed when interacting with card embeds (#67761) 2026-01-12 13:25:34 -05:00
kevinkelleher12
fbe2dd23a4 Fix funnel viz to handle increasing data (#68031) 2026-01-12 18:02:03 +00:00
Anderson
85fe26063c Fix data studio missing some hover states (#67891)
* use ActionIcon for data studio toggle icon

* Use ActionIcon on snippet tree row ellipsis menu

* Change link colors in breadcrumbs on hover

* Use ActionIcon for tree expand icon

* Update hover state on transforms runs filters

* Fix data studio nav collapsed logo hover

* Match hover state on snippets collection and snippets folders

* Fix ts
2026-01-12 14:24:53 -03:00
Alex Yarosh
afdd39c531 docs: Update link to Metabase pricing page (#68067)
Update link to Metabase pricing page
2026-01-12 14:35:23 +00:00
github-automation-metabase
fb22fed921 Auto-update documentation for master (#68052)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-01-12 09:34:12 -05:00
Edward Paget
07c5e47251 fix: remote-sync origin url errors (#67594)
* fix: remote-sync origin url errors

Fixes issues where the tmp directory for the remote-sync repo can get
into a bad state where it doesn't have an origin URL. This calls a
function that explicitly sets our desired origin URL and updates all
calls to use the more specific :remote-url keyword rather than
inconsistently using :url vs :remote-url.

* Update git_test.clj
2026-01-12 08:23:50 -06:00
metamben
fd9a13e05e Measures cleanup (#67960)
* Extract cycle detection algo and fix available-measures
* Rremove duplicated code.
* Add more serialization tests
* Fix CLJS
* Remove MBQL4 support for measures at the  model level
2026-01-12 17:09:35 +03:00
Phoomparin Mano
a46764dd85 Add virtualized grid to collection list view for tenants (#67958)
Co-authored-by: Sébastien <sebastien@metabase.com>
2026-01-12 13:42:20 +00:00
Phoomparin Mano
a4e306f9cf Fix issues with the llms.txt generation workflow (#68019) 2026-01-12 17:07:07 +07:00
Phoomparin Mano
4ec8c0cb0e fix(sdk): fix crashes on React 19 due to findDOMNode on Gauge and Modal (#67953) 2026-01-12 16:56:43 +07:00
Alexander Polyankin
bff5dfb5eb Fixes (#68046) 2026-01-10 03:31:22 +00:00
Aleksandr Lesnenko
0deffd6231 add loki stress test workflow (#68042) 2026-01-09 20:36:22 -05:00
Aleksandr Lesnenko
9311117086 tweak tree table column widths (#68035)
* tweak tree table column widths

* tweak widths

* specs
2026-01-09 23:11:23 +00:00
Alex Yarosh
9a37785bc3 Fix sentence in JWT Identity Provider URI description (#68038) 2026-01-09 17:44:33 -05:00
Alexander Polyankin
3b52306116 Add a filter for personal collections; preserve filters in the URL, drop the broken dependencies page for now (#68008)
* wip

* wip

* wip

* wip

* wip

* Filters

* wip

* tests

* Fixes

* wip

* Add e2e test

* wip

* comment

* wip initial personal coll filter

* allow deleting personal collections

* used by

* whitespace

* lint

---------

Co-authored-by: Riley Thompson <rileythompson99@gmail.com>
2026-01-09 17:33:18 -05:00
Edward Paget
7a753622e0 fix: make sure we don't sync unchanged collections (#67795)
* fix: make sure we don't sync unchanged collections

* fixup! bad test
2026-01-09 15:55:35 -06:00
Edward Paget
09860c0032 fix: limit can_run_adhoc_query hydration (#68028)
We can't hydrate unbounded collections of cards with the
can_run_adhoc_query hydration since it linearly adds db queries to the
request. Users with > 10000k can have severe CPU/memory issues
processing this.
2026-01-09 15:55:06 -06:00
Egor Grushin
48e3b5c190 QUE-2687 remove automatic selection of the first option in TemporalUnitDropdown. (#67598) 2026-01-09 20:59:29 +00:00
Ryan Laurie
08421d9ec1 remove broken overlays demo (#67995) 2026-01-09 20:26:08 +00:00
Jeff Bruemmer
1c9de41832 docs - fix translation docs (#68011)
* fix translation docs

* comment

* sdk

* data

* cleanup
2026-01-09 20:03:15 +00:00
Nemanja Glumac
4497b15aed Enable codespell for modules/drivers (#68010) 2026-01-09 20:58:06 +01:00
Abed Habli
7a8b15e271 Docs: AI exploration (#67859)
* AI exploration section

* Optimized 2 images, saved 221.4 KB (51.0% smaller)

* fix the heading link

* Update docs/ai/metabot.md

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

* Update docs/ai/settings.md

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

* few edits

* typo

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2026-01-09 20:54:55 +01:00
Nemanja Glumac
75476f4ae1 Fix frontend typos (#68003) 2026-01-09 20:41:58 +01:00
Robert Kosara
4e60b2efeb Mention search in data picker docs (#67930)
* Replace data picker image, add a line about search

* Optimized 1 images, saved -360 bytes (-1.1% smaller)

* Fix screenshot and description to talk about v58

* Incorporate bot suggestion

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2026-01-09 10:41:05 -08:00
Alex Yarosh
3315a9a65a plan callouts (#68014) 2026-01-09 13:33:29 -05:00
Alex Yarosh
d20f6f9f11 docs: minor edits to tenants (#67961)
* Fix heading level for multi-tenant strategy section

* Correct 'Admin setting' to 'Admin settings'

Updated references from 'Admin setting' to 'Admin settings' for consistency throughout the document.

* more edits

* typos
2026-01-09 13:32:51 -05:00
Riley Thompson
686de1c06e Exclude archived items from unreferenced and broken items endpoints (#67950) 2026-01-09 13:08:25 -05:00
Nicolò Pretto
7b6b37264a docs(sdk): remove links to package changelog (#67997) 2026-01-09 18:37:36 +01:00
Nick Fitzpatrick
20ec35314f Typesafe c and bg props (#67899)
* most of the way there

* happy types, simpler themeColor function

* PR Feedback

* make editor buttons slightly less offensive

* final adjustments
2026-01-09 13:31:22 -04:00
Maksym Yakubych
c7f4935d58 fix: ellipsis breadcrumb shows gray background in Dark Mode (#67805)
* fix: ellipsis breadcrumb shows gray background in Dark Mode

* refactor: use `metabase/ui` in `CollectionBreadcrumbs`
2026-01-09 16:55:35 +00:00
Nemanja Glumac
80b6060ab7 Enable codespell for the enterprise folder (#67979) 2026-01-09 17:55:26 +01:00
Timofey Kachalov
b374706a41 feat(embed-js): Change guest embeds disabled tooltip to display a link to admin settings (#67925) 2026-01-09 20:29:38 +04:00
github-automation-metabase
a131b9c921 Update llms.txt and llms-full.txt (master) (#67993)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Actions <actions@github.com>
2026-01-09 16:00:20 +00:00
Nicolò Pretto
d4486c9dff fix: make dashboard header use container queries to respond to metabot (#67376)
* fix: make dashboard header use container query

* use named container everywhere

* fix syntax

* rename and extract to other class
2026-01-09 16:59:33 +01:00
Sébastien
ad5cc2877d Allow passing arrays of string as sqlInitialParameters in InteractiveQuestion (#67282)
* Allow passing arrays of string as sqlInitialParameters in InteractiveQuestion

* nit

* better assertion

* pass all initial sql params as is
2026-01-09 16:50:19 +01:00
Jeff Bruemmer
88647269a0 docs - embedding browser options (#67957)
* browser params

* array options
2026-01-09 10:08:14 -05:00
Anderson
f0ab6a222c Show border on segment name editable content in new segment page header (#67946)
* Use PaneHeaderInput on NewSegmentHeader

* Apply segment name on content change
2026-01-09 12:01:39 -03:00
Nicola Mometto
cc9f7e63ad submit transform metering data to metering endpoint (#67902) 2026-01-09 14:36:52 +00:00
Nemanja Glumac
3798862761 chore: Fix safe typos in enterprise/ folder (#67912) 2026-01-09 15:05:04 +01:00
Nemanja Glumac
3fbd0ff00d Increase the viewport width for a flaky "data studio" e2e tests (#67901) 2026-01-09 16:55:20 +03:00
Nicola Mometto
9f30405075 Fix serialization in the presence of xray of usage analytics (#67848)
* feat: separate analytics vs non analytics escapes

* update callsite

* fix: descendant-ids requires coll models

* add test

* fix: nil safe
2026-01-09 09:43:16 +00:00
Romeo Van Snick
363baef1d9 Add defensive toString to column name (#67893) 2026-01-09 14:10:36 +11:00
github-automation-metabase
6cdb558f0e Update generated docs (master) (#67966)
Co-authored-by: github-actions <github-actions@github.com>
2026-01-08 20:40:59 -05:00
Aleksandr Lesnenko
13ec0f6fc8 fix tasks table (#67964) 2026-01-09 01:34:50 +00:00
Nick Fitzpatrick
a6b5cb7371 updating ClauseStep type, fixing segment and measure editors (#67956) 2026-01-08 20:53:19 -04:00
Maz Ameli
2e6bb7f669 Rename Tasks page to Dependency diagnostics and update labels (#67935) 2026-01-08 19:23:03 -05:00
Egor Grushin
c822a6228c GIT-8461 hide "Visualize another way" button for Sankey charts (#67753) 2026-01-08 23:46:37 +00:00
Phoomparin Mano
2229469ca4 Add documentation button to tenants list page (#67884) 2026-01-08 23:03:36 +00:00
Egor Grushin
43ad099236 fix flake unit test (#67942) 2026-01-08 21:53:50 +00:00
Braden Shepherdson
b496e05834 [perf] Add a unit test for #66955 as a follow-up (#66958) 2026-01-08 16:18:09 -05:00
Gabriel Moreno
2847a18d60 UXW-2623 Update dependency graph labels and icons for sql questions (#67870)
* feat: include query type on dependencies api response

* feat: show icons based on query type

* test: add unit spec for dependency graph utils

* refactor: restore changes after merge conflict
2026-01-08 16:05:42 -04:00
Braden Shepherdson
413b32e277 [perf] Expand the qp.perf-test benchmark suite (#65806)
Lots of new tests, mostly aimed at seeing how the lib and QP scale on
clear dimensions: more stages, wider tables, joins, big expressions.
2026-01-08 19:43:10 +00:00
Alex Yarosh
4a2fade226 Revert "remove transforms once again (#67809)" (#67945)
This reverts commit 7f08349271.
2026-01-08 14:27:24 -05:00
Gabriel Moreno
117e2a22a3 UXW-2629 Adjust library breadcrumb folder expansion behavior (#67862) 2026-01-08 15:25:24 -04:00
Braden Shepherdson
cd5bc6bf72 [QP] Reject fuzzy match of join condition LHS to that join's RHS (#67804)
Fixes #67667.

`lib.equality` has logic to do "fuzzy" matching of field refs with
the corresponding columns. This logic exists to support somewhat
malformed older queries with impoverished field refs. Refs in healthy
recent queries are fully specified and there's nothing ambiguous to
required the fuzzy matching.

The bug #67667 caught a case where this fuzzy matching could find a
column with the same name on the RHS of a join, if the original target
column has disappeared from an upstream query.

This change causes the QP to fail in exactly this case: when a would-be
LHS ref in a join condition ends up pointing at the RHS of the same
join. That would produce a strange join condition like
`LEFT JOIN Orders ON Orders.ID = Orders.PRODUCT_ID`
which produces incoherent results, and could result in a very costly
Cartesian join.

This is a user-level error, since the query is broken and needs repair.
2026-01-08 14:13:34 -05:00
kevinkelleher12
f1626f8a81 Fix search links for actions and segments 2026-01-08 19:03:19 +00:00
Nemanja Glumac
c82582de0c Provide Cypress env (CI) for the support file (#67934) 2026-01-08 18:49:56 +00:00
Nemanja Glumac
d124262aca Fix typo in a group membership endpoint (#67923) 2026-01-08 12:36:32 -06:00
Aleksandr Lesnenko
22fa6d762a skip flaking loki bar chart spec (#67929) 2026-01-08 18:26:29 +00:00
William
c771b10ea8 Readded fk field ids to v_content's fk fields (#67867)
Basically, the issue is that trying to implicit join using the instance analytics content model's made_public_by_user field made qp throw an error. The underlying problem is that the field in question wasn't defined as a foreign key, even though the model's result metadata claimed it was a foreign key. Updating the field to actually be a foreign key fixed the problem. This also applies to the content model's question_database_id field, which was also fixed.
2026-01-08 10:57:49 -06:00
Nemanja Glumac
98adee8b12 Fix typos in Metabot code (#67918) 2026-01-08 17:18:17 +01:00
Nemanja Glumac
7fe74f70f8 Fix typo in test metadata (#67909) 2026-01-08 14:58:36 +00:00
Riley Thompson
63ce826faa Use source alias for breakout with implicit join (#67480)
* use source alias if we have a fk-field-id

* try only on single stages

* try to identify implicit joins

* try fix

* Clean up

* move test and test all drivers

* move test

* only test drivers with left join feature

* adjust length for certain drivers

* smaller for mysql

* fix starts-with filter

* improve test

* case insensitive filter for h2

* move let bindings up
2026-01-08 14:55:19 +00:00
Nemanja Glumac
63f180034d Fix typos in FE enterprise code translations (#67908) 2026-01-08 15:45:37 +01:00
Anderson
89fa63c99b Show Metabot button on transform creation page (#67837) 2026-01-08 11:19:40 -03:00
Timofey Kachalov
670828db79 Fix flaky "shows a static dashboard using drills" e2e (#67874) 2026-01-08 17:43:16 +04:00
Timofey Kachalov
88684d3b2c fix(embed-js, sdk): Properly handle restricted collection access in MetabaseBrowser (#67523) 2026-01-08 16:47:53 +04:00
Phoomparin Mano
d7b8e86987 Remove static llms.txt and embedding/llms.txt (#67878) 2026-01-08 19:45:56 +07:00
kevinkelleher12
322a6a0323 Reroute admin/tenants to admin/people/tenants (#67869) 2026-01-08 07:34:21 -05:00
Timofey Kachalov
d5b070b8a3 fix(SDK, Embed JS): Hide Static Question topbar from DOM when no children rendered (#67852) 2026-01-08 14:33:40 +04:00
Timofey Kachalov
aa5a35f94c Add support for content translations for auth embeds (#67730) 2026-01-08 14:33:01 +04:00
Romeo Van Snick
adf35e2c4c Use formatting settings for date parameters (#67713)
* Use instance settings for date filters in parameters

* Fix test instance to use default time format

* Add unit tests for date paramater formatting with custom settings
2026-01-08 14:23:42 +11:00
Alexander Polyankin
da9fbb67a2 Dependencies - unreferenced & broken items (#66279)
* entity check jobs seems to work

* reset analysis version of children when updating a card or transform

* transform event tests

* event handlers actually update analyses

* transform runs update dependents and api exists

* initial changes

* params

* fixes

* Fix

* Fix

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* X

* Fix

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fix

* Fixes

* Fixes

* Fixes

* Fixes

* added more tests

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Columns

* Fixes

* Errors column

* Fixes

* Revert "added more tests"

This reverts commit c7188e55dd.

* Fixes

* Revert "Revert "added more tests""

This reverts commit 66b2b7efd9.

* fix compilation

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Add link

* make query validation errors consistent and return them in the broken api

* use the same table

* Fixes

* Fixes

* Fixes

* /graph/broken and /graph/unrecognized match /graph

* Fixes

* Polish

* possibly fix check_card 500

* Fixes

* refactor query-error

* add test for validating sql column with no available sources

* backfill correctly finds dashboard dependencies

* fix comment wording

* bump current-analysis-version

* revert error type names

* make validation exceptions store errors in the standard format

* rename unknown-error to validation-error

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fix

* Fixes

* panel

* Fixes

* Fixes

* Fixes

* Save

* Fixes

* Add missing types

* Fixes

* Fixes

* Fixes

* also analyze segments

* add more tests

* Fixes

* Fix

* Fixes

* Fixes

* status

* Hide dependencies when not analyzed

* Tests

* Tests

* Tests

* Tests

* Tests

* Fixes

* Fixes

* Remove columns

* run backfills immediately during test startup

* remove token checks for maintaining dependencies

* run dependency backfill on serdes

* Tests

* Fixes

* Fixes

* Fix types

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* fix bug involving nonstandard tag spacing

* fix some broken tests

* Tests

* Tests

* Fixes

* Tests

* Fixes

* FixesTests

* Fixes

* Fixes

* Tests

* Fixes

* Fixes

* Fixes

* Fixes

* fix another test

* Fixes

* Add missing info

* Fix tests

* Hydrate collection for snippets

* Fix

* Fixes

* revert unnecessary change

* some lint fixes and a bunch of schemas

* fix compilation

* lint fixes

* new events derive from metabase/event

* simply specs to work with open-api spec gen

* dependency backfill checks tokens again

* Fixes

* fixed tests

* don't use ::ns/blah in a #_ comment when ns isn't in scope

* fix more tests

* add and update more tests

* lint fixes

* fix linting and make lib changes backwards compatible

* maybe fix more tests?

* fix ns name

* fix another test

* update modules config

* fix one test and debug second

* more test debugging

* yet more test debugging

* fix test?

* fix more tests?

* revert another unexpected migration change

* fix another test

* fix linting

* fix more tests

* update openapi spec

* fix unrelated bug with nil ancestors

* add test for nil ancestors bug

* Remove /status call

* Merge

* Fixes

* Fixes

* Fixes

* Fixes

* review feedback

* more cleanup

* yet more cleanup

* support unnormalized snippet tags

* more review feedbac

* fix build

* fix linting

* update lib.parameters.parse to match driver.common.parameters.parse

* fix compilation

* fix tests

* fix more tests

* fix more tests

* possibly fix linting

* fix more tests

* fix even more tests

* maybe fix tests?

* actually make backend support currently impossible snippet names

* Use TreeTable

* Remove unused component

* Renaming

* FE fixes

* switched migration to 59

* fully revert 58 migrations

* most review feedback

* factor out common setup from events tests

* deduplicate analysis gen tests

* more test fiddling

* final review feedback

* actual final review feedback

* linting

* Fix merge

* Fix lint

* reformat

* add measures to spec

* fix final test

* Fix links

---------

Co-authored-by: William Zimrin <william@metabase.com>
2026-01-07 21:57:09 -05:00
github-automation-metabase
314122dee5 Update generated docs (master) (#67890)
Co-authored-by: github-actions <github-actions@github.com>
2026-01-07 21:50:19 -05:00
Nick Fitzpatrick
3975adb932 Color Key Cleanup (#65855)
* Migrating Color Keys

temp

background keys

fixing some errors

border colors

removing duplicate keys

types

* enforce types on c prop

* more type cleanup

* rebase catch up

* unit tests

* re-add embedding sdk setup plugin

* e2e tests

* Sankey chart using correct label color in static viz, fix background detection

* some loki changes

* adjust border color

* sdk: updated sdk color mapping

* type adjustments, unit test fixes

* loki tests passing

* last e2e test

* cleanup

* Update Loki Snapshots

* updating alert colors

* Claude nits

* Update Alert Loki tests

* text-tertiary

* Update Loki Snapshots

* missed one

* last adjustmnet

* Update Loki Snapshots

* text-white

---------

Co-authored-by: Phoomparin Mano <phoomparin@gmail.com>
Co-authored-by: Metabase Automation <github-automation@metabase.com>
2026-01-07 21:15:01 -04:00
Aleksandr Lesnenko
65a2afa186 Let users with data model perm access data studio (#67653)
* let users with data model permission access data studio

* respect manage table metadata permission in data studio

* fix ci

* fix flaky specs

* review

* review
2026-01-08 01:14:00 +00:00
Alexander Polyankin
c65cbf7791 Remove description (#67887) 2026-01-07 16:26:04 -08:00
Alexander Polyankin
42312e5fc2 Allow to overwrite id only for native models (#67773) 2026-01-07 23:56:31 +00:00
Egor Grushin
376ff5d1cf UXW-49 fixing log scale axis value (#67668)
Use a linear scale for values between 0 and 1, and a logarithmic scale for values greater than 1.
2026-01-07 22:54:03 +00:00
Aleksandr Lesnenko
8cbc058a0c table measures (#66576)
---------

Co-authored-by: Tamás Benkő <tamas@metabase.com>
Co-authored-by: metamben <103100869+metamben@users.noreply.github.com>
Co-authored-by: Alexander Polyankin <alexander.polyankin@metabase.com>
Co-authored-by: Brad Anderson <brad@metabase.com>
Co-authored-by: Romeo Van Snick <romeo@romeovansnick.be>
2026-01-07 22:41:11 +00:00
Romeo Van Snick
6b04138204 Add tooltip to run button when field filters are missing a target field in Native editor (#67670)
* Add e2e test for missing field mapping

* Make validateTemplateTags public

* Render errors in run button tooltip

* Pass errors to run button

* Fix selector in test

* Simplify test

* Try with realClick

* Add Lib implementation of validateTemplateTags

* Also validate display-name

* Use Lib implementation of validateTemplateTags

* Localize error messages

* fixup! Add Lib implementation of validateTemplateTags

* Add Lib.ValidationError type

* Remove unused code

* Also validate temporal-units dimension

* Use validate-template-tags in can-run

* Add tag-name to template tag errors

* Fix malli types

* Add tests for validate-template-tags

* Add tooltip to save button too

* Also test time grouping and save button

* Remove more unused code

* Remove simple wrapper

* Use cond-> pattern instead of filter identity
2026-01-08 09:26:43 +11:00
Phoomparin Mano
65d34e4e37 Add GitHub actions to generate llms.txt and llms-embedding-full.txt at repo root during release (#67737)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Actions <actions@github.com>
Co-authored-by: github-automation-metabase <166700802+github-automation-metabase@users.noreply.github.com>
2026-01-07 22:17:34 +00:00
Phoomparin Mano
fd6740eee7 Block official collections in shared collections and its subcollections (#67537) 2026-01-08 05:12:16 +07:00
Riley Thompson
18cf4fac85 fix typo (#67863) 2026-01-07 16:44:43 -05:00
da
17349e4f12 Fix logging messages for field values updates (#66767)
We're logging "Field Field xxx xxxx". I'm just simplifying that log line
2026-01-07 14:43:59 -06:00
kevinkelleher12
bfb78b8d6a Fill line series symbol with appropriate color in dark mode (#67811) 2026-01-07 18:41:03 +00:00
Rodrigo López Dato
343ae8d213 Fix -{un,}install-merge-drivers when using a git worktree (#67865) 2026-01-07 15:28:25 -03:00
kevinkelleher12
e69b260f0b Fix dark text on dark verification tooltip background in light mode (#67799) 2026-01-07 12:13:49 -05:00
Anderson
336180ee0c Make stacked row chart tooltips use custom display names (#67706)
* Make stacked row chart tooltips use custom display names

* Change the way we override seriesName with custom title
2026-01-07 12:16:57 -03:00
Nemanja Glumac
d5925e28f7 Bump Storybook to 8.6.15 (#67473) 2026-01-07 15:52:37 +01:00
Jakub Chodorowicz
5bc3af2630 update husky to v9 (#67846) 2026-01-07 15:41:35 +01:00
kevinkelleher12
c5f433336a add kevinkelleher12 to team.json and github-slack-map.json (#67752) 2026-01-07 08:25:39 -05:00
Dan Stone
dca8465cfb Index incremental filter column for OLTP databases (#66478)
* Add indexes to incremental checkpoint filter columns

* Fix bad barf

* Fix drop-index arg-list

* Less indirect supports test

* Comment on sync order

* Cleanup driver changelog entry

* Move changelog note back to 0.58 (backport)

* Fix passive voice
2026-01-07 12:36:53 +00:00
Alexander Polyankin
618e6e8701 Hide graph watermark (#67839) 2026-01-07 02:13:36 +00:00
Romeo Van Snick
6f637ee050 Test coercion strategy (#67496)
* Also test coerced datetime column

* Add e2e reproduction for opening the datetime filter for coerced fields

* Also check :effective-type in original-isa

* Fix test
2026-01-07 11:19:18 +11:00
github-automation-metabase
c06b4c2511 Update translations 2026-01-06 (#67800)
* Update translation sources 2026-01-06

* Update translations

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-07 00:13:27 +00:00
Alex Yarosh
7cdbdc8e94 docs: Add redirect for interactive embedding quickstart guide (#67833)
* Add redirect for interactive embedding quickstart guide

* Add redirect for quick-start guide
2026-01-06 18:48:13 -05:00
dpsutton
1bcc022f6b Reduce number of modules that trigger driver tests (#67769)
Before:

76 modules trigger:

```clojure
mage.modules=> (let [deps (dependencies)
                     all-deps (keys deps)]
                 (reduce (fn [acc module]
                           (if (driver-deps-affected? deps [module])
                             (conj acc module)
                             acc))
                         []
                         all-deps))
[actions analytics analyze api api-keys app-db appearance audit-app auth-identity auth-provider batch-processing cache channel classloader collections config content-verification dashboards database-routing driver driver-api eid-translation embedding events formatter initialization-status internal-stats legacy-mbql lib lib-be logger login-history model-persistence models notification parameters permissions pivot plugins premium-features public-sharing pulse queries query-permissions query-processor remote-sync request search secrets server session settings setup sso startup sync system task task-history tenants timeline types upload users util version view-log warehouse-schema warehouses enterprise/advanced-permissions enterprise/api enterprise/impersonation enterprise/sandbox enterprise/scim enterprise/serialization enterprise/sso]
mage.modules=> (count *1)
76
```

After:

Only 28 modules trigger driver tests:
```clojure
mage.modules=> (let [deps (dependencies)
                     all-deps (keys deps)]
                 (reduce (fn [acc module]
                           (if (driver-deps-affected? deps [module])
                             (conj acc module)
                             acc))
                         []
                         all-deps))
[actions analyze app-db cache database-routing driver driver-api legacy-mbql lib lib-be logger model-persistence models parameters pivot plugins premium-features queries query-permissions query-processor sync tenants upload warehouse-schema warehouses enterprise/advanced-permissions enterprise/impersonation enterprise/sandbox]
mage.modules=> (count *1)
28
```

How does this magic work? Just with an exclusion list:

```clojure
mage.modules=> driver-affecting-overrides
 #{batch-processing timeline eid-translation version
 enterprise/serialization initialization-status session users enterprise/api login-history sso classloader
 enterprise/sso permissions request view-log system api task-history notification task dashboards startup config
 content-verification secrets server formatter events util settings channel search collections remote-sync types
 api-keys setup enterprise/scim audit-app analytics public-sharing pulse embedding auth-identity auth-provider
 appearance internal-stats}
```
2026-01-06 16:13:33 -06:00
Anderson
0d13842be7 Fix dependency graph zoom controls colors in dark mode (#67774)
* Fix dependency graph zoom controls colors in dark mode

* Do not use :global
2026-01-06 22:00:37 +00:00
Phoomparin Mano
a7d35f1baf Add a tooltip message if model persistence is unsupported for a database (#67566) 2026-01-07 04:09:29 +07:00
Sloan Sparger
0c04a6a3c1 [Metabot] Split up metabot.unit.spec.tsx (#67764)
* init pass at adding an error boundary to metabot

* update the illustration used for error boundary and remove simulated error ui

* add unit tests

* split up the mega metabot.unit.spec.tsx unit test file

* fix lint
2026-01-06 14:47:18 -06:00
Jeff Bruemmer
1888c80fff 58 as latest (#67820) 2026-01-06 15:42:50 -05:00
Alex Yarosh
c1f08f65a6 docs: remove temp tenants docs (#67819)
* remove temp tenants

* jwt

* more link
2026-01-06 14:43:50 -05:00
Jeff Bruemmer
844123dbf2 docs - note on subscriptions (#67816)
* note on subscriptions

* typo
2026-01-06 18:54:00 +00:00
Alex Yarosh
ebd1476a1e docs: tenants (#67474)
* tenants

* Apply suggestions from code review

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

* links

* add links and images and edit remote sync

* links

* one more link

* Optimized 12 images, saved 930.1 KB (47.9% smaller)

* Apply suggestions from code review

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

* edits

---------

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
Co-authored-by: Metabase Automation <github-automation@metabase.com>
2026-01-06 18:47:27 +00:00
Alex Yarosh
78263d64ce documents oss (#67810) 2026-01-06 18:19:25 +00:00
Alex Yarosh
7f08349271 remove transforms once again (#67809) 2026-01-06 13:19:19 -05:00
Jakub Chodorowicz
bfa61de71f add all .env file except .env.example to gitignore (#67793) 2026-01-06 18:27:13 +01:00
Sloan Sparger
d1a55ddff1 [Metabot] Metabot error boundary (#67749) 2026-01-06 11:02:26 -06:00
Nicola Mometto
4e3d8f0caf Move metering events off the token check (#67584)
* chore: remove private from token check defs

* feat: don't send metering stats during token check

* add task for sending metering events

* lift try-catch

* add tests

* move around

* remove duplicate set!

* send ints/bools as strings, for backwards compatibility

* reduce metering frequency

* configurable interval, clamped between 1 min and 12 hours
2026-01-06 16:46:32 +00:00
Nicola Mometto
75ab330328 Add transform metrics to anonymous stats ping (#67786)
* feat: add transforms metrics

* feat: send transform metrics

* fix: don't require transforms feature, we send stats if we disabled the feature

* add tests

* fix: ee test
2026-01-06 15:42:03 +00:00
Ryan Laurie
69abc4cf1c fix translations workflow permissions (#67794) 2026-01-06 15:37:58 +00:00
Noah Moss
6cef5f80d0 Misc cleanup in Metabot clojure code (#67701)
* Misc cleanup in Metabot clojure code

* More misc cleanup

* Lint
2026-01-06 09:27:32 -05:00
Maksym Yakubych
5dd7e2049e chore: add myself to team.json and github-slack-map.json (#67754) 2026-01-06 11:19:09 -03:00
John Swanson
2393146b8c perms for moving collections with archived kids (#67728)
Previously if you had:

```
A (curate)
  B (curate)
    C (no permissions)
      D (curate)
```

Then if C was archived, you would be unable to move or archive A or
B.
2026-01-06 04:42:49 -08:00
Mahatthana (Kelvin) Nomsawadi
112d1d0235 Fix pie chart label not visible on dark theme (#67639)
* Fix `text-secondary` not working on dark theme on charts

* Support all colors so it's easier to reason about

* Add tests

* Fix type error

* Revert part of the code that's not used anymore

* Add test snapshots

* Make overriding font more consistency across environments

e.g. From storybook to SDK to the main app.

* Fix formatting
2026-01-06 12:34:27 +00:00
Sébastien
3f2ad43a43 Fix MB in an iframe running on a subpath (#67724)
* fix MB in an iframe running on a subpath

* fix

* extracted out the util fn and added unit tests for it

* addressed comments

* fixed unit tests
2026-01-06 13:19:02 +01:00
github-actions[bot]
835b3efc27 Update translations 2026-01-06 (#67782)
* Update translation sources 2026-01-06

* Update translations

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-06 11:58:16 +01:00
Romeo Van Snick
d8d4537f29 Fix broken python e2e test (#67435) 2026-01-06 10:00:38 +01:00
Nemanja Glumac
3f35a82ea7 Upgrade jspdf (#67760) 2026-01-06 08:58:38 +01:00
Maz Ameli
a1a62cd603 Add keyboard shortcut to close/open side menu in Data Studio (#67413)
* add keyboard shortcut and tooltip

* refine tooltip position and delay

* also listen for left bracket [ key
2026-01-06 00:56:48 +00:00
Romeo Van Snick
8542738fe7 Add repro for metabase#45890 (#67669) 2026-01-06 09:57:51 +11:00
bryan
f290bbbbe0 Skip cloud driver tests when possible + consolidate test skipping logic (#67568)
* Skips cloud driver tests on PRs unless files changed

Cloud drivers (Athena, BigQuery, Databricks, Redshift, Snowflake) now
only run on PRs when their files changed or 'ci:all-cloud-drivers' label
is present. Full coverage maintained on master/release branches.

* [do not merge] add failing databricks test

* Revert "[do not merge] add failing databricks test"

This reverts commit de5b6fa602.

* empty commit

* Fix cloud driver skip logic to respect ci:all-cloud-drivers label

The previous condition had three checks that could block cloud drivers:
1. !inputs.skip - false when no backend files changed
2. skip != 'true' - from mage can-skip-driver-tests
3. X-should-run == 'true' - the per-driver decision

The problem: checks 1 and 2 would override check 3, so the label had no
effect. Even with ci:all-cloud-drivers, cloud drivers were skipped.

We don't need inputs.skip or can-skip-driver-tests for cloud drivers
because the X-should-run output already encapsulates the full decision:
- master/release branch → run
- ci:all-cloud-drivers label → run
- driver files changed → run
- otherwise → skip

The label is an explicit override, so it should work even on PRs with no
backend changes. Removing the redundant checks lets the label work.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* mage -driver-decisions + roll in module analysis

* Remove quarantine check from test-driver action

Quarantine logic is now consolidated in mage -driver-decisions.
The check happens earlier in determine-driver-skips, so quarantined
drivers get should-run=false and their jobs never start at all.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fail CI if quarantined driver has file changes without break-quarantine label

If you change files in a quarantined driver's module (e.g., modules/drivers/snowflake/)
but don't add the break-quarantine-<driver> label, a new check-quarantine-conflicts
job will fail with a clear error message.

This prevents accidentally merging changes to quarantined drivers without running
their tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add --github-output-only flag to mage driver-decisions

Instead of using grep to filter mage output, the task now supports two modes:
- Default: prints human-readable analysis + GITHUB_OUTPUT preview
- --github-output-only: prints only clean key=value lines for CI

The workflow now calls mage twice: once for debugging visibility,
once with --github-output-only redirected to $GITHUB_OUTPUT.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add quarantine conflict checks to all driver jobs

Extends the quarantine conflict detection to ALL drivers, not just cloud
drivers. When a driver is quarantined but has file changes in
modules/drivers/<driver>/, the job will run but immediately fail with
a clear error message explaining how to add the break-quarantine label.

Changes:
- Add quarantine conflict check steps to presto-jdbc, sparksql, sqlite,
  sqlserver, and vertica jobs
- Update login-to-ecr job condition for vertica quarantine conflicts
- Fix verbose output suppression in --github-output-only mode by adding
  verbose? parameter to changes-important-file-for-drivers?

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add driver decision priority documentation and tests

Adds comprehensive documentation to driver-decision function showing the
priority order as a table, plus explanations of what triggers "driver
module affected" and the difference between cloud vs self-hosted drivers.

Adds mage.modules-test with 14 tests (78 assertions) covering:
- Quarantine logic and break-quarantine labels
- Global skip behavior
- H2 always-runs behavior
- Master/release branch behavior
- Driver module affected behavior
- Cloud driver special rules (labels, file changes)
- Self-hosted driver skip logic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Comment out starburst from driver-directory mapping

Starburst tests are currently disabled in drivers.yml, so the mapping
entry was inconsistent with all-drivers list. Commented out with a note
explaining why, so it can be easily re-enabled when starburst tests
come back.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* silence messages when in github-output-only mode

* remove redundant cloud-driver change detection

- this happens inside the script instead

* get rid of redundant rules definitions

- now only print how we make decisions in help for the task

* make a temporary redshift change

* Revert "make a temporary redshift change"

This reverts commit 3d93c60368.

* format usage fn code

* light refactor

* Rename driver decision variables for clarity and flatten decision tree

- driver-module-affected? → driver-deps-affected? (module dependency graph)
- drivers-changed → particular-driver-changed? (specific driver's files)
- Reorder priority: skip/H2/master now before quarantine
- Flatten nested cond for cloud driver rules

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Quarantine now respected on master/release branches

- Move quarantine check before master/release in driver-decision priority
- Quarantined drivers are now skipped even on master/release (unless break-quarantine label)
- Update tests and priority table documentation to reflect new order
- Cloud drivers don't benefit from driver-deps-affected (only label or file changes)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 16:15:58 -06:00
Nemanja Glumac
1f366dde49 Update copyright year in README.md (#67677)
It's that time of the year again...
2026-01-06 11:05:33 +13:00
Aleksandr Lesnenko
edeea2ead0 fix saved question intro modal layout (#67703) 2026-01-05 21:23:25 +00:00
appleby
fbdf7574ed Fix parsing of :ERROR chunks in metabase-enterprise.metabot-v3.util/aisdk->messages (#67674)
* Fix parsing of :ERROR chunks in metabase-enterprise.metabot-v3.util/aisdk->messages

There was a typo in the case expr where :ERROR chunks were being handled like :DATA chunks, but in fact should be
handled like :TEXT chunks. This was resulting in an error like

    1. Unhandled java.lang.ClassCastException
       class java.lang.String cannot be cast to class
       clojure.lang.Associative (java.lang.String is in module java.base
       of loader 'bootstrap'; clojure.lang.Associative is in unnamed
       module of loader 'app')
                       RT.java:  847  clojure.lang.RT/assoc
                      core.clj:  193  clojure.core/assoc
                      core.clj:  192  clojure.core/assoc
                      util.clj:   56  metabase-enterprise.metabot-v3.util/aisdk->messages/fn/fn
                      ...

whenever an :ERROR chunk was encountered as we tried to ASSOC a string where we were expecting a map.

https://v4.ai-sdk.dev/docs/ai-sdk-ui/stream-protocol#text-part
https://v4.ai-sdk.dev/docs/ai-sdk-ui/stream-protocol#error-part

059d904d6e/ai_service/ai_sdk.py (L50)
059d904d6e/ai_service/ai_sdk.py (L203)
059d904d6e/ai_service/ai_sdk.py (L324)

* Add some error chunk parsing tests to aisdk-line-parse-test

* Mark aisdk-line-parse-test as ^:parallel

This does io to read some files, but should be threadsafe as no other tests read or modify those files.

* Add make-mock-error-stream-response test util

And rename make-mock-stream-response to make-mock-text-stream-response

* Add client-error-test to test streaming-request with error chunks in response
2026-01-05 12:38:04 -08:00
Sloan Sparger
a2aea53b1c [Metabot] Update Metabot icon (#67741) 2026-01-05 13:29:48 -06:00
metamben
d972f4529f Patch malli to avoid OOM related to recursive memoization (#67733)
This is a temporary fix until https://github.com/metosin/malli/pull/1250 gets merged into Malli.
2026-01-05 21:46:29 +03:00
Noah Moss
f1f47d4050 Clarify permissions model for suggested prompts generation (#67656)
* Run suggested prompts generator as admin & fix test

* Add a prompt suggestions GET perms test

* small cleanups

* use mbql5
2026-01-05 13:33:26 -05:00
dpsutton
476f61760c Handle unroutable token checks (#67698)
We have a grace periods and circuit breakers for token checks. But one
issue is that if the token check doesn't throw an error we can't catch
it.

An easy way to see this is to use a local network address that won't
respond like 192.168.random.random (i used 192.168.40.40) then see the
behavior. Without the timeouts, the threads all just get stuck here and
the page never loads. With timeouts, you'll see a few stutters until the
circuit breaker steps in, at which point you have a non-enterprise
version.

https://www.loom.com/share/6ae056dc126b48c9abe8a7ad9366fd05
2026-01-05 11:52:56 -06:00
Copilot
b24727409c Migrate React components from dispatch(addUndo) to useToast hook (#66778)
* Update React components to use useToast hook instead of dispatch(addUndo)

Co-authored-by: iethree <30528226+iethree@users.noreply.github.com>

# Conflicts:
#	enterprise/frontend/src/metabase-enterprise/tenants/containers/NewTenantModal/NewTenantModal.tsx
#	enterprise/frontend/src/metabase-enterprise/tenants/containers/TenantActivationModal.tsx
#	frontend/src/metabase/admin/people/components/GroupDetail.tsx

* type fix

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Ryan Laurie <iethree@gmail.com>
2026-01-05 10:48:54 -07:00
dpsutton
119487b1cc remove api "uses" dependency on api-routes (#67650)
* remove api "uses" dependency on api-routes

api-routes can use all modules to expose their routes. ie it uses
timeline module, etc. It has `:uses :any`.

```clojure
mage.modules=> (let [deps (dependencies)
                     all-deps (keys deps)]
                 (reduce (fn [c module]
                           (update c (if (skip-driver-tests? deps [module])
                                       :skip :run) inc))
                         {:skip 0 :run 0}
                         all-deps))
{:skip 0, :run 153}
```

This is shown in this path here:

```clojure
mage.modules=> (let [ds (dependencies)
                     ds (into {}
                              (map (fn [[k v]] (if (= v :any)
                                                 [k (-> ds keys set)]
                                                 [k v])))
                              ds)]
                 (letfn [(driver-path [to]
                           (loop [q '[[driver]]
                                  seen #{}]
                             (let [p (first q)]
                               (when-let [node (peek p)]
                                 (if (= node to)
                                   p
                                   (recur (into (vec (rest q))
                                                (for [adjacent (remove seen (ds node))]
                                                  (conj p adjacent)))
                                          (conj seen node)))))))]
                   (driver-path 'enterprise/remote-sync)))
[driver warehouse-schema api api-routes enterprise/remote-sync]
```

driver uses arehouse-schema uses api uses api-routes which uses
any. Therefore all changes will trigger driver tests.

So after these changes we observe:
- the path above is empty (drivers don't transitively use remote-sync
module) and therefore would not trigger driver tests
- only 76 modules trigger driver tests

```clojure
mage.modules=> (let [deps (dependencies)
                     all-deps (keys deps)]
                 (reduce (fn [c module]
                           (update c (if (skip-driver-tests? deps [module])
                                       :skip :run) inc))
                         {:skip 0 :run 0}
                         all-deps))
{:skip 77, :run 76}
```

What else did i try?

1. add a `#_{:clj-kondo/ignore [:metabase/modules]}` to the ns
I didn't love this because it felt a bit like cheating. All of this is
kinda annoying because it's fundamentally about changes during dev time.

2. remove the ns require and add a requiring-resolve
This actually doesn't break the module usage analysis. It's smart enough
to see this so this just makes it more tenuous and easy to miss if we
change anything while also still leaving in place the module
entanglement.

So I just fire the event from the api module when rebuilding routes and
handle the event from the api-routes module. The trick is that the api
module sends along the function to rebuild the docs

* handle cycling ref

* remove reference to deleted file

* our linter is scared of an extra line

* use an events namespace

not doing an init namespace as that's similar but not the same. Those
are for settings and models. It's fine to just require the event
namespace in the core namespace. it's a bit of ceremony but the pattern
is useful

* include random event correctly

used to be just `(first (descendants :metabase/event))`. This was
fragile and just now started to fail:

```clojure
models-test=> (first (descendants :metabase/event))
:metabase.api-routes.events/api-events
```

because of course do we things like `(derive ::api-events
:metabase/event)`.

```clojure
models-test=> (filter (comp (complement #{"event"}) namespace)
                      (descendants :metabase/event))
(:metabase.api-routes.events/api-events
 :metabase.audit-app.events.audit-log/card-event
 :metabase.audit-app.events.audit-log/cloud-add-on-event
 :metabase-enterprise.dependencies.events/transform-delete
 :metabase.activity-feed.events.recent-views/legacy-card-event
 :metabase.view-log.events.view-log/collection-read-event
 :metabase.audit-app.events.audit-log/notification-handler-event
 :metabase.audit-app.events.audit-log/user-update-event
 :metabase-enterprise.dependencies.events/transform-run
 :metabase.revisions.events/transform-event
 ...
 )
```

This has been lucky for a long time
2026-01-05 11:28:46 -06:00
Anderson
a5afeea12d Update Remote Sync branch picker to match new designs (#67620)
* Update Remote Sync branch picker to match new designs

* Move git sync controls next data studio logo

* Fix unit test

* Fix e2e test

* Address Claude's review

* Remove console.error

* Use css modules for the chevron icon transition

* Use popover instead of findByRole('presentation')
2026-01-05 17:21:58 +00:00
Ryan Laurie
4521f75ee6 stabilize flaky test (#67646) 2026-01-05 14:05:56 -03:00
Noah Moss
cfdd4de405 try to fix flake in semantic index dlq tests (#67700) 2026-01-05 09:22:27 -05:00
Noah Moss
24f586428d Disable progress bar in whitespace linter github actions workflow (#67695)
* disable progress bar in whitespace linter github actions workflow

* add extra whitespace to demonstrate failure

* Revert "add extra whitespace to demonstrate failure"

This reverts commit ba34650efd.
2026-01-05 09:21:56 -05:00
Nemanja Glumac
0128771ad1 Revert "Replace Cypress grep with Bahmutov's cy-grep (#67660)" (#67725)
This reverts commit d2d8d1fe83.
2026-01-05 14:06:11 +00:00
Timofey Kachalov
e3f05d0cbb Don't close InteractiveQuestion editor on Filters change (#67517) 2026-01-05 17:02:24 +04:00
Dan Stone
53203af754 Add some additional incremental transforms tests (#67683)
* Add some additional incremental transforms tests

* Add missing require

* Use driver/table-name-length-limit
2026-01-05 11:02:08 +00:00
Aleksandr Lesnenko
71c188c09f Use tree table in data model (#67117)
* use tree table in the data model section of data studio

* review
2026-01-02 18:05:57 +00:00
Nick Fitzpatrick
db48071330 Don't show metrics in the join step (#67490) 2026-01-02 13:01:25 -04:00
Nick Fitzpatrick
05d04cf64b specify gauge label sizes in px (#67386) 2026-01-02 12:54:35 -04:00
Nick Fitzpatrick
6c99df07a8 Adding e2e repro for drill through entity keys (#67467) 2026-01-02 12:54:19 -04:00
Alex Yarosh
5b92cc2b02 Improve formatting and clarity in serialization.md (#67587)
Updated curl command formatting and clarified instructions for exporting and importing Metabase data.
2026-01-02 10:41:15 -05:00
Vamsi Peri
fea1cbad4b Update issue templates (#67687)
* Update issue tempaltes

* Delete .github/ISSUE_TEMPLATE/task.md

* Update verbiage for new feature request
2026-01-02 10:24:50 -05:00
Jakub Chodorowicz
024c43ff39 fix: broken date filter test (#67684) 2026-01-02 16:18:14 +01:00
Edward Paget
ff4f2bf956 feat: add git settings modal to data studio (#67178)
* feat: add git settings modal to data studio

* Refactor GitSettingsModal to reuse existing settings form / Adjust some styles

* Fix and improve unit tests

* Adjust font size according to variant

* fix unit test

* fixup! mock API not other plugins in this layout

* Split unit test files and improve endpoints setup

* Implement PLUGIN_REMOTE_SYNC.GitSyncSetupMenuItem with internal rendering condition

---------

Co-authored-by: Anderson <anderson@metabase.com>
2026-01-02 11:55:52 -03:00
Nemanja Glumac
d2d8d1fe83 Replace Cypress grep with Bahmutov's cy-grep (#67660) 2026-01-01 12:33:26 +01:00
Eric Normand
e5ab9db7bc Extra remapped fields (#67601)
* kick ci

* Disable remaps when calculating columns for a query.

* Add tests for result_metadata remappings

* Add comments

* Whitespace
2025-12-31 19:07:17 +00:00
Braden Shepherdson
4786076692 [dashboards] Handle parallel FKs with dashboard filter values (#66287)
Fixes #65838.

This issue was about dashboard filters showing the wrong value when
the filter was bound to an FK field from a table with multiple FKs to
the same foreign table. The dashboard parameters logic on the BE was
choosing which FK to use for the filter values arbitrarily, meaning that
binding the filter to one of them would work fine, but the other would
give incoherent results.

The fix is to be deliberate about selecting the parameter's column. That
doesn't solve all ambiguous cases, but we really can't help if there's
a multi-hop join that has parallel edges in the middle!
2025-12-31 11:46:34 -05:00
Nicola Mometto
1e3a879116 Mage python runner (#67265)
* disable chunked encoding if using path style access

* mage task to start python runner with mock s3
2025-12-31 11:03:13 +00:00
Aleksandr Lesnenko
2c01e5063b series limit for row chart (#67419) 2025-12-30 20:08:11 -05:00
Ryan Laurie
b4912b71f1 more entity cleanup (#66659) 2025-12-30 17:23:34 -07:00
Nathan Voxland
1d8b669f62 Avoid joins of remote_sync_object with actual tables (#67042) 2025-12-30 15:37:13 -06:00
Denis Berezin
25091a2fd1 UXW-603 unified picker for Document smart link (#67408)
* UXW-603 temp unified picker

* Add unified data picker

* Fix issues with tabs, add e2e tests

* Self review
2025-12-30 18:06:54 -03:00
Timothy S. Dean
6f00f47c47 Simpler fix than first attempt. (#67300) 2025-12-30 22:41:43 +03:00
Aleksandr Lesnenko
07e2560596 fix zoom resets on resize (#67420) 2025-12-30 13:15:21 -05:00
dpsutton
d47b9d6759 bumping deps: (#67638)
- https://github.com/metabase/metabase/security/code-scanning/543
  about snowflake's of grpc netty shaded. We already have this
  version elsewhere so now it matches
- https://github.com/metabase/metabase/security/code-scanning/549
  and https://github.com/metabase/metabase/security/code-scanning/557
  issue in databricks. We bumped that and now it uses the new coordinate
  `at.yawk.lz4/lz4-java 1.10.1`
- https://github.com/metabase/metabase/security/code-scanning/496 bump commons-lang3.
  actually just exclude it from the driver jar so it will be found on parent
  classpath with coordinate from deps.edn: `{:mvn/version "3.19.0"}`
2025-12-30 10:44:10 -06:00
Chris Truter
b222e32bdf Revert "Add transforms.target_database_id column (#66953)" (#67630) 2025-12-30 16:25:10 +00:00
Jakub Chodorowicz
390e559dc2 Prg 160 add field grouping format and group host and port fields (#64280)
* Add field grouping of host and port

* Add host and port settings to postgres, mysql

* Add host and port grouping to db drivers

* Add database story with host and port group

* Add groupFields unit tests

* Fix typo

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix missing tunnel parameter value

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Refactor and simplify field grouping function

* feat: add nested fields support for db format

* feat: remove id field, adapt new format foy postgres, mongo, mysql, remove leftovers

* feat: support nested fields, add backdrop component

* fix: group inputs loosing focus on type/render

* refactor: simplify custom containers logic

* style: adjust backdrop container style

* refactor: field mappers for db forms

* refactor: move host and port config to the new format

* refactor: cleanup old grouping approach

* refactor: remove unneeded property

* fix: typo in the html prop name

* internal: validate container style comping from BE

this value can be set be external drivers so it's better to validate  it

Signed-off-by: Jakub Chodorowicz <jakub.chodorowicz@metabase.com>

* fix: type errors

* fix: driver translation test

* refator: use existing getFlattenedFields function

* fix: flatten properties for connection property uniquness

* backtrack from ssl grouping for mongo

---------

Signed-off-by: Jakub Chodorowicz <jakub.chodorowicz@metabase.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-30 14:51:28 +01:00
John Swanson
44aa361a2c UXW-2586: Acquire locks before changing data permissions (#67201)
* Acquire locks before changing data permissions

Data permission have a read-modify-write cycle:

- we read the existing permissions to see what's currently set
- then we decide what to do (e.g. delete the existing DB level
  permissions to write a granular table-level permission)
- then we do the write

This has a race condition if multiple Metabase instances are modifying
permissions at the same time.

For example, say we have:

Initial state: `{:db_id 1 :table_id nil :perm_value :unrestricted}`

Instance A: set table 1 to :blocked
Instance B: set database to :blocked

T1: A reads state, sees db-level permission, plans to expand to table-level
T2: B reads state, sees db-level permission, plans to replace it
T3: A deletes db-level, inserts table-level rows for all tables
T4: B deletes db-level (no-op), inserts new db-level :blocked

Result (CORRUPT):
```
{:db_id 1 :table_id 1 :perm_value :blocked}      ;; from A
{:db_id 1 :table_id 2 :perm_value :unrestricted} ;; from A
{:db_id 1 :table_id nil :perm_value :blocked}    ;; from B
```

Both db-level AND table-level permissions now exist.

For the permissions API, we take a cluster lock, but sync operations
bypassed this cluster lock. This PR creates a lower-level cluster lock
per `[database, group, perm-type]` so only one instance/thread can do
the read/decide/write cycle for a particular db/group/perm at a time.

* Add a test for race conditions setting data perms

This took a while before I was able to track down the fact that using
`(mt/with-temp )` caused both threads to share the same connection, so
they could obtain the lock simultaneously 🤦

* Use a slightly coarser lock

I realized that if an instance has a huge number of groups, we'll obtain
a lock and ask Postgres to maintain an active savepoint for each group,
which might be untenable.

I think the best solution here is to use slightly coarser locks. This
might increase contention slightly, since we won't be able to change
permissions for `db 1, group 1, perm type view-data` at the same time
that we change permissions for `db 1, group 2, perm type view-data`. But
I think the tradeoff here is necessary.
2025-12-30 13:08:39 +00:00
Mahatthana (Kelvin) Nomsawadi
cf7026a6a2 Fix empty cards with no results making dashboard longer than expected (#67581)
* Prevent unnecessary height calculation

* Prioritize local layout from `react-grid-layout` for height calculation

* Refix the issue for real

* Add tests
2025-12-30 12:51:29 +00:00
Jakub Chodorowicz
afef9ac2ae fix: hide editing toggle for unsupported engines (#67564)
* fix: hide untested and unsupported db engines in table editing section

* move allowed engines to constants file

* test: add hidden editing toggle test case
2025-12-30 11:50:11 +01:00
Nemanja Glumac
b5f483d951 E2E workflows env vars cleanup (#66592) 2025-12-30 10:56:23 +01:00
Jakub Chodorowicz
7247ffca2d feat: allow setting custom y axis range, even if points are outside of the range (#67533)
* feat: allow setting custom y axis range, even if points are outside of the range

* fix: adjust Waterfall null x value loki screenshot test
2025-12-30 09:15:10 +01:00
github-automation-metabase
8d7ffb6845 Update generated docs (master) (#67618)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-30 00:06:07 -05:00
Egor Grushin
2b97f841bc UXW-2597 fix row bar charts' tooltip (#67617)
* UXW-2597 fix Row Bar tooltip data error
2025-12-30 01:33:34 +00:00
Gabriel Moreno
fe7668963c UXW-69 Avoid persisting non-dashboard settings (#67592)
* fix: avoid persisting settings that are hidden from dashboard UI

* test: add `sanitizeDashcardSettings` unit spec

* refactor: use `_.pick` for sanitizing dashcard settings
2025-12-29 18:52:06 -04:00
bryan
29b1e70d21 fix perf/mapv to handle infinite and large lazy sequences (#66984) 2025-12-29 15:02:00 -07:00
Ryan Laurie
b8113ad526 Get personal collection hook (#66701)
* get personal collection hook

* use the hook

* better tests

* barrell

* Apply suggestions from code review

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

* cmon claude

* review fixes

---------

Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>
2025-12-29 14:42:33 -07:00
metamben
6d1cb34859 Normalize aggregation references, sort maps and remove all uuids (#67521)
* Normalize aggregation references, sort maps and remove all uuids

Fixes QUE-2916
2025-12-29 21:32:10 +00:00
Nemanja Glumac
0c2996b7da Re-introduce: Upload failed e2e test artifacts for quarantined tests (#67600) 2025-12-29 21:10:32 +00:00
Egor Grushin
9daa5119f6 fix: user's input is overwritten by async form reinitializations (#67525) 2025-12-29 18:27:03 +00:00
Anderson
48b6a9d289 Fix pie chart flickering when toggling legend / Convert ChartWithLegend to ts (#67240)
* Fix pie chart flickering on toggling legend / Convert ChartWithLegend to ts

* Convert test to ts

* Resolve flickering when toggling visualization config sidebar

* Fix regression with map chart (only apply svg centralization to pie charts)

* Apply PieChartContainer classname to inner component
2025-12-29 17:40:02 +00:00
Ryan Laurie
037391a1ea our analytics strikes again (#66909) 2025-12-29 10:21:03 -07:00
Eric Normand
c8c18494ac Default to base-type when it differs from effective type (#67486)
* Default to base-type when it differs from effective type

* Make 'er parallel

* Does this clause make it better?

* Remove parallel.

* New test and fix for two literals

* Use y-type for effective type

* Update test to try number
2025-12-29 11:08:13 -06:00
Ryan Laurie
cfcf6c16eb Update frontend dev guide (#67333)
* update frontend dev guide

* add color notes

* ouch
2025-12-29 09:57:01 -07:00
William
050a38bb19 Hopeful fix for the ooms that betterment is running into. (#67482)
* Hopeful fix for the ooms that betterment is running into.

Note that this will only work once macaw is updated and metabase is using the new version of macaw.  Until that
happens, this change is a noop.

* bump macaw for context stripping

https://github.com/metabase/macaw/pull/123

here's the gist:

```clojure
core-test=> (let [base {:select [:a :b :c]
                        :from   [:foo]
                        :where  [:= :foo.a [:inline "baz"]]}]
              (-> {:union-all (for [_ (range 3)]
                                base)}
                  sql/format
                  first
                  (components {:strip-contexts? true})
                  :columns
                  ))
                  ;; replacing #{} with <set> so git doens't comment it out
<set>{{:component {:table "foo", :column "a"}}
  {:component {:table "foo", :column "b"}}
  {:component {:table "foo", :column "c"}}}
core-test=> (let [base {:select [:a :b :c]
                        :from   [:foo]
                        :where  [:= :foo.a [:inline "baz"]]}]
              (-> {:union-all (for [_ (range 3)]
                                base)}
                  sql/format
                  first
                  (components )
                  :columns
                  ))
                  ;; replacing #{} with <set> so git doesn't comment it out
 <set>{{:component {:table "foo", :column "b"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x6343d805 "com.metabase.macaw.AstWalker$ScopeInstance@6343d805"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "a"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x6343d805 "com.metabase.macaw.AstWalker$ScopeInstance@6343d805"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "a"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "a"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x4de719cd "com.metabase.macaw.AstWalker$ScopeInstance@4de719cd"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x76f86e4f "com.metabase.macaw.AstWalker$ScopeInstance@76f86e4f"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x6343d805 "com.metabase.macaw.AstWalker$ScopeInstance@6343d805"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "c"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x6343d805 "com.metabase.macaw.AstWalker$ScopeInstance@6343d805"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "b"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x1241e96a "com.metabase.macaw.AstWalker$ScopeInstance@1241e96a"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x6343d805 "com.metabase.macaw.AstWalker$ScopeInstance@6343d805"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "a"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x542edf1d "com.metabase.macaw.AstWalker$ScopeInstance@542edf1d"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x2e474cfd "com.metabase.macaw.AstWalker$ScopeInstance@2e474cfd"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "b"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "a"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x459ed576 "com.metabase.macaw.AstWalker$ScopeInstance@459ed576"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x38a0b358 "com.metabase.macaw.AstWalker$ScopeInstance@38a0b358"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x1241e96a "com.metabase.macaw.AstWalker$ScopeInstance@1241e96a"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x6343d805 "com.metabase.macaw.AstWalker$ScopeInstance@6343d805"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "c"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "a"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x1241e96a "com.metabase.macaw.AstWalker$ScopeInstance@1241e96a"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x6343d805 "com.metabase.macaw.AstWalker$ScopeInstance@6343d805"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}
  {:component {:table "foo", :column "c"},
   :context
   (#object[com.metabase.macaw.AstWalker$ScopeInstance 0x1241e96a "com.metabase.macaw.AstWalker$ScopeInstance@1241e96a"]
    #object[com.metabase.m
acaw.AstWalker$ScopeInstance 0x6343d805 "com.metabase.macaw.AstWalker$ScopeInstance@6343d805"]
    #object[com.metabase.macaw.AstWalker$ScopeInstance 0x761965fc
    "com.metabase.macaw.AstWalker$ScopeInstance@761965fc"])}}
```

---------

Co-authored-by: dan sutton <dan@dpsutton.com>
2025-12-29 10:27:09 -06:00
github-automation-metabase
0e21ffcaac Update generated docs (master) (#67576)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-29 10:49:30 -05:00
Edward Paget
c36208d52e docs: fix enable tenant string (#67195) 2025-12-29 15:33:34 +00:00
Nemanja Glumac
d4ba2829bd Revert "Upload failed e2e test artifacts for quarantined tests (#67381)" (#67582)
This reverts commit 487036f0b1.
2025-12-29 13:54:36 +01:00
Jakub Chodorowicz
9f6d9f46f3 fix: custom home page settings are not being exported (#67550)
* fix: custom home page settings are not being exported

* fix: update seralization baseline test
2025-12-29 09:47:44 +01:00
bryan
cb7c3a09ac Add hour to redshift test schema prefix for more aggressive cleanup (#67215)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 11:09:20 -07:00
Jakub Chodorowicz
d0327d0b4b docs: improve .env.example docs (#67545)
* docs: improve .env.example docs

* docs: fix numbering and comment out default value env var
2025-12-26 15:55:17 +01:00
dpsutton
42a7260209 bump log4j (#67393)
* bump log4j

* bump snowflake in hope of clearing advisory

https://github.com/metabase/metabase/security/code-scanning/543

> This file introduces a vulnerable io.grpc:grpc-netty-shaded package
> with a high severity vulnerability.

* bump netty shaded

https://github.com/metabase/metabase/security/code-scanning/543

* bump aws s3 for io.netty:netty-codec-http2

https://github.com/metabase/metabase/security/code-scanning/536

before bump:
    . io.netty/netty-codec-http2 4.1.126.Final

after dump:
❯ clj -X:deps tree :extra '{:deps {software.amazon.awssdk/s3 {:mvn/version "2.40.13"}}}' | grep http2
    . io.netty/netty-codec-http2 4.1.130.Final

* bump netty-codec-http

from software.amazon.awssdk/s3

before:
    . io.netty/netty-codec-http 4.1.126.Final

https://github.com/metabase/metabase/security/code-scanning/534

* bump athena to 3.7.0

ran workflow at
https://github.com/metabase/metabase/actions/runs/20439789522/job/58729767910

https://github.com/metabase/metabase/actions/workflows/athena.yml to
publish the 3.7.0 version

* include driver change to force running drivers

* sort deps edn

* attempt to solve l4z issues

weirdness is that this version might move some stuff? we'll see if it
works.

* Revert "attempt to solve l4z issues"

This reverts commit 03d845eeea.
2025-12-26 10:24:04 -03:00
Jeff Bruemmer
df292ad856 note on SQL download perms (#67464) 2025-12-26 10:03:14 -03:00
Nemanja Glumac
81010429ec Delete duplicate e2e repro model metadata (with custom expression) (#67555) 2025-12-26 13:59:33 +01:00
Nemanja Glumac
487036f0b1 Upload failed e2e test artifacts for quarantined tests (#67381) 2025-12-26 12:57:34 +01:00
Mahatthana (Kelvin) Nomsawadi
7a36d9143a Prevent black background loaded with light full-app embedding (#67544)
* Prevent black background loaded with light full-app embedding

* Fix tests
2025-12-26 11:49:00 +00:00
Nemanja Glumac
fb96706972 Reinforce 'rename column' e2e helper (#67539) 2025-12-26 11:45:20 +01:00
Nicolò Pretto
3459c5344d chore(sdk): move setting cypress baseUrl to global beforeEach for sdk tests (#66308) 2025-12-26 11:34:10 +01:00
Mahatthana (Kelvin) Nomsawadi
42c8a22c37 fix(sdk-package, sdk-bundle, embed-js): Don't expose question in SDK's entityTypes (#67534)
* Don't expose `question` in SDK's `entityTypes`

Because it's only applicable to staged picker

* Fix type

* Clarify the use of `question` in SDK's `entityTypes`

* Fix SDK not building
2025-12-26 03:55:27 +00:00
Nemanja Glumac
8ee6859b19 Fix model metadata e2e flake (#67522) 2025-12-25 20:27:29 +01:00
Mahatthana (Kelvin) Nomsawadi
3f4e0678f5 feat(sdk-bundle, embed-js): Remove embedding subscriptions email links (#67511)
* Prevent test email from including Metabase links (#67068)

* Send a new flag from FE if testing subscription from modular embedding

* Pass :disable_links to dashboard subscription email template

* Remove links from dashboard subscription email template

* Remove link from pulse cards

* Remove dangling divider line

* Add test

* Fix tests

* Use the same logic as in the actual subscription tasks

* Prepare to use a new column name from pulse table

* Remove embedding subscriptions email links (#67181)

* Add a column to pulse to save when a subscription is created on embedding

* Save disable_links to "pulse" table

* Fix tests

* Fix more tests

* Update column name

* Add tests

* Make code less confusing after embedding name change

* Fix liquibase boolean type

* Fix tests

* Fix more tests

* Fix formatting

* Fix wrong test names

* Make function comment styles consistent

* Make the test more solid

* Add modular embedding SDK tests

* Don't render the dashboard subscription button when there's no data cards (#67501)
2025-12-25 14:28:28 +00:00
Timofey Kachalov
26f6e2b590 Use actual metadata in a Notebook in Embedding SDK/Embed JS (#67453) 2025-12-25 15:39:26 +04:00
Jakub Chodorowicz
0cc6677886 fix: add filter clauses to support min max required for age binning (#67448) 2025-12-25 09:55:54 +01:00
Ngoc Khuat
f14e1f1444 Support named tables for python transforms (#66934) 2025-12-25 07:52:21 +00:00
Phoomparin Mano
09d69f2cdf docs(sdk): move llms.txt under docs/embedding (#67526) 2025-12-24 22:10:18 +00:00
Denis Berezin
75f3c9fc01 UXW-1852 Reset filter to default for specific click behavior (#67220)
* UXW-1852 Reset filter to default for specific click behavior

* Fix CI

* Fix unit tests

* Review fixes

* Add e2e test
2025-12-24 19:05:19 +03:00
Roman Abdulmanov
101fc34a37 Custom headers (#67502)
* added vars
* added tests
2025-12-24 14:21:49 +00:00
Phoomparin Mano
dd830db392 docs(sdk): add statically generated docs/llms.txt (#67506) 2025-12-24 19:30:26 +07:00
Fraser
286b89bf92 Measure all columns to provide expand option (#67429) 2025-12-24 11:00:21 +00:00
Jakub Chodorowicz
141d49a4c5 fix: respect time format in exclude date picker filter QUE-2611 (#67384)
* fix: respect time format in exlude date picker filter QUE-2611

* rework: move constant out of function body

* test: fix failing tests due to lack of redux provider

* fix: add missing redux  provider in story

* test: improve testing logic for ExcludeDatePicker

* internal: use specialized useSetting hook

* test: adjust looping with async action
2025-12-24 10:44:48 +01:00
Timofey Kachalov
462a62a092 Call overrideRequestsForGuestOrPublicEmbeds for static/public embeddings (#67358) 2025-12-24 13:39:10 +04:00
Oleksandr Solovyov
4c9fe80dc5 Add transforms.target_database_id column (#66953) 2025-12-24 10:21:30 +02:00
Fraser
23eae39c3c Apply field settings to parameter field widget (#67428) 2025-12-24 17:17:52 +13:00
Nemanja Glumac
e4eab0c668 Fix flaky pinned metrics e2e test (#67481)
The root cause of the flakiness was that the save modal sometimes picks the root collection, while at other times it picks the current user's personal collection. The selector was trying to find "Our analytics" in the breadcrumbs, which is why it was failing every time the actual collection is personal collection.

The second issue was that trying to (1) clear and then (2) type the metric name was extremely unreliable.
2025-12-23 23:49:49 +01:00
Egor Grushin
b2bac8e014 QUE-418 fix hidden column check test (#67444) 2025-12-23 22:33:58 +00:00
bryan
b149b004b0 airgap token check user creation fix (#66770)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-23 16:12:46 -06:00
Cam Saul
fdabf871f3 Disable nonworking email and URL extractions for BigQuery and 7 other broken drivers (#66982)
* Add failing test for #63822, DEV-1190

* Add new feature flag

* Update FE config

* Fix tests 🔧

* Disable for 7 more drivers

* Fix MySQL + MariaDB

* Fix TypeScript
2025-12-23 11:37:10 -08:00
github-actions[bot]
b99d3d186d Fix: very low percentages can collide with the y-axis when there are lots of decimals (#67219)
* Fix: very low percentages can collide with the y-axis when there are lots of decimals

Fixes #55853

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add e2e test

* Review fixes

* Update Loki Snapshots

---------

Co-authored-by: Claude Code[bot] <noreply@anthropic.com>
Co-authored-by: Denis Berezin <denis.berezin@metabase.com>
Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-12-23 22:26:35 +03:00
Brad Anderson
d2da731428 Fix #61219: Add ability to include personal collection items in search results for admins (#67396) 2025-12-23 13:22:40 -05:00
Aleksandr Lesnenko
687d28227a Replace table with tree table in Library and Jobs pages (#67060)
* use tree table in library and jobs

* specs

* use width=auto on datetime columns

* padding for auto measured columns
2025-12-23 13:17:16 -05:00
Nicolò Pretto
50e46d56a7 fix: use "All tenant users" group for tenant users in popover and modal (#67446)
* fix: use "All tenant users" group for tenant users in popover and modal

* clean up

* Revert "clean up"

This reverts commit d054ad7d9e.
2025-12-23 17:06:13 +00:00
Timofey Kachalov
7596158b4a Add parameters /search e2e for guest embeds (#67273) 2025-12-23 20:34:37 +04:00
Eric Normand
711a728569 Check that the number was parsed correctly (#67403)
* Check that the number was parsed correctly

* Don't parse int columns that are remapped

* oops, remove old change

* Better fix and specific test

* kick ci

* kick ci

* Make sure it still hits the bigint branch

* Move check into parseNumber()

* Move check back to value.tsx

* Single describe in tests

* Add blank lines (fe-lint)
2025-12-23 16:31:42 +00:00
Nicolò Pretto
c95d1d4883 Tenant Collections -> Shared collections in permissions page (#67452) 2025-12-23 15:58:45 +00:00
Nicolò Pretto
6635453dae hide the column to promote to group manager for tenant groups (#67451) 2025-12-23 15:32:37 +00:00
Nemanja Glumac
73a25b84ef Fix object detail flake #39477 (#67442) 2025-12-23 14:07:01 +01:00
Nemanja Glumac
4bece3e5c1 Remove the "Groups" heading from the invite popover (#67222) 2025-12-23 12:55:56 +01:00
Nicolò Pretto
e37c65d34b update tenants empty state listing copy (#67431)
* update tenants empty state listing

* Update enterprise/frontend/src/metabase-enterprise/tenants/components/TenantsListingEmptyState.tsx
2025-12-23 11:52:38 +00:00
Nemanja Glumac
04dbcf1823 Fix flake #23630 (#67367) 2025-12-23 12:44:01 +01:00
Nemanja Glumac
2c7d8835d8 Consolidate outlines in the main sidebar nav (#67283) 2025-12-23 12:43:18 +01:00
Abed Habli
0972cf4e5b Docs: Metabot inline SQL editing (#67362)
* Docs: inline SQL editing

* Optimized 1 images, saved 35.9 KB (13.6% smaller)

* typos

* Update docs/ai/metabot.md

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

* Update docs/ai/metabot.md

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

* Update docs/ai/metabot.md

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

* small edit

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2025-12-23 10:13:39 +01:00
Gabriel Moreno
6d00178043 UXW-2546 Fix permissions table cell background color & borders (#67331)
* fix: table cell background & border color

* feat: use css variable instead of theme templating
2025-12-23 02:05:12 +00:00
Cam Saul
8ce1d65f8c Fix adding two DIFFERENT implicit joins with the SAME generated alias (#67411)
* Fix adding two DIFFERENT implicit joins with the same generated alias

* Part 2 of #67411 fix
2025-12-23 01:54:24 +00:00
Nick Fitzpatrick
453478f9fb ellipisify table names, fix published table link (#67402) 2025-12-22 21:09:50 -04:00
Nick Fitzpatrick
c857b75646 Uxw 2511 field metadata edit and field detail panels cant be closed (#67034)
* close field panels

* undo scroll behavior changes

* little more cleanup

* use ScrollArea

* e2e and table picker adjustments
2025-12-22 20:55:00 -04:00
Romeo Van Snick
269891d61c Use collection in breadcrumbs for nested questions (#67154)
* Always show collection in header breadcrumbs for cards

* Add repro for metabase#47005

* Fix e2e tests
2025-12-23 11:52:13 +11:00
Fraser
b5083f4afa Hide Data Permissions sections that are irrelevant to oss (#67354) 2025-12-23 12:08:46 +13:00
Brad Anderson
b8117583a8 Fix #64631: Change "Report an issue" -> "Download diagnostics" (#67310)
* UXW-1988 Copy change: "Report an issue" -> "Download diagnostics"

* UXW-1988 Updates tests/documentation
2025-12-22 17:45:58 -05:00
Denis Berezin
cb398d5630 Fix for security alert 541 (#67401) 2025-12-23 00:53:02 +03:00
Nemanja Glumac
4680a440e1 Simplify content moderation e2e tests (#67375) 2025-12-22 22:43:17 +01:00
Cam Saul
1e4e2b3f7b Allow temporal args for - (#67397) 2025-12-22 21:31:05 +00:00
Aleksandr Lesnenko
f42b947b37 resolve mdast-util-to-hast to 13.2.1 (#67389) 2025-12-22 20:17:44 +00:00
github-automation-metabase
1e94db5a93 Update generated docs (master) (#67349)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-22 14:19:22 -05:00
metamben
b2a430f208 Log each entity as it gets dependency-backfilled at debug level (#67378)
Log each entity (card) as its dependencies get backfilled by the job. This is to be able to see if there is a particular entity that's causing the OOM.
2025-12-22 17:42:25 +00:00
Roman Abdulmanov
172aa84fd7 bump versions (#67385) 2025-12-22 12:16:11 -05:00
Sloan Sparger
3d5c36960d [Metabot] Natural language query entry point (#66737)
* prototype

* open chat sidebar on navigate

* update copy for new route

* use nlq profile and make sticky, redirect to empty query builder if no navigate_to is recieved

* responsiveness

* move code to enterprise folder

* imple error states, better loading state

* handle user leaving the page while a response is being loaded

* lint fix, change inline sql shortcut key, disable prompt suggestions and fade out once a prompt has been sent

* fix e2e test

* add test coverage, update copy

* fix failing e2e tests

* attempt to fix e2e flake
2025-12-22 16:59:24 +00:00
Roman Abdulmanov
7038c00b38 bump versions (#67379) 2025-12-22 11:54:04 -05:00
metamben
93e1a7a60b Export published tables when their collection is selected (#67141)
* Export published tables when their collection is selected
2025-12-22 16:48:40 +00:00
Mahatthana (Kelvin) Nomsawadi
4207ad9722 Remove my temp DB file (#67369) 2025-12-22 15:06:02 +00:00
Jeff Bruemmer
6d002819df auth snippets (#67371) 2025-12-22 10:02:10 -05:00
Anderson
52bfdad99d Don't reset map zoom when filter is active and a marker is clicked to view details (#67063)
* Don't reset map zoom when clicking marker with a filter Applied

* Simplify condition to check that we should recalculate zoom

* Fix unit test
2025-12-22 14:54:21 +00:00
Denis Berezin
f601dea72d UXW-2449 fix pasting mixed content containing cardEmbed (#66733)
* UXW-2449 fix pasting mixed content containing cardEmbed

* Fix issue with cardEmbed loading forever

* Fix issues with smartLink and caedEmbed paste to a list

* Fix typecheck
2025-12-22 17:31:08 +03:00
Denis Berezin
cf9868d509 UXW-77 fix missing bar chart labels for 12 months timeseries (#67316)
* UXW-77 fix missing bar chart labels for 12 months timeseries

* Update Loki Snapshots

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-12-22 17:29:50 +03:00
Nemanja Glumac
0ddc4ab309 Fix stress-test snapshot conditions (#67344) 2025-12-22 13:04:10 +01:00
bryan
3b6dbaee4b Remove openapi.json from repo and disable CI check (#67294)
* Remove openapi.json from repo and disable CI check

The committed openapi.json was causing friction:
- Cascade CI failures when master got out of sync
- Merge conflicts on a 36k line generated file
- Phantom local changes when switching branches

The OpenAPI generation still works - run `yarn generate-openapi` when needed.
We're just not committing the artifact for now.

* Check for Node.js 22+ before generating OpenAPI types

The previous check for `yarn` wasn't sufficient - the system may have
yarn installed with an older Node.js version. Now we explicitly check
that Node.js 22+ is available before running the generation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Revert client-side OpenAPI types generation

* Remove types generation from postinstall

* Restore package.json newline

* Restore prepare-backend action

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Stas Gavrylov <stasgavrylov@gmail.com>
Co-authored-by: Stas Gavrylov <stas@metabase.com>
2025-12-22 10:54:18 +02:00
Romeo Van Snick
34996f11d3 Keep filters header visible when details view is open (#67246)
* Do not hide filters when showing object details

* Add repro for metabase#66957
2025-12-22 13:31:52 +11:00
Romeo Van Snick
9f65da5129 Add time in click behaviour for hours and minutes (#67151)
* Allow clicking dates with hour and minutes granularity to set parameter

* Add repro for metabase#58556

* Fix unit tests

* Add repro for metabase#66277

* Allow selecting date ranges with hours and minutes
2025-12-22 13:30:56 +11:00
Romeo Van Snick
5299dd726a Hide view details button in Transform viz (#64752)
* Hide 'View details' button on transform results

* Add repro for metabase#64473

* Fix test

* Use queryBuilderMode rather than adding another prop
2025-12-22 10:28:33 +11:00
Cam Saul
0004f3efc6 Allow arbitrary expressions inside :is-null and :not-null in MBQL 4 schema (#67326)
* Support arbitrary expressions inside `:is-null` and `:not-null`

* Remove unnecessary blank line in schema_test.cljc
2025-12-21 14:30:47 -08:00
Oleksandr Yakushev
a848299a7a Get rid of peridot dependency by embedding necessary functions (#66921) 2025-12-21 22:52:06 +02:00
Cam Saul
7057724abf Allow :aggregation refs inside (aggregation) expressions in MBQL 4 schema (#67311)
* Allow :aggregation refs inside expressions in MBQL 4 schema

* Test + Kondo fix
2025-12-21 20:04:44 +00:00
Noah Moss
337885f0b8 Metabot NLQ collection picker (#67051)
* accept optional profile-id in search tool request and use it to determine collection filtering

* cleanup

* try to fix tests

* fix build

* kondo

* fix toucan syntax

* address comment

* oops, fix build

* remove some more use_case code on the FE that slipped through the revert via messy rebase
2025-12-19 19:14:34 -05:00
Egor Grushin
6d33574064 GDGT-1411 Transform UX updates (#66969)
UX updates that makes transform saving form more clear.
2025-12-19 23:10:56 +00:00
Nathan Voxland
953f266b24 Added spec for library API response (#66623) 2025-12-19 16:53:33 -06:00
Ryan Laurie
808c283577 fix isExternalUser check (#67303) 2025-12-19 22:28:27 +00:00
Cam Saul
0fe28f8d4e MBQL 4 => MBQL 5 conversion should ignore invalid expressions (#67305) 2025-12-19 14:27:59 -08:00
Jeff Bruemmer
426acdbc85 docs - update embedding docs (#66784)
* move appearance

* links

* sample app links

* heading

* update code to copy

* embedding updates

* remove generated file

* fixes

* redirect

* typos

* image

* various clean up

* appearance

* components

* pick an item

* guest embeds and components

* translations

* auth

* sample app

* Apply suggestion from @jeff-bruemmer

* theme json

* links
2025-12-19 17:24:20 -05:00
Gabriel Moreno
c13f91f922 UXW-2333 Add revision history to transforms and documents (#66989)
* feat: implement document revision history

* feat: implement transform revision history

* refactor: fully embrace RTK query

* test: add e2e runthrough for document revisions

* test: add e2e runthrough for transform revisions

* feat: add error boundary for transform revision sidebar

* feat: add loading indicators

* fix: avoid layout shift on documents revision history sidebar

* test: wait for sidebar to open on transform revision history tests

* feat: add missing revision diff string cases

* feat: generate openapi

* fix: code compilation by breaking method in two
2025-12-19 17:43:41 -04:00
Noah Moss
1c415eae09 Refactor metabot error handling (#67290)
* metabot check-response! function for ai service error handling

* Add test, tweak logic
2025-12-19 15:41:26 -05:00
Aleksandr Lesnenko
3e91364955 python library (#67173) 2025-12-19 15:31:31 -05:00
Riley Thompson
a77b0ee1da Set network timeout in connection options (#66861)
* set network timeout in connection options

* add test

* kondo

* fix test

* Add try catch

* use network timeout setting

* use exception chain util

* use cached thread pool, and timeout to call connection.close

* just do setnetworktimeout

* address comments
2025-12-19 20:28:53 +00:00
github-actions[bot]
276d6532d8 Fix: Cannot add filters on boolean MySQL columns when the data source is a model (#67123)
* Fix: Cannot add filters on boolean MySQL columns when the data source is a model

Fixes #65826

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Introduce multimethod

* Improve docstring

* Add db-type-name to changelog

* Make tests work

* improve changelog entry

---------

Co-authored-by: Claude Code[bot] <noreply@anthropic.com>
Co-authored-by: Eric Normand <ericwnormand@gmail.com>
2025-12-19 13:59:39 -06:00
Nathan Voxland
a7425eff43 Fix trend lines when aggregating by datetime (#65873) 2025-12-19 13:47:31 -06:00
Brad Anderson
9e53b9b9aa UXW-115 Disables "Export as PDF" button in dashboard share menu if cards are still loading (#67168) 2025-12-19 14:30:46 -05:00
github-actions[bot]
1c5150508b Fix: Redshift external tables have unknown types for string/enum columns on sync (#67028)
* Fix: Redshift external tables have unknown types for string/enum columns on sync

Fixes #63025

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add more Iceberg types to Redshift external table types

---------

Co-authored-by: Claude Code[bot] <noreply@anthropic.com>
Co-authored-by: Eric Normand <ericwnormand@gmail.com>
2025-12-19 17:54:53 +00:00
John Swanson
c6efa84b64 automatic search index versions (#66898)
- when a spec is registered, store the raw form in an atom. This is so
things like `search.spec/explode-raw-case` can be stored as raw symbols
rather than functions. (Do note that this is technically a bug in a rare
edge case, where the definition of `search.spec/explode-raw-case`
changes and the search index should technically be invalidated - but I
think this is rare and low-impact enough that we can just not care.)

- when we access the current search index version, canonicalize the
stored specs, plus default attributes and attribute types, and sha256
hash the result
2025-12-19 09:08:00 -08:00
Noah Moss
157e484d91 Fix race condition in metabase.util.queue-test/multithreaded-listener-test (#67225) 2025-12-19 11:22:39 -05:00
appleby
de21452107 Use snake_case for MetabotCodeEdit and MetabotCodeEditorBufferContext fields (#67231)
For consistency with other types shared between metabase and ai-service.
2025-12-19 08:04:27 -08:00
bryan
6c8e8aac1d installing merge drivers works with git worktrees (#67199) 2025-12-19 16:03:45 +00:00
Timofey Kachalov
674a804d4c Cleanup docker build caches when building sample apps on CI (#67268) 2025-12-19 19:56:01 +04:00
Nicolò Pretto
232fc1d3ef update collection name in tests to use the new one from the BE (#67280) 2025-12-19 16:16:09 +01:00
John Swanson
d5c3f459ba UXW-2576 show tenant collections in the trash (#67124)
* UXW-2576 show tenant collections in the trash

I also deleted the `audit-namespace-clause` function. It felt like it
didn't do enough to justify its existence - every caller needed to
modify the list of namespaces. Could probably DRY things up a bit still,
but think we should change the approach.

* Check `use-tenants` before returning tenant colls

* s/audit-namespace-clause/namespace-clause helper

`namespace-clause` takes the ns column, ns value, and an optional
argument for whether *this* particular result should include the tenant
collections in the response (since sometimes we want 'em, sometimes we
don't.)

* kondo
2025-12-19 06:58:07 -08:00
Mahatthana (Kelvin) Nomsawadi
e44789763f Fix invalid snowplow schema (#67250)
* Pass the schema validation

* update schema

* Update tests
2025-12-19 14:51:48 +00:00
John Swanson
68fb061106 UXW-2578 - Prevent renaming of tenant collection (#67086)
* Prevent updating tenant specific root collections

* Localize the name of dedicated tenant collections

* rename dedicated tenant collections 'Our Data'

When displayed on the FE for an admin, they can be renamed to something
like "Foobar's tenant collection"

* Internal users see different names

* prevent tenant users to edit their dedicated tenant collection

* Revert "prevent tenant users to edit their dedicated tenant collection"

This reverts commit 08d2d722be.

* Rename `Our Data` to `Our data`

Co-authored-by: Nicolò Pretto <info@npretto.com>

---------

Co-authored-by: Nicolò Pretto <info@npretto.com>
2025-12-19 06:48:44 -08:00
Nicolò Pretto
ee37ce0408 test(tenants): add e2e for what tenant users should see in core app (#67272) 2025-12-19 15:48:02 +01:00
Nicola Mometto
ff6fffded9 disable chunked encoding if using path style access (#67262) 2025-12-19 13:39:22 +00:00
Phoomparin Mano
0df342cd45 Make "All internal users" sentence-cased in permission editor (#67258) 2025-12-19 20:19:10 +07:00
Nicolò Pretto
adcd80bbd0 My Tenant Collection -> Our data in hooks.ts (#67257) 2025-12-19 14:15:10 +01:00
Phoomparin Mano
a01df0e090 Show embedding picker when logged in as a tenant user (#67189) 2025-12-19 19:42:24 +07:00
Sébastien
b2a256c792 SDK loaderComponent now applies to all loaders (#66646)
* SDK loaderComponent now applies to all loaders

* removed getLoaderComponent, render the loader comp as a react comp, pass it an optional label
2025-12-19 13:28:26 +01:00
Stas Gavrylov
3f79bc36e5 Update OpenAPI spec (#67256) 2025-12-19 11:14:17 +01:00
Phoomparin Mano
7068bbe559 Design changes for tenants onboarding flow in embedding setup guide (#67125) 2025-12-19 16:53:33 +07:00
Phoomparin Mano
2dd017d522 Validation for internal group's tenant collection permission should reference all internal users (#67177) 2025-12-19 16:51:14 +07:00
Mahatthana (Kelvin) Nomsawadi
68c0efa9cd Allow customizing filters values for subscriptions on modular embedding (#67249)
* Allow customizing filter values for subscriptions on modular embedding

* Add tests
2025-12-19 09:50:28 +00:00
Nicolò Pretto
88c9b0bf37 prevent tenant users to edit their dedicated tenant collection name (#67180) 2025-12-19 09:24:25 +00:00
Nemanja Glumac
62a8a7b32e Fix opening an info sidebar when native _variables_ sidebar was already opened (#67165) 2025-12-19 10:04:01 +01:00
Sébastien
ae13d817bf Only import the needed plugins in unit tests (#66751)
* Demo of only importing the relevant plugin in unit test

* Optimize enterprise plugin unit tests with targeted setupEnterpriseOnlyPlugin calls

* fixed tests

* fixup

* .

* fixed test

* removed hasEnterprisePlugin

* fixup

* removed remaining hasEnterprisePlugins and unnecessary setupEnterprise fn

* specificPlugins -> enterprisePlugins

* .

* fixed type

* docs
2025-12-19 07:51:47 +01:00
Romeo Van Snick
0719750252 Add effective type to expression when resolving from ref (#67064)
* Add effective type to expression when resolving from ref

* Add repro for QUE-2567

* Fallback to base type when checking effective types

* Avoid shadowing var

* Add tests for effective-type fallback
2025-12-19 16:12:12 +11:00
Romeo Van Snick
1c4435c17e Python test runs on the BE test runner (#64695)
* Always show debugger

* Move test hook to hooks file

* Update python transform endpoint

* Fix useTestPythonTransform hook

* Update UI for transform editor results

* Add e2e test for python runner

* Fix types

* Add missing config key

* Add python tag to test

* Fix copy output -> logs

* Remove unused helper

* Move isPythonTransformSource to top-level utils

* Remove double padding
2025-12-19 16:11:56 +11:00
Cam Saul
c78ccaaaa0 Several MBQL 4 normalization fixes 🔧 (#67203)
* Fix normalization of MBQL 4 `:aggregation-options` with a `nil` options map

* Update tests

* Fix normalization of Template Tag :options

* Allow raw values as expression definitions

* Automatically remove :ident from joins

* Properly handle aggregations expressions that contain `:if` (alias for `:case`)

* Allow `:coalesce`, `:if`, and `:case` as datetime exprs in MBQL 4

* Test & Kondo fixes 🔧
2025-12-18 15:51:57 -08:00
Aleksandr Lesnenko
373cf5db58 edit & archive transforms collections (#67170)
* archive transforms collections

* edit transforms collections

* better types, placement

* fix
2025-12-18 23:22:04 +00:00
Nemanja Glumac
2d523dc16b Convert the "View SQL" to an icon only (#67159) 2025-12-18 23:05:15 +00:00
Riley Thompson
cde52a68ec Fix bigquery timestamp and timezone casting in aggregation (#67089)
* working fix

* clean up

* clean up test

* kondo

* Update modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk/query_processor.clj

Co-authored-by: metamben <103100869+metamben@users.noreply.github.com>

* Update modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk/query_processor.clj

Co-authored-by: metamben <103100869+metamben@users.noreply.github.com>

---------

Co-authored-by: metamben <103100869+metamben@users.noreply.github.com>
2025-12-18 22:42:54 +00:00
Sloan Sparger
f9b914af2b [Metabot] Inline SQL entry point (#66688) 2025-12-18 16:08:10 -06:00
Edward Paget
f4d51537fa feat: add branch picker to data studio (#66970)
* feat: add branch picker to data studio

* fixup! address PR feedback

* fixup! PR feedback about sync visibility
2025-12-18 21:48:56 +00:00
Dennis Schridde
283ecedf6d Fix grammar of billing period for Metabase AI (#67191)
Fixes: 2b76c38e1f
Closes: https://github.com/metabase/metabase/pull/67053#issuecomment-3671353062
2025-12-18 20:54:27 +00:00
Dennis Schridde
cabfed364e Fix check-openapi-specs (#67200)
OpenAPI specs were out-of-date, preventing this check to succeed on PRs
that did not change the API.

References: https://github.com/metabase/metabase/actions/runs/20347428135/job/58463226792?pr=67191#step:6:56
2025-12-18 20:53:50 +00:00
Noah Moss
0a53e9f918 Revert "Metabot use case configuration groundwork (#66673)" (#67106)
This reverts commit dce776c8cc.
2025-12-18 21:43:47 +01:00
Jeff Bruemmer
77da2dcc93 chill on the backticks (#67210) 2025-12-18 20:42:47 +00:00
Eric Normand
4346b7d7c3 Add mbql time schema test (#67182)
* Add test

* Move test to temporal-test

* Openapi json

* Add second time string
2025-12-18 20:03:27 +00:00
Jeff Bruemmer
185957ac8c Remove models and metrics section from settings (#67174)
Removed section on adding models and metrics to Metabot collection.
2025-12-18 13:53:55 -05:00
Eric Normand
d7425d04f8 Don't do implicit joins through sensitive FKs (#67056)
* WIP

* Working test! (it reproduces)

* Fhew! I found it!

* Remove printlns

* Also remove sensitive fks in calculation

* Remove stray marker comment

* Move tests to fields-test

* Exclude :retired too

* Move tests and add one for retired

* Add another retired

* Better tests

* Appease the kondo

* Fix broken test
2025-12-18 12:28:38 -06:00
Nicolò Pretto
a4f94cd784 don't show synced collections icon for tenant users (#67161)
* feat(tenants): tenant users should not see the synced folder icon

* empty commit to retrigger ci
2025-12-18 17:46:49 +00:00
Dennis Schridde
935494dfdb Change Metabase AI price to be based on quantity for whole billing period (#67053)
### Description

We want to communicate per-billing-period quantities with customer, instead of always communicate monthly quantities.  Invoiced totals will stay the same.

### How to verify

Describe the steps to verify that the changes are working as expected.

1. Ensure you have a token with the `offer-metabase-ai-tiered` feature, but without the `metabot-v3` feature.
2. Navigate to `/admin/metabot` and see the quantities as per billing period, and not per month.

### Checklist

- [x] Tests have been added/updated to cover changes in this PR

Fixes: 2b76c38e1f
Closes: https://metaboat.slack.com/archives/C07RMUQ0GE5/p1765907134400039
2025-12-18 18:30:45 +01:00
Mahatthana (Kelvin) Nomsawadi
ebb85d6b27 Modular embedding subscription analytics (#66932)
* Update default value locations in comments

* Update snowplow schema for modular embedding analytics

* Add more type safety

* fix 'dashboard.drills' and 'question.drills' default values for guest embeds

* Fix auth type

* Test guest embed authentication

* Log `with-subscriptions`

* Strengthen the type
2025-12-18 17:08:01 +00:00
Riley Thompson
788d7c91e2 fix p1 label, add p0 label, escape title (#67171) 2025-12-18 12:03:42 -05:00
Sloan Sparger
7615ef0b9b [Metabot] Multi-convo support (#66864) 2025-12-18 11:02:34 -06:00
Nathan Voxland
0c01ed9259 Don't allow attachments if the creator doesn't have permission to download (#66827)
* Don't allow attachments if the creator doesn't have permission to download

* Fixed failing test

* Fixed failing test

* Fixed frontend issues

* Fixed frontend issues

* Updated BE code

* Fix unit tests

---------

Co-authored-by: Denis Berezin <denis.berezin@metabase.com>
2025-12-18 08:44:55 -08:00
Ryan Laurie
1ad2a572ac fix dashboard question picker collection icons (#67139) 2025-12-18 09:38:02 -07:00
Edward Paget
43217e9350 feat: collection selector for remote-sync (#66977)
* fix: dirty state tracking of bulk set collections

* feat: collection selector for remote-sync

* Update enterprise/frontend/src/metabase-enterprise/remote_sync/components/CollectionSyncList/CollectionSyncList.tsx

Co-authored-by: Anderson <ands.alves.nunes@gmail.com>

* fixup! remove extraneous errormsg property

---------

Co-authored-by: Anderson <ands.alves.nunes@gmail.com>
2025-12-18 15:53:48 +00:00
Sébastien
6f710a3b4f Fix props wrongly marked as interactive-only (#67008)
* fix props wrongly marked as interactive-only

* also remove interactive from withDownloads
2025-12-18 16:45:09 +01:00
Nicolò Pretto
76bf2624eb flatten collection list for tenant users (#67072)
* Hide external collections sidebar for internal users without tenant collection accesses (#67033)

* show the add button if user can write to root

* update unit tests for shared collections nav

* simplify test mocks

* getIsTenantUser selector

* flatten navbar for tenant users

* move up state and use plugin, keep "Collections" name when the external
collection section is not shown

* polish

* throw new error

* fix unit test

---------

Co-authored-by: Phoomparin Mano <poom@metabase.com>
2025-12-18 15:29:47 +00:00
Jakub Chodorowicz
30616565b4 OpenAPI -> TypeScript schema generation (#65144)
* add openapi-typescript schema generation

* chore: add live type generation

* Temp fix for self ref schema

* nemanja wants avaible locales schema

* generate openapi.json file on dev or when updating the apis

* now it e2e. you update an api schema => generate openapi.json => hook to update d.ts

* add hey api

* update user profiles

* proper types now

* fix: remove leftover folders and adjust imports

* chore: Claude guide to generate MALI schemas

* feature: add schema for users API

* wip add user type to profile

* remove the ref of the old lib. all hey-api now

* WIP

* Update FE unit mock

* fetch openapi.json from file system instead of the api

* Add in-browser overlay with errors

* disable error overlay

* feat: script to generate openapi spec

* experiments

* do not clean cwd

* Enable pretty-printing for OpenAPI json

* Add OpenAPI spec keys sorting

* Move generated openapi.json to resources/openapi

* Commit generated typings with sorted keys. Add types.get.ts to eslintignore because it has incorrectly linted typing

* wip

* Fix nullable types

* test fixes

* revert hack for self ref schemas as the new lib cna generate it

* Move TS generated types to gitignore. Cleanup.

* revert uncessary schema changes and also fix indentation

* Add types generation to TS CI job

* Update CI to generate and cache TS types

* Fix CI types generation

* Cleanup FE

* reorganized the modules and remove the requiring-resolve

* Fix unit test

* fix: wrong function call to regenerate api spec

* chore: upgrade hey-api (fixes self referencing hey_api type)

* feat: disable type generation for MetabaseLegacyMbqlSchema

* chore: regenerate openapi definition

* chore: regenerate  openapi.json

* feat: add generate-openapi-spec command

* build: use generate-openapi-spec in yarn scripts

* build: add script that verifies the that openapi spec is uptodate

* build: add CI check for openapi schema being uptodate

* build: fix wrong filename of api check script

* internal: use yarn script for schema generation

* internal: generate version in the api schema generation step

* internal: install node 22 in the api generation job

* internal: fix hey api running twice on build hot

* internal: debounce ts api types generation

* bring back debounce logic

* revert changes in users schema

* internal: add malli docs instructions in skills format

* internal: add details to defendpoint+malli skill

* Fix incorrect types:watch initialization in build-hot script

* Remove version field from generated OpenAPI JSON to allow proper versions comparison on CI

* Update OpenAPI JSON schema

* a nice solution for the dynamic timezone enum

* update openapi json

* test fixes

* update openapi json with latest apis

* resolve tips when this happens again

* fix kondo test and revert the locale type in properties api

* update spec to remove locales

* Revert enum usage on UI

* build: types as part of postinstall

* types: replace hardcoded log type values

* build: format types with prettier - compatible with embedding type transforms

* Update OpenAPI schema

* Update OpenAPI schema

* Revert types cache generation

* Address PR comments

* Reset spec format

* Reset spec again

* Merge master and update OpenAPI spec

* Update package.json

Co-authored-by: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>

* feedback

* resolve comments

* Update OpenAPI spec

* Update OpenAPI spec

* Update OpenAPI spec

* Update OpenAPI spec

* follow derive conventions

* Remove deprecated rspack type check deps

* Add eslint rule to restrict imports from metabase-types/openapi

* Update OpenAPI schema

---------

Co-authored-by: Nicolo-Maria <nicolo.mezzopera@metabase.com>
Co-authored-by: Ngoc Khuat <qn.khuat@gmail.com>
Co-authored-by: Nemanja <31325167+nemanjaglumac@users.noreply.github.com>
Co-authored-by: Stas Gavrylov <stasgavrylov@gmail.com>
Co-authored-by: Uladzimir Havenchyk <uladzimir@metabase.com>
Co-authored-by: Oleksandr Solovyov <o@solovyov.net>
Co-authored-by: Stas Gavrylov <stas@metabase.com>
Co-authored-by: Bryan Maass <bryan.maass@gmail.com>
2025-12-18 17:13:32 +02:00
Edward Paget
b2ec3abf62 fix: savingModel prop only "collection" matters (#66906)
The savingModel prop allow "collections" to be written to the
shared-tenant-collection namespace root while other model types are disallowed.

Fixes how this prop is calculated because the original implementation
left off other types of cards. This prop is now just "collection" | null
since collection is the only model type that matters here.
2025-12-18 09:13:27 -06:00
Timofey Kachalov
f6cf387c02 Fix Question parameters remapping, add more e2e (#66878) 2025-12-18 18:56:02 +04:00
Benoit Vinay
4adf66e56c Improvements to pro-self-hosted to cloud migration flow (#66806)
* Change url from checkout to login

* Use store login url when pro-self-hosted plan

* Unit test WIP

* source_plan query param added

* Cleanups

* Move useGetStoreUrl to hooks file

* Unit tests added

* Misc

* Misc

* Remove hooks

* Removed login path page

* Param renamed to `migration-source-plan`

* Unit tests updated
2025-12-18 14:58:01 +01:00
Mahatthana (Kelvin) Nomsawadi
e60c7f127d Update master after 58 beta. We won't need this next beta. (#67000) 2025-12-18 12:34:49 +00:00
Nemanja Glumac
03764dcb92 Stop preserving the sql/native preview panel open/closed state (#67138)
This pull request removes the user setting that persisted the open/closed state of the native query preview sidebar in the notebook editor. The sidebar's visibility is now managed entirely in the UI state (not persisted per user), simplifying the logic for showing or hiding the sidebar and cleaning up related code and tests.

1. opening a notebook editor will *always* start from a closed native preview sidebar
2. state is now managed exclusively by Redux (sidebar state might be preserved until the page reload, but it is not persisted on the backend)
3. We're changing a previous behavior where, if a native preview sidebar was open and we're resizing the window to something small, the sidebar was automatically closed. This PR changes that behavior. i.e. There is no special resize handling anymore. Whatever the (Redux) state of the sidebar is, it will stay like that no matter the window size.
2025-12-18 12:09:01 +00:00
bryan
4b01fe116a Fix sample app e2e tests silently failing when containers don't start (#67127)
The catch block in startContainers was swallowing errors - it would
log and tear down containers but never re-throw. This meant when
health checks failed, the script would print "All done!" and exit 0,
then Cypress would run and fail with a confusing "could not verify
server is running" error.

Now we re-throw after cleanup so the actual failure is surfaced.
2025-12-18 12:01:29 +01:00
Sébastien
e31368df3e Fixes a flaky e2e test for guest embedding (#66954)
* .

* .

* .

* .

* .

* trying without one timeout

* trying without another timeout

* trying without another other timeout

* trying without yet another timeout

* .
2025-12-18 11:33:32 +01:00
Nicolò Pretto
1aa2160ad6 docs(tenants): update "tenant" to "@tenant" (#67069) 2025-12-18 09:32:28 +01:00
Aleksandr Lesnenko
2185185701 Transforms collection tree (#66893)
Co-authored-by: Nathan Voxland <nathan@metabase.com>
2025-12-18 05:26:37 +00:00
Romeo Van Snick
2a6741df9c Do not pick unsupported databases automatically in transforms (#64406)
* Do not allow picking unsupported databases in Python data picker

* Do not auto-select disabled items

* Add e2e test for empty data selector

* Simplify ugly if condition

* Fix e2e test

* Do not open datapicker wen going to next step
2025-12-18 15:09:24 +11:00
github-actions[bot]
6f83c4e8a1 Update E2E test timings with averaged data (#66916) 2025-12-18 12:54:12 +13:00
Denis Berezin
32eb9a53ce UXW-2444 support opening Document cards in a new tab (#67057)
* UXW-2444 support opening Document cards in a new tab

* Add e2e tests
2025-12-18 01:13:25 +03:00
John Swanson
1c8d56b2cd UXW-186: Mark Mongo connection URI as a "password" (#65178)
Since it contains a password, it should be treated as one. This way it
will be redacted in the UI and API.
2025-12-17 13:54:33 -08:00
Nick Fitzpatrick
ab0418fd09 Scalar - column might be undefined (#67099) 2025-12-17 17:22:17 -04:00
Nemanja Glumac
4d85779e0f Fix github.ref_name references in backend workflows (#66257)
Co-authored-by: bryan <bryan.maass@gmail.com>
2025-12-17 21:11:26 +00:00
Nick Fitzpatrick
4ba6b26bae Uxw 2512 standardize background headings and margins on all pages (#66908)
* broad strokes

* clean up snippets and metrics pages

* tons of PR feedback

* Hi Dan

* test adjustments

* more adjustments

* fix card issue

* removing text on runs list page

* fixing glossary tests

* PR Feedback

* remove header prop

* page spacing adjustmnets

* Center Viz Empty State, fix python library page

* fix python transform page

* scrolling behavior on Job and Transform list pages

* last bits of shame
2025-12-17 20:42:54 +00:00
Edward Paget
d8f84e991e feat: add dev tool to explain analyze queries (#67059) 2025-12-17 14:10:42 -06:00
Phoomparin Mano
650c2c232d Use sentence case for people tab pages in admin settings (#67048) 2025-12-17 19:53:09 +00:00
Case Nelson
0747444277 fix: druid breakout and agg names must be unique (#59483)
* fix: druid breakout and agg names must be unique

Fixes #10670

* Fix CI

* cljfmt

* format

* format rows

* make it work with druid jdbc

* address comments

* use seq over some?

---------

Co-authored-by: Riley Thompson <riley@metabase.com>
Co-authored-by: Riley Thompson <rileythompson99@gmail.com>
2025-12-17 19:48:03 +00:00
Riley Thompson
e6575a5086 Use mongo field filter alias if available (#67025)
* use mongo field alias if available

* Address comments
2025-12-17 19:45:26 +00:00
Phoomparin Mano
c7029242e9 Move the attribute widget description under the accordion header (#67019) 2025-12-17 19:04:06 +00:00
Phoomparin Mano
29a82f017e Hide authority level picker in new shared collection modal (#67041) 2025-12-18 01:28:08 +07:00
Nemanja Glumac
474e198b9b Reduce the "Attributes" font size in a user form (#67096) 2025-12-17 19:25:43 +01:00
Phoomparin Mano
c5117a19b2 feat(sdk): resolve tenant collection in collection browser (#67050) 2025-12-18 01:23:19 +07:00
Edward Paget
d2212003ef fix: improve search performance with tables (#67055) 2025-12-17 12:04:01 -06:00
Timofey Kachalov
49e37e2e9c Wait for recent dashboards being loaded before we load a resource in Embed JS wizard (#67013) 2025-12-17 21:46:42 +04:00
bryan
c6d105ebd9 fixes yaml-merge-driver migrations during rebase (#66904) 2025-12-17 10:18:06 -07:00
Brad Anderson
7640c6ff02 Improves type-checking with color function, removes unnecessary .includes() calls. Adds maybeColor for the few places where it'd be needed. (#67030) 2025-12-17 11:30:40 -05:00
Brad Anderson
ecf50a755b UXW-2451 Fix opposite light/dark mode colors leaking when table is present (#67017)
* WIP UXW-2451 Fixes issue where changing light/dark mode messes up color variables by removing nested providers in useBodyCellMeasure which probably breaks other things

* Update Loki Snapshots

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-12-17 11:29:53 -05:00
Braden Shepherdson
7d84882a3a [o11y] Log + metrics for lib.convert/clean making material changes (#67094)
This generally indicates an MBQL 4 -> 5 conversion issue, and we need
the signal in the 57 rollout.

Also improves the detail of the logging for when `:dataset_query {}`.
2025-12-17 11:14:22 -05:00
Edward Paget
9a96a65abf fix: dirty state tracking of bulk set collections (#67020) 2025-12-17 09:04:47 -06:00
Alex Yarosh
92f7d79f1a docs - australia (#67039)
* Add Australia (Sydney) to available regions

Added Australia (Sydney) to the list of regions.

* Add Asia Pacific (Sydney) IP addresses to whitelist

Added IP addresses for the Asia Pacific (Sydney) region.

* Reorder South America IP addresses section

* Update cloud region list in change-region.md

Removed duplicate entry for Australia (Sydney) and updated Asia Pacific region.
2025-12-17 10:02:47 -05:00
Nicolò Pretto
55fb97170c refactor: create CollectionListView component that is used both by UserCollectionList and TenantCollectionList (#66937)
* refactor: create CollectionListView component that is used both by
UserCollectionList and TenantCollectionList

* address  PR feedback

* use IconName
2025-12-17 15:14:48 +01:00
Timofey Kachalov
b87cab77ed Fix embedding types casing (#67071) 2025-12-17 17:15:12 +04:00
Timofey Kachalov
43ece9bc5d Adjust text of Static Embedding Alert (#67037) 2025-12-17 13:39:52 +04:00
Edward Paget
9fa1bdfc2f fix: card serdes/descendants misses metrics (#67029) 2025-12-16 20:52:26 -06:00
Fraser
fdf1b06786 Use named exports for entities (#66997) 2025-12-17 02:26:38 +00:00
Brad Anderson
cc29923e52 UXW-2481 Add a button in the Library to publish a table (#66947) 2025-12-16 17:30:10 -05:00
Noah Moss
740d3cac62 add a precondition to segment dependency migration in case it was already run on 57 (#67052) 2025-12-16 17:23:32 -05:00
Gabriel Moreno
a54f99d8b0 UXW-2335 De-emphasis + organize models from the data reference side bar (#66531)
* feat: implement tree-based model browsing grouped by collection

* refactor: better extract grouping logic & rename tree node component

* feat: implement new tree structure for schemas navigator

* refactor: unify `DatabaseTablesPane` and `DatabaseSchemasPane`

* fix: reproductions e2e test

* fix: native e2e tests

* feat: update database icon

* refactor: extract render functions into small separate components

* refactor: grouping functions & fix import

* refactor: remove loaders & bring in RTK queries

* test: extend database pane test suites

test: extend database pane test suites

* fix: identifier extraction

* fix: database name

* fix: tests

* feat: update schema icons, see which tests break

* fix: update potential broken tests to search for correct schema icon

* test: add an additional wait on (seemingly) flaky test
2025-12-16 16:15:43 -04:00
bryan
e273cd3135 update test to match exact string (#67043) 2025-12-16 20:03:15 +00:00
Denis Berezin
e016d21ede UXW-2562 Fix document printing (#66972) 2025-12-16 22:58:24 +03:00
Denis Berezin
5f62734470 UXW-2425 Add event timeline label (#66976)
* UXW-2425 Add event timeline label

* fix: typecheck
2025-12-16 22:57:32 +03:00
Nathan Voxland
d564461410 Manage Table Metadata permission is enough to sync table schema (#65866) 2025-12-16 13:52:25 -06:00
github-automation-metabase
6fcd8c914b Update generated docs (master) (#66992)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-16 14:17:12 -05:00
Cam Saul
90d4c2a753 Fix bad normalization for the :text function in MBQL 4 (#67031) 2025-12-16 19:05:10 +00:00
Nick Fitzpatrick
61146a7e98 Data Model UX (#66847)
* Filter Popover close on click outside

* scroll on mount for field and preview panels, tests

* ci bandaid

* UXW-2510 Fix background color mismatch in table metadata panels

* PR Feedback

* shameful fix

---------

Co-authored-by: Brad Anderson <brad@metabase.com>
2025-12-16 12:02:33 -04:00
Nemanja Glumac
771d131f61 Update version-helpers for v58 (#67010) 2025-12-16 16:56:27 +01:00
John Swanson
11c56c57fe Fix check for card changes (#64374)
* Fix check for card changes

The query coming from the FE looks like:

```
{:aggregation [["count"]],
 :breakout [["field"
             42
             {:base-type "type/DateTime",
             :temporal-unit "month"}]],
 :source-table 7}
```

(note strings like `"count"` and `"month"` and, most importantly, `"type/DateTime"`.)

The card from the DB looked like:

```
{:aggregation [[:count]],
 :breakout [[:field
             42
             {:base-type :type/DateTime,
              :temporal-unit :month}]],
 :source-table 7}
```

When we compare the query to the old version to see if it's changed (and
thus, we should invalidate the verified status) we walk it first,
converting all keywords to strings:

```
  (let [prepare              (fn prepare [card] (walk/prewalk (fn [x] (if (keyword? x)
                                                                        (name x)
                                                                        x))
```

... but this is not the correct way to do this conversion, because
`:type/DateTime` becomes `"DateTime"`. We need to include the namespace
if it's present.

* Compare normalized queries

* Modify `changed?` to only compare updated keys

In the end we're doing a `t2/update!` with the updates passed in. If a
key isn't in the updates, it's not going to be updated.

Simplify `changed?` to just take two arguments, `before` and `after`,
and compare the keys in `after` (after doing the necessary
normalization).

If a key is in `after` but *not* before we can't compare it and should
throw an exception. For example, if we passed a card like
`(t2/select-one [:model/Card :id :name])`, we should throw.

* More sane way to check if a card has changed

Instead of ad-hoc updating keys, use the toucan transforms to just
canonicalize all the values before we compare.

* kondo
2025-12-16 15:55:41 +00:00
github-actions[bot]
28460b6d6c Update translations 2025-12-16 (#67009)
* Update translation sources 2025-12-16

* Update translations

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-12-16 15:03:07 +00:00
Timofey Kachalov
65316d089d Output container logs for Sample App CI (#67003) 2025-12-16 18:08:34 +04:00
Brad Anderson
b34216286f UXW-2368 Fixes Alert's warning background color (#66964) 2025-12-16 09:05:39 -05:00
Nick Fitzpatrick
ac5496288e update logic to only show empty library when a searching (#66866) 2025-12-16 10:00:20 -04:00
Timofey Kachalov
4bdc380aef Update jsonwebtoken dependency (#67006) 2025-12-16 17:35:42 +04:00
John Swanson
e6f7260321 Add cluster lock around data permissions updates (#66960)
We currently have the "revision number", but:

- the intent there is slightly different; we want to prohibit one user
from making changes to the permissions graph before they *see* changes
another user might have made concurrently, not just sequence the
concurrent changes, and

- we allow API users to pass the `force` parameter to skip the revision
check entirely

Note that the reason we have `force` available is to allow people to
change permissions without first making a request to *GET* the
permissions graph (which can in some cases be extremely large). It is
not intended to allow concurrent updates to permissions.
2025-12-16 05:02:08 -08:00
Nemanja Glumac
5d8fa4ad64 Run only the default snapshot for pre-release (#67007)
https://github.com/metabase/metabase/actions/runs/20267445215/job/58194458921 failed because snapshots were running for QA databases, and we don't have those Docker containers up for this job.

Since we don't need them, I have adjusted the snapshot step to only run the default snapshots. There's a comment what to do if we change our mind and want to run external database checks in the future.
2025-12-16 13:30:44 +01:00
Timofey Kachalov
2716118f1b Update Embedding-related dependencies (#67001) 2025-12-16 15:38:07 +04:00
Nemanja Glumac
13b47d4452 Install clojure for pre-release (#66988) 2025-12-16 02:36:35 +00:00
Ryan Laurie
b83f897a89 prettier is not a dev dependency (#66949) 2025-12-16 00:23:29 +00:00
Timothy S. Dean
1aaee4e32c Don't offer drill-throughs when top-level column doesn't exist (#66907)
The summary: we are offering drill-throughs on custom columns defined after aggregation, but those custom columns don't exist in the base query. The error presented in such a way that `lib.underlying/top-level-column` for a dimension was returning `nil`, and we were happily putting that `nil` into the query we constructed.

I created a utility to filter dimensions by whether or not the top-level-column can be resolved, and used this for the underlying-records drill-through (from the original issue) as well as the pivot drill-through (which behaved similarly). If no dimensions have a top-level column, the drill-through is not available. If some do, we offer the partial drill-through.
2025-12-15 16:24:26 -07:00
bryan
aa9b07e600 Fix mage doctor to work without mise and add tests (#66896) 2025-12-15 16:17:54 -07:00
Eric Normand
79106a218c Skip fields with inactive table. (#66967)
* Skip fields with inactive table.

* Remove redundant let

* Better fix.
2025-12-15 17:08:53 -06:00
Timothy S. Dean
bd89348a11 metadata.cljs: always prefer lib/source over source (#66858)
`source` is a legacy key on the frontend that gets translated to `lib/source`. Some maps are using both `source` and `lib/source`, and the translation layer translates keys and values in completely separate steps. When the time comes to translate the legacy value of `source` into a valid value for `lib/source`, the code can't tell what the key was originally named. So already-valid values were going through the translation process, producing invalid values (e.g., `:source/source/aggregations`).

This adds a step to object parsing to detect that both keys are present; when they are, it sets an option to simply skip `source` during the parsing; secondly, it adds a step in the value parsing to check whether the value is already a keyword namespaced by `source/`.
2025-12-15 15:32:44 -07:00
Ryan Laurie
35a7e08bfe remove orphan package.json (#66974) 2025-12-15 15:14:02 -07:00
John Swanson
37b9e0eb8a Include email in forgot password links (#64724)
Theoretically the BE could provide the email if you send in an expired
token, but it seems slightly less controversial to just provide a link
like `/auth/reset_password/the-very-long-token?email=some%40email.com`.

This way having the expired token itself can't reveal any information,
but if you click on an expired link, then it's just 2 clicks to send
yourself a fresh token instead of click -> type email -> click.

Fixes [UXW-658: New user invites expire quickly, adds friction to new user experience](https://linear.app/metabase/issue/UXW-658/new-user-invites-expire-quickly-adds-friction-to-new-user-experience)
2025-12-15 21:56:09 +00:00
Cam Saul
26e5de8e0f Normalize invalid :widget-types correctly (#66965) 2025-12-15 13:38:00 -08:00
Riley Thompson
7ee2668a24 Fix mongo native preview of queries with variables (#66959)
* decode strings before formatting

* require lib.metadata
2025-12-15 16:24:11 -05:00
Denis Berezin
6aac5296de Fix 2 flaky tests (#66839)
* Fix flaky test

* Fix flaky test

* Fix broken pipeline

* Fix flake remote sync test

* Review fixes
2025-12-16 00:21:29 +03:00
John Swanson
c756f9a9b0 collection-id only works with shallow=true (#64476)
Document that we only use `collection-id` when `shallow=true`.
2025-12-15 21:18:56 +00:00
Cam Saul
8f5c1adc27 Eliminate enterprise/sso dep on channel (#66854)
* Eliminate `enterprise/sso` dep on `channel`

* Fix missing require
2025-12-15 12:38:07 -08:00
Edward Paget
12886aeb94 fix: api regexes for all routes without them (#66163)
* fix: api regexes for all routes without them

* fixup! regex can't have ^ or $ in api matches

* fixup! embedding issues

* fixup! nano-id enforce
2025-12-15 13:49:59 -06:00
Edward Paget
672f62f9ee fix: better conversions of v57 remote-sync files (#66894)
* fix: better conversions of v57 remote-sync files

* Fix test for remote synced parent

* fixup! kondo

* fixup! merge brainfart
2025-12-15 19:25:16 +00:00
Braden Shepherdson
f248bb4669 [perf] Fix a sneaky infinite loop in a prod-only error case (#66955)
`util.perf/mapv` checks the `count` of all its collection args, so it's
not safe to call with an infinite `seq`.

`lib.metadata.result-metadata/merge-cols` was doing exactly that in the
case where there was a mismatch between the column counts from lib and
driver. It was passing `(concat short-list (repeat nil))` to `mapv` and
causing an infinite loop!
2025-12-15 19:13:16 +00:00
Alexander Polyankin
00c6163ca5 Remove moderation reviews from graph filters (#66952) 2025-12-15 18:35:45 +00:00
Gabriel Moreno
8d7c058ec0 Restore theme preference after login (#66892)
* fix: restore theme preference after login

* test: add theme restoring e2e sequence

* test: perform manual sign-in for better reproduction

* docs: explain new `useEffect` call on `ColorSchemeProvider.tsx`

* fix: experimentally replace colorscheme change listening method
2025-12-15 13:55:40 -04:00
John Swanson
b7c18ff30d Correctly handle non-string @tenants in JWTs (#66944)
* Correctly handle non-string `@tenants` in JWTs

Previously we threw exceptions if we received an invalid non-string
`@tenant`, like `123` or `false` or `{:foo "bar"}`.

Now we:

- convert integers to strings,

- take strings as-is, and

- throw a meaningful exception for anything else
2025-12-15 16:59:19 +00:00
Riley Thompson
1a4bddf25e Pagerduty for querying on-call (#66776)
* test issue workflow

* set up pager duty notifications for querying on call
2025-12-15 11:55:49 -05:00
metamben
7314318fa8 Move the check for published tables into :model/Database's can-read? (#66674)
This is a refactoring, it should not change the overall behavior.
2025-12-15 19:54:34 +03:00
bryan
d6149a57c4 uninstall the custom migration yaml merge driver (#66910) 2025-12-15 09:54:14 -07:00
github-automation-metabase
987a8ab107 Update generated docs (master) (#66923)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-15 11:47:24 -05:00
Braden Shepherdson
bd40119508 [o11y] Add a new metric to count unique cards with blank queries (#66903)
`:dataset_query {}` should not happen, and indicates a bug in the
MBQL 4 normalization. On reading any card, if its `:dataset_query`
is `{}`, add the ID to an in-memory set and update a Prometheus
metric.
2025-12-15 16:12:07 +00:00
dpsutton
4e38125789 Revert "Quick ci test disabling (#63030)" (#66912)
This reverts commit 9191713854.

used to do this in-house but now we use trunk for this. Old way has
ultimate flexibility. But trunk has some really nice workflows built
in (reporting, creating issues in linear, etc).
2025-12-15 10:09:03 -06:00
Sébastien
0a213ebaa7 Trying to fix the infamous app palette loki flaky (#66935)
* Trying to fix the infamous app palette loki flaky

* .
2025-12-15 15:29:35 +01:00
Egor Grushin
720b73a476 Fix lint-staged token-scan for files with special characters (#66911)
* Fix lint-staged token-scan for files with special characters
2025-12-15 14:08:36 +00:00
Timofey Kachalov
9e62f8c2b7 Additional changes for Embedding names (#66899) 2025-12-13 08:06:31 +04:00
Alex Yarosh
3e071e464c docs: embedding renames (#66869)
* rename to full app and modular embedding

* Update docs/embedding/sdk/quickstart-with-sample-app.md

* Update docs/embedding/full-app-ui-components.md

* Apply suggestions from code review

---------

Co-authored-by: Jeff Bruemmer <jeffbruemmer@gmail.com>
2025-12-12 23:42:27 +00:00
Noah Moss
dce776c8cc Metabot use case configuration groundwork (#66673)
* Add DB infra for metabot use cases

* add enabled? use case setting and hook it up end to end for transforms

* remove transforms use case toggle

* add back migrations, number of tests

* add more missing migrations; lint

* some simplification

* fix some tests

* pull use-case out of tool call request header & fix last test

* more test fixes

* add back commits, move use_case->profile mapping to the appdb

* clean ns

* bump ci

* just store use case names in metabot_message instead of fks

* update test

* serialization fix; refactor

* lint

* restore migrations, address code review

* add back migrations again
2025-12-12 18:09:10 -05:00
Maz Ameli
7ddc7cae7d Update our Table icon (#66900)
* change table icon

* remove the redundant table_spaced icon

* use folder instead of table for Questions tab in entitypicker

* Update Loki Snapshots

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-12-12 22:44:49 +00:00
Timofey Kachalov
e52c6c5717 Show EmptyState with publish button on the GetCode step when an entity is not published (#66789) 2025-12-13 01:10:47 +04:00
Denis Berezin
313f25f84f UXW-2484 fix chart tooltip color (#66855) 2025-12-12 23:54:19 +03:00
Edward Paget
6840c68feb fix: restore deleted migration (#66897) 2025-12-12 20:46:59 +00:00
Edward Paget
cee9d99700 Tenants, External Users, and tenant based JWT with Audit Events (#66661)
* Tenants, External Users, and tenant based JWT with Audit Events

Allow the creation of tenant users

While working on this, I realized that my approach to the "All External
Users" group and renaming the "All Users" group was untenable.

I had been planning to just update these things in the database (create
AEU, rename AU to AIU) in the setter function for the `:use-tenants`
setting. The issue here is caching: we don't want to need to actually
reach out to the database every time we need to fetch the All Users or
All External Users, but it would also be quite unfortunate if one
Metabase instance in a cluster had an outdated view of, e.g. the ID of
"All External Users".

(Although - I'm not really sure how much we use the *name* of "All
Users" when we fetch `(all-users)`, so that might be worth a look.)

For now, I've modified things to just update things dynamically in the
`GET /api/permissions/group` and `GET /api/permissions/group/:id`
endpoints: we show/hide the "All External Users" group, and rename the
"All Users" group, based on whether Tenants are enabled.

Allow the creation of tenants

Listing tenants / tenant members will be a followup PR

lint

doh missing require

fix tests

add a test for enabling tenants changing groups

fix tests, slight change to tenant creation API

kick ci

fix another test

give minimum permissions to ext groups

fix more tests

impl user stategy setting ui

more API endpoints

add more tests, fix a very silly migration

slug validation

fix mariadb/mysql

lint migrations file

kondo

fix test

replace tenant members API with `/user?tenant_id=`

also realized that the `/user/recipients` endpoint needed to be modified
for tenants: tenant users should not see recipients that are not part of
the same tenant. (reminder for later: we will need to add safeguards
around actually creating those pulses, not just assume the API won't
send bad recipients!!)

IF you are an admin, `/api/user` respects a `tenant_id` query param and returns:

- "normal" (non-tenant) users if it's `nil`

- specific-tenant users if not

If you are *not* an admin, `/api/user` ignores the `tenant_id` passed
and only returns users in the same tenant.

`/api/user/recipients` will:

- return ALL users if you are a superuser (both tenant and non-tenant)

- return only users in the SAME tenant as you if not

doh

tenant crud wip

integrate endpoints, fix type errors

Allow getting all external users

previously you could do only

```
GET /api/user                => internal users
GET /api/user?tenant_id=null => internal users
GET /api/user?tenant_id=123  => users in tenant 123
```

now you can do

```
GET /api/user                  => internal users
GET /api/user?tenant_id=null   => internal users
GET /api/user?tenant_id=123    => users in tenant 123
GET /api/user?tenancy=all      => internal + external users
GET /api/user?tenancy=internal => internal users
GET /api/user?tenancy=external => external users (in all tenants)
```

If you specify both `tenancy` and `tenant_id` (regardless of the values
passed) you'll get a 400.

fix my bad rebase

fix bad rebase more

remove #p

mark tenants as `is_active` or not

initial external users management

remove permissions check on the trash endpoint

I don't know why this was added in the first place (I mean, I think I
added it, but I don't know why I did).

The trash is always accessible to everyone. We gate the visibility of
things *in* the trash, but the trash itself is always readable.

no personal collection for tenant users

remove tenant query inside oss

tenant user routes

make it so that you cannot remove users from the external users group

do not send email to tenant users

no login for inactive tenants

disable collection permissions, don't show sent email modal on user success with SMTP

remove all users group has higher permissions warnings for external users group

moving is external checks behind plugins

unit test cleanup, add simple test

read only application permissions for external users

set tenant on login with JWT

incredibly hacky tenant attribute

separate `:attributes` from `:login_attributes`

thinking here is that `login_attributes` are the things you set on the
user, where `attributes` are all the attributes of the user including
things like tenant slug or maybe someday locale etc.

fix build

fix token check

create a tenant collection in a migration

this works, but the tenant collection is always visible to admins, even
if the setting is off.

hide tenant collection from normal users

fixing build and FE rebase

Delete stray "howdy"

Lol, sorry about that.

fix tests

throw instead of silent failure on no tenant

superuser can't be tenant

fix up tenant collections

tenant collection now includes subcollections.

Tenant collections are hidden if the feature isn't enabled.

tenant collections marked in API

bugfix and current user can write any coll

don't add `attributes` key to all users

just the current user on login

invalidate groups when changing user strategy

read only user

{{ tenant_slug }} user attribute

fix be test

rip out tenant collection stuff on BE

fix BE tests

lint

fix magic string

no tenantifying existing users for now

also clean up a complicated, confusing fn.

starting e2e

fixing e2e, adjusting @tenant user attribute

fix permissions editor, add tenant.name e2e test

allow more than one user per tenant

🤦

allow getting only active tenants

*actually* don't replace existing values with nil

getting e2e ready for tenant user provisioning

tenants management ux

e2e coverage on sandboxing, deactivating tenants

replace {{tenant_slug}} with `@tenant.slug`

filter out other-tenant users from pulse creation

rename any existing `@.+` user attributes

prohibit new user attributes starting with `@`

fix migration

ugh, forgot to actually commit this file

add more tests

kondo

use the `tenants` feature

fix a test - missed one `:advanced-permissions`

e2e test coverage, updating tenant attribute to @tenant.slug

Partial Type Fixes

types green

unit tests

adding groups to e2e test, maybe fixing tenant feature check?

Add tenants to tracked snowplow features

Fixing Admin ui

Modernizing tenants page

separate external group in permissions sidebar

permissions editor updates

hardcode that *everyone* has trash access

shame... bad imports

adjusting Main Navbar. using globe icon

CR response

fix tests

fix attributes when tenants are disabled

lock up the 'all external users' collection

tenants route guard

add tests for missing feature and oss

fixing some unit tests, and type errors

set token features in default.cy.snap

unit and e2e test adjustment

another pass on e2e

fix e2e and build

fix a bad merge

Green CI?

reset token after restoring DB

move a test to fix the test

kondo

Move `/api/ee/tenants` to `/api/ee/tenant`

PR Feedback, part 1

move route functions into ee

ADM-1105 permissions editor adjustments for external users

ADM 1104 do not show invite button on external users when there is no tenant

adjusting unit tests

fix no results message for deactivated users page

center no results message

Fix migrations IDs / related tests

adjusting no results message for tehants

fixing unit tests, adding e2e test for permissions

chore: add timestamp columns to tenants (#60575)

* chore: add timestamp columns to tenants

* fixup! add hooks

* kick ci

Auto provision tenants, respect tenants feature (#60571)

deactivate tenant users along with their tenants (#60552)

* deactivate tenant users along with their tenants

Tenant users from deactivated tenants were already prevented from
logging in (we checked the activation status of their tenant) but for
bookkeeping it's probably best to actually deactivate the users
themselves along with their tenants, and reactivate them if the tenant
is reactivated.

* invalidate users when updating a tenant, adjust external users list screen

* e2e test

---------

Co-authored-by: Nick Fitzpatrick <nickfitz.582@gmail.com>

audit events for tenants (#60647)

* Revert "Delete unused string util from metabase lib (#64389)"

This reverts commit 0af38ef8f0.

* fix the build

* fix tests

* fix rebase error in invite button

* fix more tests

* fix more tests

* fix more tests

* fix more tests

* fix more tests

* fix more tests

* fix another test

* Fix another couple tests

* and more

* and more

* Close the modal to create shared tenant collection after it is created (#66049)

* Fix more tests, nearly all e2e tests passing

* a couple more tests

* couple more tests

* last (???) few tests

* Remove edit permissions in ellipsis menu when viewing shared tenant collection (#66042)

* Suggest external users only when adding tenant group members (#66046)

* feat: separate namespace for tenant collections (#66102)

* fixup! FE build

* feat: add remote-sync support for tenant collections (#66272)

* feat: add remote-sync support for tenant collections

* Update permissions.clj

* fixup! tests

* fixup! enterprise tests

* fixup! mysql/h2

* EMB-1011: add default read perms for namespace

* Fix tests (#66403)

* Fix tests

Not exactly sure how these got merged, I think maybe they were hidden by
GH issues.

* Fix kondo

* fix apparent rebase error

* fixup! EMB-1065 fix namespace filtering

* fixup! some bad perms tests

* fixup! remote sync dep checking across collections

* fixup! remove blank test

* fixup! missing tenant setting

* fixup! add premium feature declaration

* fixup! get test working with h2

* fixup! revert h2 fix

* fixup! revert h2 fix

* fixup! real h2 fix

* Dedicated Tenant Collections

* More fixes

* Tests and more fixes

* Fix rebase error

* rename

* Fix query for shared tenant collections

* fixup! UXW-2386 don't pass `tables` model into tenant root

* fixup! UXW-2436 build correct path for namespaced collections

* Remove test of non-existent fn

* Fix failing frontend unit and e2e tests in tenants feature branch (#66243)

Co-authored-by: John Swanson <john.d.swanson@gmail.com>

* fix failing frontend ESLint errors

* Prefix users and groups as "Internal" in admin settings when tenants are active (#66169)

* Update design of the user strategy modal for tenants (#66182)

Co-authored-by: Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>

* Add multi-tenancy setup guide to embedding hub (#66113)

* Update design of the tenants listing and internal user page (#66193)

* Give tenant users a personal collection

* Fix BE tests

* another be test

* Add specific error messages for JWT tenant claim errors (#66172)

* kondo/fmt

* fix running jwt tests standalone

* feat: per collection setting (#66475)

* feat: per collection setting

* feat: remove unsynced collections

* fixup! tests

* fixup! lints

* fixup! test

* Remove duplicated tenant permissions

* handle disabling feature more cleanly

when tenants is turned off:

- disable all tenant users

- reject any logins from tenant users

- reject any JWTs that specify a tenant

* Add tenant entity picker e2e tests. Fix one bug surfaced

* uxw-2456: remove drop shadows from dedicated tenant collection cards

* Hide tenant collections permissions tab when tenants are disabled (#66537)

* Hide create shared tenant collection button on sidebar for non-admin users (#66538)

* Hide tenant collections sidebar section when no collections exist for non-admins (#66539)

* Fix dedicated tenant collection root in collection picker as tenant user (#66549)

* fix frontend type-check: only set namespace if it is defined

* EMB-1093: Fix not passing a tenant attribute

Fixes [EMB-1093: If you enable multi-tenants and don't add JWT
attribute, it will
break](https://linear.app/metabase/issue/EMB-1093/if-you-enable-multi-tenants-and-dont-add-jwt-attribute-it-will-break)

* EMB-2459: Fix restrict where collections can be moved to

* Fixup working e2e entity picker tests

* fixup! mysql namespace tests

* fixup! tenant group mapping tests

* fixup! ws

* tree endpoint allows specifying multiple nses

* fix broken test

* Show dedicated tenant collections in collection pickers for admins (#66583)

* feat(sdk-bundle): add tenants ee plugin (#66586)

* fixup! bad ns clause audit feature is off

* fixup! UXW-2473 support non-string attributes

* Hide tenant collections section when there are no visible shared collections (#66597)

* Add tenant cards to search

* fixup! tenant collection cleanup

* EMB-1082 rename strings in the ui (#66603)

* make tenant field required (#66516)

* change `tenant` key to `@tenant`

- if the feature is off, you can still log in if you have the `@tenant`
key set. It will be silently ignored, but a warning will be logged.

- if the feature is on, `@tenant` is a drop-in replacement for `tenant`.

- we'd previously prevented setting user attributes that start with `@`.
This updates `remove-invalid-attributes` to do the same with JWT/SAML
attributes.

* add SAML tests

* Expose SAML attribute for tenant

* External users can't use MB if feature disabled

Plus add tests for:

- tenant user, feature disabled

- tenant user, feature unavailable

* Add missing test files

* Multi-stage embedding data picker should query models and questions from tenant collections (#66598)

* Fix external group tooltip referencing All Internal Users (#66654)

* Allow conversion of tenant <-> internal users

Upon conversion, all previous group memberships are destroyed and the
user is added to either the "All External Users" or "All Users" groups
accordingly.

* feat: implementing new tenant/remote-sync designs (#66567)

* fix missing dep in test file

and a tiny removal of an unnecessary `dissoc`

* fixup!: broken embedding page due to bad rebase conflict resolution

* fixup!: fix type errors

* fixup!: fix frontend jest unit test errors

* fixup! Move search tests requiring EE to EE code

* Fix copy test

* add confirmation warning when disabling tenants (#66697)

* fix test

* more renaming

* fixup!: failing tenants.cy.spec.js test and rename "All tenant users" migration

* fixup! whitespace fixes

* Remove serialization for dropped column

* fixup! missing migration

* fix other wrongly ordered migration

* fixup! Ordering more migrations

* fixup! other tests

* fix test

* fix another test

* api response schemas for tenant endpoints

* kondo

* one more kondo

* fixup! bad test query

* fixup! popover to use the right way of passing args

* Fix push changes modal

* fixup! correct token for entity picker tests

* Fix tenants e2e test with correct attribute

* fixup! tenants tests

* fixup! remove test for old behavior

* fix type on events, removed unused string union values

* update MainNavSharedCollections.unit.spec.tsx to use the new name

* fix linting issue unused import

* remove test file not on master anymore

* fix permissions select

* fix dashboard filters autowiring e2e test

* fix formating of module.edn

* remove useless test file

* add enum for namespaces

* fixup! remove toggle

* Update EntityPickerModal.tsx

* Remove commented tests

* Update e2e test based on feedback

* Split add-attributes-test

* Update test/metabase/collections_rest/api_test.clj

* Fix copy cmd model list

* Remove :put handling code for is_remote_synced

* Update src/metabase/premium_features/settings.clj

* Update resources/migrations/056_update_migrations.yaml

* Remove extraneous regex in api def

* Update frontend/src/metabase-types/analytics/event.ts

* UXW-2536 popup remote-sync modal after request

* Remove the "sidebar" event type

* Improve some backend tests

* Fix remote-sync e2e tests

* refactor: remove useAdminSetting and use settings already in the
component

* same for the jwt form

* move error message to Messages

* variant filled for apply button

* convert attributes to strings on read/write

In practice there is no difference between the value `true` and the
value `"true"`, so let's keep things simple by making all attributes
maps of string->string.

Fixes [UXW-2550: Cannot edit tenant users with non-string attributes](https://linear.app/metabase/issue/UXW-2550/cannot-edit-tenant-users-with-non-string-attributes)

* fw={500} => medium

* add c() to t`Sync {collection.name}`

* useSetting("use-tenants") in MainNavSharedCollections

* fixup extra dialog on permspagelayout

* fix broken tests

* fix the other broken test

* Remove tenant collection app permission

* Fix embedding sdk collection type

* Convert tenants e2e test to typescript

* move setupRemoteSyncEndpoints to server-mocks folder

* actually remove it from test-utils

* Small BE fixes

* use usePrevious from react-use

* Remove custom root tenant collection hook

* Change group detail to use text

* fix sdk type

* Redid git controls with button.group

* fixup! bad test

* fixup! tenant logic and components into plugins

* Update frontend/src/metabase/lib/string.js

Co-authored-by: Ryan Laurie <30528226+iethree@users.noreply.github.com>

* fixup! bad merge

* Rearrange last unit test for CollectionPicker

* fixup! PR feedback

* fixup! handle nils and seqs in attributes

* fixup! kondos

* fixup! better stringify

* Add missing maybe to login attributes schema

* fixup! yaml tests

* fixup! sequential check

* fixup! Stringify ldap attributes

* Fix ldap tests

---------

Co-authored-by: John Swanson <john.swanson@metabase.com>
Co-authored-by: John Swanson <john.d.swanson@gmail.com>
Co-authored-by: Phoomparin Mano <phoomparin@gmail.com>
Co-authored-by: Phoomparin Mano <poom@metabase.com>
Co-authored-by: Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>
Co-authored-by: Nicolò Pretto <info@npretto.com>
Co-authored-by: Ryan Laurie <iethree@gmail.com>
Co-authored-by: Ryan Laurie <30528226+iethree@users.noreply.github.com>
2025-12-12 12:53:38 -06:00
Anderson
241c2c9576 Add a horizontal border across the top of the dependency graph (transform, metric, table) (#66884) 2025-12-12 15:49:18 -03:00
John Swanson
641ddb52a9 bump search index version (#66890) 2025-12-12 12:28:37 -06:00
Nicolò Pretto
aba6bd6b9b fix: cors popover white-on-white when dark mode (#66881) 2025-12-12 17:39:22 +00:00
Braden Shepherdson
12c938d6b3 [perf] Add metric for lib.computed/weak-map size; speculative fixes (#66404)
OOMs in cloud are linked to this weak map retaining too much. The
exported heap dump reports are suggestive but not conclusive, and I
can't reproduce locally.

Adds `:metabase-query-processor/computed-weak-map-queries` to measure
the size of the weak map. That should sawtooth with GCs as it
accumulates queries and then discards them, but we'll see if it rises
forever on the problem instances.

This also adjusts the caching for a `MetadataProvider`-level entity
(`:metadata/card`) from the weak map to the `MetadataProvider`'s
internal cache. That's speculative, since there's no evidence to link
it to the issue, but it should be at least as effective a cache and
there's less risk of accidentally retaining too much.
2025-12-12 17:26:20 +00:00
Riley Thompson
653d9ab52f Fix clickhouse uuid filtering (#66852)
* fix uuid filtering

* rewrite tests to be more structured
2025-12-12 17:12:48 +00:00
Sébastien
fb303ccd82 Closes EMB-990 add description to columns in CollectionBrowser (#66305)
* Closes EMB-990 add description to columns in CollectionBrowser

* keep the existing behavior with tooltip unless description is explicitely set to be visible

* .

* addressed comments

* cleaned up unit tests
2025-12-12 17:14:17 +01:00
bryan
66bd405f0e Add mage doctor command for dev environment health checks (#66726) 2025-12-12 09:02:10 -07:00
John Swanson
ae9b3684b9 Enforce table collection permissions in search correctly (#66841)
* Ignore collection for unpublished tables

Unpublished tables have no collection and the `collection_id` means
nothing, and should be ignored.

* Add a test

* Fix legacy search permissions

Legacy search ignored the collection permissions for published tables,
so it was possible to get a table back from search even though you
didn't have permission to see it because it was published to a table.
2025-12-12 07:50:53 -08:00
Edward Paget
309d6a6b46 fix: apply deep serialization sort for remote-sync (#66846) 2025-12-12 08:24:14 -06:00
Brad Anderson
1ebb50b914 UXW-2531 Omits "New snippet" option in Library "New" dropdown if user lacks permission (#66835) 2025-12-12 09:10:24 -05:00
Mahatthana (Kelvin) Nomsawadi
f473c192b9 fix(embed-js): Fix EAJS children with ExplicitSize not scaling down (#66821)
* Fix EAJS children with ExplicitSize not scaling down

* Add tests

* Update e2e/test/scenarios/embedding/sdk-iframe-embedding-setup/select-embed-options.cy.spec.ts

Co-authored-by: Sébastien <sebastien@metabase.com>

* Fix formatting issue

---------

Co-authored-by: Sébastien <sebastien@metabase.com>
2025-12-12 13:42:23 +00:00
Sébastien
49503e742f fixes a flaky (#66822) 2025-12-12 12:57:14 +01:00
Mahatthana (Kelvin) Nomsawadi
b5788126a4 Avoid flashing of subscriptions channel selections sidebar (#66870) 2025-12-12 11:11:55 +00:00
Timofey Kachalov
cf87e41548 Adjust EAJS/SDK/adjust full-app names (#66753) 2025-12-12 14:28:16 +04:00
Mahatthana (Kelvin) Nomsawadi
354d5da0d6 fix(sdk-bundle): Fix can't drill numeric string ID dashboard (#66819)
* Fix can't drill numeric string ID dashboard

* Address when ID is an empty string
2025-12-12 09:27:38 +00:00
Kamil Mielnik
0168438c25 GDGT-1386 Auto-populate table name based on transform name (#66813)
* Auto populate targetName in CreateTransformModal

* Update tests

* Fix weird "./../" imports

* Fix logic
2025-12-12 15:58:59 +07:00
Ngoc Khuat
9db0f4c5e8 wraps transforms execute! multimethod with a function (#66555) 2025-12-12 08:12:59 +00:00
Fraser
6ab3820a60 Prepare backend in e2e stress test (#66868) 2025-12-12 05:29:17 +01:00
github-automation-metabase
900bc0c1aa Update generated docs (master) (#66865)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-11 21:21:43 -05:00
Aleksandr Lesnenko
028f67ab34 Segments list revision history, dependencies, list view in published tables (#66678)
* segments: published table segment list, revision history, dependency graph, breadcrumbs, move preview to the menu

* specs

* fix specs

* dedupe tests of segments pages

* fix avatars

* fix rebase

* visuals

* update specs

* final refactoring

* polish

* review

* drop react context although it adds a bit of dupe
2025-12-11 20:58:38 -05:00
Timothy S. Dean
68b1a18e1f Ensure Claude prefers clojure-mcp if it is available. (#66860)
For those of us who use clojure-mcp (https://github.com/bhauman/clojure-mcp), our Claude configuration directly contradicts instructions we're giving it. This PR only adds to our `CLAUDE.md` and our skills a note that **if** clojure-mcp is available, it should prefer it over shell-based methods (like `./bin/mage -repl`).
2025-12-11 17:05:30 -07:00
Denis Berezin
044323c97c UXW-2537 fix row/bar viz crash after native query column rename (#66786)
* UXW-2537 fix row/bar viz crash after native query column rename

* Fix unit tests
2025-12-12 01:59:30 +03:00
Cam Saul
6d6a477a2c Eliminate analytics dependency on channel (#66681)
* Eliminate `analytics` dependency on `channel`

* Update refs to `slack-configured?`

* Kondo
2025-12-11 14:49:40 -08:00
Cam Saul
4509828711 Split up queries and queries-rest modules (#66677) 2025-12-11 14:49:27 -08:00
John Swanson
7b8c62f63c No 500 on deactivating user (#66621)
Fixes https://github.com/metabase/metabase/issues/66599
2025-12-11 14:22:03 -08:00
Ryan Laurie
e7c1fc0c19 Show location of minipicker search items (#66736)
* show paths to minipicker search items

* widen modal and debounce

* show tables as in collections

* fix table display bug
2025-12-11 22:03:49 +00:00
metamben
d2d7f62d66 Trust the model's FK semantic type even for MBQL models (#66788)
* Trust the model's FK semantic type even for MBQL models

Fixes #48427
2025-12-11 21:44:38 +00:00
dpsutton
75e0180a66 Hide analytics-dev-mode setting from generated docs (#66794)
docs scoop up all settings and has ways to avoid. In
`metabase.cmd.env-var-dox/avoid?` This had a docstring and then an extra
docstring. We can just copy the nice docstring to the docstring slot and
put `:doc false`.

```clojure
(defn- avoid?
  "Used to filter out environment variables with high foot-gun indices."
  [env-var]
  (or (false? (:doc env-var))
      (false? (:can-read-from-env? env-var))
              ;; Ideally, we'd move off of this list completely,
              ;; but not all environment variables are defsettings.
      (contains? env-vars-not-to-mess-with (format-prefix env-var))))
```
2025-12-11 15:42:39 -06:00
Anderson
18e227736c Show breadcrumbs on published table page (Library > Data > table) (#66837)
* Show breadcrumbs on published table page (Library > Data > <table>)

* UXW-2524 Makes table breadcrumbs dynamic

* Adjust e2e test

---------

Co-authored-by: Brad Anderson <brad@metabase.com>
2025-12-11 21:41:37 +00:00
Nick Fitzpatrick
2ebcd1631c Various Data Studio Table Adjustments (#66795)
* Various Data Studio Table Adjustments

* remove unneeded comment
2025-12-11 21:08:50 +00:00
Anderson
d85ffad7cb Update Transforms detail view (#66532)
* Adjust UI on transform pages / Implement transforms view-only and edit mode

* Add and fix tests

* Fix tests

* Fix transform notebook query preview issues

* Adjust padding on runs page

* Adjust edit definition font size / query builder header margin / transform header icon

* More layout tweaks / Adjust preview section height calculation

* Fix lint / Make editor content-editable=false when readonly

* Remove unneeded TransformsSectionHeader.tsx

* Rename LibraryEditorHeader->PythonLibraryEditor in PythonLibraryEditorPage

* Fix scrolling behavior on a few pages

* Restore metabot button on transforms pages

* Fix PaneHeader for when we have breadcrumbs, actions and metabot button showing up

* Fix lint / Fix e2e test
2025-12-11 17:56:25 -03:00
Gabriel Moreno
c32c99e982 fix: send document data on analytics call (#66820) 2025-12-11 16:16:40 -04:00
Brad Anderson
789ee55ef8 UXW-2534+UXW-2527 Globally rename "Top folder" to "SQL snippets" in snippet collections + Remove the library option when dealing with collections in the snippet picker (#66787)
* UXW-2527 Disallows Library as an option in the snippet collection modal

* UXW-2534 Renames root sql snippet folder from "Top folder" to "SQL snippets" globally
2025-12-11 15:14:22 -05:00
Riley Thompson
af53e3fa1d Don't add newline to commented out clauses in native query preview (#66700)
* only replace clause if it's not commented

* add tests

* remove sql formatting on frontend
2025-12-11 14:25:56 -05:00
Timofey Kachalov
f3318cab6d Show a spinner button for the Download button when exporting (#66824) 2025-12-11 22:25:55 +04:00
Anderson
f504e28714 Improve database form dirty state awareness (#66684)
* Handle dirty state in the database form properly

* Change approach and add tests
2025-12-11 14:52:40 -03:00
Aleksandr Lesnenko
9b41d14147 fix broken text wrapping in tables in documents (#65254)
* fix broken text wrapping in tables in documents

* render measure root in a portal
2025-12-11 16:41:26 +00:00
Timofey Kachalov
fb721f66e8 Change Embed JS Wizard Upsells (#66756) 2025-12-11 20:13:18 +04:00
Roman Abdulmanov
8f2447f644 Fix for the limit in the static embed context (#66811) 2025-12-11 16:08:36 +00:00
Brad Anderson
87eed4d7c9 UXW-2519 Update Data Studio icon/logo (#66782) 2025-12-11 10:48:31 -05:00
Gabriel Moreno
c10c6c378a UXW-2322-2323 Document stats & analytics (#66665)
* feat: add document metrics to daily stats ping

* feat: add tracking event for leaving document without saving

* fix: leave without saving tracking event

* refactor: move `trackSimpleEvent` call to `analytics.ts`

* refactor: add all dependencies & check for previous value instead

* test: assert snowplow events on leave confirm modal display

* test: add document metrics test
2025-12-11 10:57:27 -04:00
Nathan Voxland
d66071551a Support relative-datetime in legacy mbql (#66214) 2025-12-11 08:51:01 -06:00
Eric Normand
7fec8c9fbf Prevent looping past current-schema-version when already past it (#66785)
* Prevent looping past current-schema-version when already past it.

* Add test for upgrade-card-schema-to-latest

* Make test parallel
2025-12-11 14:44:09 +00:00
Gabriel Moreno
81cd9980b6 refactor: unify TextInputBlurChange component (#66796) 2025-12-11 10:43:16 -04:00
Timofey Kachalov
551ed1694b Fix LegacyStaticEmbeddingAlert trigger when it is visible (#66812) 2025-12-11 18:36:48 +04:00
Nicolò Pretto
02f2d128f7 feat(sdk): skip first /auth/sso request when jwtProviderUri is passed (#66120)
* remove hash logic from /auth/sso endpoint to speed up sdk auth

* remove first /auth/sso request when jwtProviderUri is passed

* add e2e test

* Update enterprise/frontend/src/embedding-sdk-ee/tests/auth-flow/jwt.unit.spec.tsx

Co-authored-by: Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>

* address feedback: sort fields, remove dead code, don't requier
prefferredAuthMethod when the uri is passed

* Update enterprise/frontend/src/embedding-sdk-ee/auth/auth.ts

Co-authored-by: Sébastien <sebastien@metabase.com>

* stubbing Date

---------

Co-authored-by: Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>
Co-authored-by: Sébastien <sebastien@metabase.com>
2025-12-11 13:20:28 +01:00
Chris Truter
86e5e9d0e0 Optimize u/index-by when used with vf (#66800) 2025-12-11 09:29:04 +00:00
Nicolò Pretto
799f71841a remove hash logic in /auth/sso to speed up auth flow (#66076)
* remove hash logic from /auth/sso endpoint to speed up sdk auth

* fixed e2e test - again

* fixup

* remove nil assertion

---------

Co-authored-by: Sébastien <sebastien@metabase.com>
2025-12-11 09:43:07 +01:00
Cam Saul
d25eba372c Fix user attribute filters against implicitly joined tables that are also sandboxed (#66790) 2025-12-10 21:29:20 -08:00
Anderson
fe84b44bb3 Restore admin-permissions.cy.spec.js e2e test file (#66765)
this file got removed during a master->uxw-394-sub-collections-permissions-toggle merge on the PR #65928
the file had some changes, and removing it was not intended.

the version restored is this one, extracted from the same PR:
ab62f89a2c
2025-12-11 01:55:38 -03:00
Nick Fitzpatrick
6c903ded78 Tree Filter should not be case sensitive (#66792) 2025-12-10 22:15:51 -05:00
Alex Yarosh
d0705fd069 docs: debetify metabot (#66676)
* metabot unbetaying

* Apply suggestions from code review

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

---------

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2025-12-10 18:18:08 -05:00
Nick Fitzpatrick
a8f813a149 misc fixes (#66766)
* misc fixes

* memoize useTreeFilter response

* Avoid nested ternaries in LibrarySectionLayout

* Update column definition names, remove dependency graph header, use datetime on library page

---------

Co-authored-by: Anderson <anderson@metabase.com>
2025-12-10 16:42:01 -05:00
Riley Thompson
d358403667 fix typo (#66771) 2025-12-10 15:19:20 -05:00
Denis Berezin
f04e790b90 UXW-285 filter not accessible questions in data picker (#66483)
* UXW-285 filter not accessible questions in data picker

# Conflicts:
#	frontend/src/metabase-types/api/collection.ts

* Fix CI

* Fix e2e

* Fix CI, add e2e

* Add fix for big picker

* fix: CI

* Fix e2e tests
2025-12-10 21:23:56 +03:00
Nick Fitzpatrick
542861c88e Data Studio UX (#66612)
* New Data Studio UX

* cleaning up unused files

* small adjustments

* Groups 5 and 12

* groups 20 and 23

* Group 15 and Linter

* types?

* fixup hooks and routes

* fix item urls

* Fix transforms.cy.spec.ts (group 19)

* Fix transforms-codegen.cy.spec.ts (group 17)

* fix library page

* Fix MetricHeader and other typescript issues

* Fix snippets.cy.spec.ts (group 21)

* Fix modeling-metrics.cy.spec.ts (group 22)

* Create Libray Modal

* snippets tests

* Some Maz Feedback

* Reverts now-unnecessary prop change

* Revert probably unintentional change

* Fix modeling-tables.cy.spec.ts (group 9)

* Fixes date formatting

* Table fixes

* Fix hard-coded strings that need to be translated

* Fix naming

* Rename variables with "model" in the name that don't deal with models anymore

* Removes outdated e2e helpers

* Address @andsalves review comments

* Group 47 Errors

* Rename modeling -> library (#66762)

* Addresses useCollectionPath PR feedback

---------

Co-authored-by: Anderson <anderson@metabase.com>
Co-authored-by: Brad Anderson <brad@metabase.com>
2025-12-10 12:17:40 -05:00
Edward Paget
b31ea69d01 fix: update mongo docker/add :drivers to startup (#66764) 2025-12-10 10:23:59 -06:00
Riley Thompson
a173a45e80 Treat postgres bit strings as text (#66618)
* treat bit strings as text

* Add tests

* cast bit string values instead of fields

* only use string value if bit type

* fix kondo

* Add comment
2025-12-10 14:48:17 +00:00
Noah Moss
59154067f9 Deftool macro for Metabot tool APIs; tool API reorganization (#66614)
* tool macro + initial endpoint migration

* more endpoint migrations

* new deftool namespace + tests

* more consistent macro api

* parallelize new tests

* Reorganize: put argument/response schemas near tool defs, add section separators

* lint

* fix test

* remove skip-decode? - not needed

* Use perf/get-in
2025-12-10 14:31:01 +00:00
Jeff Bruemmer
8d920e120b note on metabot context (#66707) 2025-12-10 09:43:44 -03:00
Nicolò Maria Mezzopera
590bd138c5 GDGT-1313 | Bulk metadata usage analytics additions (#66582)
* feat: db managemtn

* WIP: load yamls

* wip: transform

* feat: just toggle on load-analytics-content

* feat: export

* chore: user-email

* analytics-dev-mode

* wip: startup logic

* require ns for init

* kondo

* wip: export route

* wip

* fix api

* feat: download button

* refactor

* fix db yaml

* fix: skip db for import

* chore: move stuff around

* use is-audit-dev toggle

* internal setting

* tighter control on export

* lint FE

* perf

* lint fe

* jar aware

* feat: PR-Env-analytics-dev

* chore: use timer

* fail unless postgres

* tests

* fix tests

* throw out of future

* delete old shell command

* feat: mage commands

* fix: test

* fixes for mage commands

* chore: return schema

* cleanup

* fixes to mage commands

* fix: is-audit-dev can always connect, it's appdb

* update checked out analytics to latest format

* reset on teardown

* reinstate even if no edit

* add analytics:finalize for convenience

* exclude qrtz and liquidbase tables

* feat: add usage analytics fields to v_tables views for PostgreSQL, MySQL, and H2

* feat: add new fields for entity type, estimated row count, owner email, owner user ID, view count, and visibility type in v_tables schema

* Apply suggestion from @bronsa

Co-authored-by: Nicola Mometto <nicola.mometto@metabase.com>

* fix: use unique changeset ID for usage analytics migration

Change the migration ID from v58.2025-11-19T00:00:02 to v58.2025-12-05T00:00:00
to avoid duplicate ID conflict with another changeset.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update resources/migrations/058_update_migrations.yaml

Co-authored-by: Nicola Mometto <nicola.mometto@metabase.com>

* Update frontend/src/metabase/status/components/AnalyticsExportStatus/AnalyticsExportStatus.tsx

Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>

* Update frontend/src/metabase/collections/components/CollectionHeader/CollectionExportAnalytics.tsx

Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>

* Update frontend/src/metabase/collections/components/CollectionHeader/CollectionExportAnalytics.tsx

Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>

* address review comments

* relativize

* remove needless == true

* missing io/file

* whitespace

* test: add regression test ensuring the usage analytics views have the expected fields, and they are synced properly

---------

Co-authored-by: Nicola Mometto <nicola.mometto@metabase.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>
Co-authored-by: Uladzimir Havenchyk <uladzimir@metabase.com>
2025-12-10 09:08:41 +01:00
dpsutton
5ccc379d41 add input for the logs-artifact-suffix (#66738)
also fix where the name comes from on the mysql job (it uses version not
job)
2025-12-09 23:22:36 -06:00
dpsutton
a06219bd1b handle uploads from matrix jobs (#66732)
motivating example:
we ran the redshift tests, and had three failures: redshift 1, redshift
2, and redshift transforms.

redshifts 1 and 2 timedout at 60 minutes. But the log upload failed
because the python transform tests failed in 24 minutes and then
uploaded:

from the transform failure run:

```
Run actions/upload-artifact@v4
  with:
    name: test-logs-be-tests-redshift-ee
    path: logs/test-log.json
    retention-days: 1
    if-no-files-found: warn
    compression-level: 6
    overwrite: false
    include-hidden-files: false
  env:
    CI: true
    ...
With the provided path, there will be 1 file uploaded
Artifact name is valid!
Root directory input is valid!
Beginning upload of artifact content to blob storage
Uploaded bytes 1072768
Finished uploading artifact content to blob storage!
SHA256 digest of uploaded artifact zip is 267d4b085d49ca4d682fedca97832fecb603bbb5a52c0e1d99bd4daa49984ba3
Finalizing artifact upload
Artifact test-logs-be-tests-redshift-ee.zip successfully finalized. Artifact ID 4816135520
Artifact test-logs-be-tests-redshift-ee has been successfully uploaded! Final size is 1072768 bytes. Artifact ID is 4816135520
```

And then from the redshift tests:

```
Run actions/upload-artifact@v4
  with:
    name: test-logs-be-tests-redshift-ee
    path: logs/test-log.json
    retention-days: 1
    if-no-files-found: warn
    compression-level: 6
    overwrite: false
    include-hidden-files: false
  env:
    CI: true
    ...
With the provided path, there will be 1 file uploaded
Artifact name is valid!
Root directory input is valid!
Error: Failed to CreateArtifact: Received non-retryable error: Failed request: (409) Conflict: an artifact with this name already exists on the workflow run
```

The same happens on redshift part 1.

```
Error: Failed to CreateArtifact: Received non-retryable error: Failed
request: (409) Conflict: an artifact with this name already exists on
the workflow run
```

This just introduces on the driver action to look for a
logs-artifact-suffix and use it if present. And on driver jobs that use
a matrix include the matrix.job.name (or matrix.version.name depending
on the exact structure).
2025-12-09 16:57:10 -06:00
Cam Saul
d2d11e9ed0 Fix query normalization issues in v57 (#66722)
* Fix query normalization issues in v57

* Remain strict when saving a query

* replace bad dataset_query with legacy_query

* Test fixes 🔧

* Test/Kondo fix 🔧

---------

Co-authored-by: dan sutton <dan@dpsutton.com>
2025-12-09 14:12:26 -08:00
Jeff Bruemmer
3483583201 docs - note on Metabot usage (#66702)
* note on Metabot usage

* clean up

* clarification
2025-12-09 16:33:44 -05:00
Eric Normand
37ec35a0c3 Make card schema upgrade 23 a no-op (#66719)
* Make card schema upgrade 23 a no-op

* Fix kondo error

* Yay, fix kondo error in other file

* Appease the module check
2025-12-09 16:23:22 -05:00
Riley Thompson
c9969b6552 Revert "Hide cursor in the readonly native editor (#63774)" (#66727)
This reverts commit f901d08b1c.
2025-12-09 20:31:41 +00:00
Denis Berezin
4861323112 UXW-2448 fix untime error with viz settings (#66657) 2025-12-09 22:24:58 +03:00
Prathyush Shankar
b6eae5e33f [docs] Add StarRocks driver to community drivers list (#66720)
Co-authored-by: carc-prathyush-shankar <prathyush.shankar@carbonarc.co>
2025-12-09 14:12:26 -05:00
Aleksandr Lesnenko
235958555f Fix gauge trims decimal parts of ranges (#66714)
* fix floating point numbers usage in gauge

* trigger change only if changed
2025-12-09 18:33:23 +00:00
Dennis Schridde
9e3e43f14a Show different copy on Metabot AI purchase page after trial (#66706)
### Description

In https://github.com/metabase/metabase/pull/65343 we added a page to purchase Metabase AI (Metabot).  Now we are improving the text to:
* Show information about trial only if Metabot was not already trialed
* Improve wording regarding multiple questions / messages in chat

### How to verify

1. Ensure you have a token with the `offer-metabase-ai-tiered` feature, but without the `metabot-v3` feature.
2. Check that the subscription associated with the token had either with (test case 1) or without (test case 2) the `metabase-ai` or the `metabase-ai-tiered` add-on.
3. Navigate to `/admin/metabot` and see the page look like in the mock ups.

### Checklist

- [x] Tests have been added/updated to cover changes in this PR

Closes: https://linear.app/metabase/issue/CLO-4673/show-different-copy-on-metabot-ai-purchase-page-after-trial
Closes: https://linear.app/metabase/issue/CLO-4688/copy-correction-in-the-admin-panel
2025-12-09 18:57:12 +01:00
Egor Grushin
c9222983ee GDGT-1275 make refetching for bulk metadata editing (#66543)
* GDGT-1275 make refetching not only for current path but for all selected nodes.
2025-12-09 17:40:18 +00:00
Brad Anderson
4794cc3081 Fix #66585: Updates static embeds to omit color-scheme settings to preserve legacy transparent iframe behavior (#66662)
* #66585 Updates static embeds to omit color-scheme settings to preserve legacy transparent iframe behavior

* support public embed too (#66693)

* support public embed too

* Imports isPublicEmbedding to prevent app crash

---------

Co-authored-by: Brad Anderson <brad@metabase.com>

---------

Co-authored-by: Nicolò Pretto <info@npretto.com>
2025-12-09 11:05:41 -05:00
Phoomparin Mano
4d72176b9e ci(sdk): fix broken docgen by adding interface modifier (#66695) 2025-12-09 15:54:59 +00:00
Sébastien
cc1ddc80f0 closes emb 1021 flaky test again (#66541) 2025-12-09 16:47:52 +01:00
Oleksandr Yakushev
92edd97120 [perf] Add and use m.u.performance/get-in (#65889) 2025-12-09 17:30:18 +02:00
Oleksandr Yakushev
002b049e11 [retry] Rewrite metabase.util.retry to use diehard instead of resilience4j (#66177) 2025-12-09 17:29:21 +02:00
Oleksandr Yakushev
85ab85b6cf Embed necessary part of crypto-random dependency and remove it (#66016) 2025-12-09 17:25:57 +02:00
Ryan Laurie
a09c470b1b Use the correct table icon for questions in the MiniPicker (#66485)
* use correct table icon

* update tests

* use viz icons for questions
2025-12-09 15:19:32 +00:00
Nicola Mometto
1b9b6bb524 Editable usage analytics (#66430)
* feat: db managemtn

* WIP: load yamls

* wip: transform

* feat: just toggle on load-analytics-content

* feat: export

* chore: user-email

* analytics-dev-mode

* wip: startup logic

* require ns for init

* kondo

* wip: export route

* wip

* fix api

* feat: download button

* refactor

* fix db yaml

* fix: skip db for import

* chore: move stuff around

* use is-audit-dev toggle

* internal setting

* tighter control on export

* lint FE

* perf

* lint fe

* jar aware

* feat: PR-Env-analytics-dev

* chore: use timer

* fail unless postgres

* tests

* fix tests

* throw out of future

* delete old shell command

* feat: mage commands

* fix: test

* fixes for mage commands

* chore: return schema

* cleanup

* fixes to mage commands

* fix: is-audit-dev can always connect, it's appdb

* update checked out analytics to latest format

* reset on teardown

* reinstate even if no edit

* add analytics:finalize for convenience

* exclude qrtz and liquidbase tables

* Update frontend/src/metabase/status/components/AnalyticsExportStatus/AnalyticsExportStatus.tsx

Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>

* Update frontend/src/metabase/collections/components/CollectionHeader/CollectionExportAnalytics.tsx

Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>

* Update frontend/src/metabase/collections/components/CollectionHeader/CollectionExportAnalytics.tsx

Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>

* address review comments

* relativize

* remove needless == true

* missing io/file

---------

Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>
Co-authored-by: Uladzimir Havenchyk <uladzimir@metabase.com>
2025-12-09 13:01:52 +00:00
William
470db21b7f Native query parsing understands queries with dependent ctes (#66139)
If you have a query like "WITH query_a AS (...), query_b AS (select ... from query_a) SELECT ... from query_b",
native query parsing understood that query_b in the final query referred to query_b in the WITH, but it didn't realize
that query_a in query_b referred to query_a in the WITH.  Now, it should understand these sorts of depedent ctes.
2025-12-09 02:22:24 -06:00
Timofey Kachalov
d0b8578497 Adjusted auth controls for Guest Embed flow Wizard (#66548) 2025-12-09 09:20:40 +04:00
Egor Grushin
f720766374 GDGT-1315 actualize a branch (#66571) 2025-12-09 02:24:58 +00:00
Alexander Polyankin
4eea91f41d Add documents to broken card responses (#66638)
* add documents

* fix icon

* documents

* Fix lint

* Show documents for questions in the graph (#66663)

* Add documents

* Handle link

* show documents

* X

* Fix

* Fix

* Fix
2025-12-08 19:20:47 -05:00
Nemanja Glumac
f72633bd9f Add mise for automated dev environment setup (#66517) 2025-12-08 22:46:07 +00:00
dpsutton
43e2dce357 Include "all entries for" in mt/all-entries-for (#66668)
this should get all audit log entries for a given model and
model-id. but previously it was using t2/select-one. now it uses
t2/select. whoops
2025-12-08 16:22:31 -06:00
Aleksandr Lesnenko
eda5bd5102 add more specs, fix implicit joins, polish code (#66630) 2025-12-08 22:05:16 +00:00
Cam Saul
569b976fc0 Add Kondo linter to make sure all tests are in a known module and fix violations (#66561)
* Add linter

* `metabase.query-processor-test.*` => `metabase.query-processor.*`

* cljfmt and ignore namespaces outside of module system

* `metabase.timeseries-query-processor-test` => `metabase.query-processor.timeseries-test`

* `metabase-enterprise.upload-test` => `metabase-enterprise.sandbox.upload-test`

* move `metabase-enterprise.models.entity-id-test` into `serialization`

* `metabase-enterprise.content-management.api.collection-test` => `content-verification`

* `metabase-enterprise.notification.payload.core-test` => OSS `notification`

* rename other ee notification payload test namespace

* Last round of fixes? 🔧

* Fix tests 🔧
2025-12-08 21:31:57 +00:00
Riley Thompson
632b5f96a9 fix: format week of year ordinal string safely (#66667)
* check if we should remove square brackets from week of year ordinal

* add tests
2025-12-08 16:30:05 -05:00
Denis Berezin
19e4e35d00 Move documents feature to OSS (#66223)
* Move documents feature to OSS

* Remove plugin

* Move comments, remove public sharing plugin

* Fix some CI issues

* Move documents BE to OSS

* Move documents BE to OSS

* Move documents BE to OSS

* Move documents BE to OSS

* Move documents BE to OSS

* Fix bug with state

* Move rest enterprise imports

* Remove token checks from apis related to documents

* Fix CI

* Fix CI

* Fix CI

* Fix CI

* Fix BE tests

* Fix CI

* Fix CI

* Fix bookmarking a document

* Add branding footer for public document

* Add e2e tests

* Fix CI

* Fix CI

* Fix CI

* Fix CI

* BE fixes for documents to oss  (#66511)

* reinstate sandbox test

* refactor circular deps

* fix: copy documents/comments

* fix path

* remote-sync tests are ee only

* ee only

* documents are not just ee

* kondo

* missing mapping

* set site-url

* fix broken tests

* Fix metabot plugin

* Fix issue where having a metabot block inside a document prevents it from loading when publicly shared (#66564)

* Prevents public document view from crashing when document contains a metabot node. Uses fallback similar to print version.

* Omits SupportingText drag handle when in read-only mode

* Adds e2e test to verify metabot blocks don't crash public documents and aren't editable within them

* Fix accidental spacing change

* Fix unit tests, cleanup e2e test

* fix after merge

---------

Co-authored-by: Nicola Mometto <nicola.mometto@metabase.com>
Co-authored-by: Brad Anderson <brad@metabase.com>
2025-12-08 23:54:55 +03:00
Eric Normand
d6923507a8 Add schema 23 upgrade (#66601)
* If dataset_query is empty and legacy_query is not, copy legacy query over

* Fix kondo errors and bump schema to 23

* Remove parens

* Baseline update
2025-12-08 15:41:51 -05:00
dpsutton
0aa02bdc36 add events when making cards/dash public or retracting (#64582)
* add events when making cards/dash pubic or retracting

https://github.com/metabase/metabase/issues/64417

When we make a card public, we put a uuid on it and include
`made_public_by_id`. But when you retract the public link, we remove
both bits of information. This is a nice invariant but it removes
information about who publicized a card.

Imagine a card is discovered by have been public. Of course you want to
immediately remove it. But this erases the audit trail (so to speak) of
who made it public. It is not a great idea to delay remediation during
the investigation. Now you can just consult the audit log

* make events

* formatting

* clean up tests a bit

tests were a bit wack. We should have utility functions to get audit
events. Also noticed we are going off of the object id and ignoring the
object. Could lead to gross issues if there's dashboard with id 4 in
there and also card with id 4. so require model on new one

* fmt
2025-12-08 13:12:41 -06:00
Alexander Polyankin
609c502fde Data studio drop models from Library (#66631)
* Remove models

* Remove models

* Move

* Move

* Drop columns for model publishing

* Drop columns for model publishing

* Drop columns for model publishing

* Drop columns for model publishing

* Rename library-models to library-data

* Rename library-models to library-data

* Rename library-models to library-data

* Rename library-models to library-data

* Fix tests

* Fix table URLs
2025-12-08 14:07:28 -05:00
metamben
ecd6168888 Address review comments from #66262 (#66648) 2025-12-08 21:51:28 +03:00
Ryan Laurie
a0a9850b20 Remove URLs from entities (#66282)
* dont need entities for collections methinks

* entities don't handle icons anymore

* revert url change (for now)

* fix tests

* remove urls from entities

* lil fixes

* fix types

* fix indexed entity urls
2025-12-08 08:30:54 -07:00
Ryan Laurie
275d15ca70 dont limit search to library (#66572) 2025-12-08 08:30:33 -07:00
Rodrigo López Dato
aad277faca Remove SLACK_WEBHOOK_URL from .env.example (#66649) 2025-12-08 14:12:41 +00:00
Denis Berezin
8279532cbb UXW-2257 fix theme override after table render (#66620) 2025-12-08 16:26:30 +03:00
Nemanja Glumac
3f8c3b946a E2E setup follow up (#66588) 2025-12-08 21:11:09 +13:00
Oleksandr Yakushev
f4c5bc93d9 [equality] Implement faster inequality operation for Long arguments (#65642) 2025-12-08 01:24:59 +02:00
Oleksandr Yakushev
be2e7054af Replace a solitary usage of clojure.data.xml with clojure.xml (#66573) 2025-12-08 00:55:23 +02:00
Gabriel Moreno
f6937a7021 fix: change 'support agent' to 'Success Engineer' (#66629) 2025-12-06 14:24:57 -04:00
Alexander Polyankin
7e31d3b579 Tables in collections (#66262)
* Empty

* FE

* FE

* Collection items

* Collection items

* Collection items

* Collection items

* Collection items

* Collection items

* Breadcrumbs

* Breadcrumbs

* Breadcrumbs

* Collection menu

* Add collection_id and is_published to metabase_table

* E2E tests

* Extend /collection/.../items endpoints with tables

* Hydrate collection in /api/table/:id, /api/table/:id/query_metadata

* Set collection_id in publish-table endpoint

* Set is_published flag on publish

* Implement unpublish

* Skip mi/can-read? on nil

* E2E tests

* E2E tests

* Name

* Name

* Name

* Name

* Name

* Name

* Name

* Name

* Name

* Publishing

* Publishing

* Improve tests a little

* Format extract-test

* Remove extraneous modules

* Publishing

* Fix some tests and the module config

* Publishing

* Fix search config

* Publishing

* Publishing

* Publishing

* Unpublish tables when their collection is deleted

* Publishing

* Publishing

* Publishing

* Publishing

* Publishing

* Publishing

* Publishing

* Check data permissions when listing tables

* Test that GET /api/database/:id/schema/:schema returns is_published

* Join tables in search via the database or collection, not both

* Publishing

* Publish tables into the singleton models library

* Publishing

* Publishing

* Remove duplication

* Fix tests

* Fix more tests

* Fix test

* Remove duplication

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Extract data model

* Fix tests

* Fix picker

* Fix tests

* Fix HoneySQL expression

* Use case expression instead of MySQL specific if

* Fix picker

* Fix picker

* Fix picker

* Fix picker

* Fix picker

* Remove duplication

* Remove duplication

* Remove duplication

* Remove duplication

* Properly return collections for published tables in search

* Remove duplication

* Fix test

* Use standard MySQL boolean conversion

* Remove duplication

* Remove duplication

* Use postgres compatible query string

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Return the root collection for tables published into it

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix test

* Implement in-place search for MySQL

* Fix tests

* Fix tests

* Fix collections in MySQL search's table results

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Try casting to placate MariaDB

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Fix tests

* Add CI debug logging for bit->boolean conversion

* Fix tests

* Fix tests

* Fix tests

* Fix spacing

* Fix spacing

* Fix spacing

* Fix below

* Fix below

* Fix below

* Fix below

* Throw an exception instead of debug logging

* Change publishing

* Change publishing

* Remove unused properties from response

* Handle MariaDB byte array booleans

* Remove unused properties from response

* fix tests

* Remove broken sorting

* Remove debugging exception and add pointer in comment

* Fix perms

* Update Loki Snapshots

* Make test verify that only superusers can (un)publish

* Merge master

* Tables in collections permissions (#66425)

* ,

* Add API return value schemas

* Fixes

* Fix formatting

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Centralize collection exports in core

* Remove trivial liquibase rollback instructions

* Fixes

* Fixes

---------

Co-authored-by: Tamás Benkő <tamas@metabase.com>
Co-authored-by: metamben <103100869+metamben@users.noreply.github.com>
Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-12-05 20:39:51 -05:00
Nemanja Glumac
5e76c476e2 Clarify MB_PREMIUM_EMBEDDING_TOKEN env var usage (#66627)
Comment out MB_PREMIUM_EMBEDDING_TOKEN in .env.example to prevent
conflicts with Cypress tests that need to start from a clean state, and
set tokens programmatically.
2025-12-06 13:19:09 +13:00
bryan
13e378ff86 bump the hive jdbc library (#66523) 2025-12-06 00:27:49 +01:00
bryan
bcd33be0ae yaml migrations helper, into mage (#66486)
Co-authored-by: Oleksandr Solovyov <o@solovyov.net>
2025-12-05 23:05:00 +00:00
Nemanja Glumac
2164c3bb20 Expand .env.example with Global Context and Local Development sections (#66625)
Add structured configuration for:
  - Global credentials (GitHub, AWS, Docker Hub)
  - Local development settings (app database, server, SMTP, Slack)
  - Feature flags and license tokens

  Reorganize sections with clearer descriptions and documentation links.

  Summary:

  The .env.example now has three main sections:
  1. Global Context - Shared tokens (GitHub, AWS, Docker Hub)
  2. E2E / Cypress Testing - Unchanged, already vetted
  3. Local Metabase Development - App database config,
server/integrations (Jetty, SMTP, Slack), and feature flags
2025-12-06 00:00:18 +01:00
Noah Moss
60f60e1c9b Sort ids before comparison in published-models-test (#66619) 2025-12-05 15:31:30 -07:00
Nemanja Glumac
a87175627a Cache trunk between runs (#66602)
Trunk action supports `use-cache` that should prevent us hitting
GitHub's API rate limits.
2025-12-05 21:41:41 +01:00
Filipe Silva
b3d7753609 fix: strip some attached dwh config keys on update (#66594)
We considered a few options before settling on this one:
1. replace usecase with private HM API
2. disallow db updates via config.yml
3. add config.yml update semantics
4. work around this particular use of config.yml for cloud dwh

1 would be a fair bit of work and testing, 2 could break existing
customers, 3 was a bit of a rabbit hole, and 4 was hacky.

We decided for 1 long term, 4 short term in https://metaboat.slack.com/archives/C010ZSXQY87/p1764869574808769.

Fix https://linear.app/metabase/issue/CLO-4581/metabase-cloud-storage-gets-set-by-default-in-the-upload-csv-everytime
2025-12-05 19:48:31 +00:00
Riley Thompson
c4cabddf8e implement driver.sql/json-field-length for druid-jdbc driver (#66525) 2025-12-05 19:25:52 +00:00
Riley Thompson
88a6c07b9c add starburst ssh (#66568) 2025-12-05 13:26:54 -05:00
Eric Normand
c0238e6024 Add :aggregation as valid argument to a filter. (#66560) 2025-12-05 18:15:20 +00:00
Riley Thompson
ab51e0f700 Only use snowflake dbname value if db value is not present (#66534)
* only use dbname value if db value is not present

* trigger ci

* remove role setting

* trigger ci
2025-12-05 17:59:53 +00:00
Riley Thompson
7a98f93ad7 Include segments in dependencies graph (#66264)
* initial segments dependencies

* add initial frontend for segment dependencies

* fix segment details and dependency analysis version

* fix fe

* Collection menu

* E2E tests

* Add segment to segment dep

* add view this segment link

* add segment calculation and events tests

* fix whitespace

* Fix tests

* fix remaining tests

* fix kondo

* fix kondo

* self review

* include implicit join deps for segments

* whitespace

* fix test

* Fix i18n issue

---------

Co-authored-by: Alexander Polyankin <alexander.polyankin@metabase.com>
2025-12-05 16:59:09 +00:00
Riley Thompson
4bdbeedf8e exclude snowflake (#66600) 2025-12-05 11:50:57 -05:00
Egor Grushin
b0a44b283b fix: add correct valueFormat for DateInput (GIT-8486, #65480) (#66298)
* fix: add correct valueFormat for DateInput (GIT-8486, #65480)

* GIT-8486 add cleanup after changing locales
2025-12-05 15:25:39 +00:00
Braden Shepherdson
e39fa09638 [QP] If a :field ref by ID needs fallback metadata, include :join-alias (#66563)
Fixes #66464.

This was a corner case in `lib.field.resolution` and `qp.util.add-alias-info`
that regressed in 57. It made the QP less smart about repairing a certain
class of broken queries, which regrettably exist in the wild.

The breakage in question was a `:field` ref in later stage, which had a
numeric field ID and a `:join-alias`. If that field ID was not actually
returned as part of the join anymore, fallback metadata would be
generated by looking up the field by ID. That "works" for non-joined
fields but for an explicitly joined field it would use
`source."SOME_FIELD"` rather than `"The Join Alias"."SOME_FIELD"`, which
causes SQL compilation to fail.
2025-12-05 10:10:40 -05:00
Dennis Schridde
ae8a038ec0 Adjust layout of Metabot purchase page and add video demo (#66580)
### Description

In https://github.com/metabase/metabase/pull/65343 we added a page to purchase Metabase AI (Metabot).  Now we are improving the layout and content to better present the product.

### How to verify

1. Ensure you have a token with the `offer-metabase-ai-tiered` feature, but without the `metabot-v3` and `offer-metabase-ai` features.
2. Navigate to `/admin/metabot` and see the page look like in the mock ups.

### Checklist

- [x] Tests have been added/updated to cover changes in this PR

Closes: https://linear.app/metabase/issue/CLO-4669/make-small-changes-to-ai-page-in-admin
2025-12-05 16:04:27 +01:00
Noah Moss
2af3fde476 Experimental options for improving Metabot Search [resurrected] (#66528)
* Combine metabot search queries using OR

* Fix zero-terms edge case

* Point out a critical defect

* Urgent typo

* Add docstring to join-results-by-rrf function

Co-authored-by: crisptrutski <881351+crisptrutski@users.noreply.github.com>

* Use non-semantic fallback engine for term-queries

* Group experimental options together

* Small fixes and testing

* Workaround for semantic search matching unwatned stuff

* Renaming and wiring

* Remove unused import

* Remove sharp edge around 0 queries

* Fix bug in disjunction for legacy search. Test coverage for it.

* Complete comment

* Whitespace lint

* Try to fix new tests - run in semantic search test group, simplify test configuration

* More test fixes

* More test fixes

* Whitespace lint

* Make appdb search check more explicit

* don't run metabot semantic search tests on h2 because they rely on the appdb backend being available

* address test comments

* remove experimental flags; make this the normal behavior

* fix test

* fix disjunction on h2

* try again to fix search-test

* move search-test to metabase-enterprise.metabot-v3.tools.semantic-search-test since it now requires semantic search to be available

---------

Co-authored-by: Chris Truter <chris@metabase.com>
Co-authored-by: crisptrutski <881351+crisptrutski@users.noreply.github.com>
2025-12-05 14:45:02 +00:00
github-automation-metabase
335cb2c39e Update generated docs (master) (#66491)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-05 09:12:03 -05:00
github-automation-metabase
2227341d69 Update generated docs (master) (#66575)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-05 09:11:31 -05:00
Mahatthana (Kelvin) Nomsawadi
61b0f5f503 feat(sdk-package, embed-js): Subscription supports for SDK/EAJS (#66249)
* Add a subscription button for modular embeddings (#65704)

* Add an entry to the dashboard subscriptions on modular embeddings

* Hide the subscription when email hasn't been set up

* Add tests

* Add subscription button to interactive and editable dashboard components

* Make dashboard button styles consistent + expose subscriptions button

* Fix types

* Fix wrong default `aria-label` for `ToolbarButton`

* Support `withSubscriptions` prop

* Add tests

* Make it so that modifying tests would be easier

* clarify missing assertions with a comment

* Fix types

* Update Loki Snapshots

* Add `withSubscriptions` to storybook

* Remove duplicate test

* Fix comment date format

* Tighthen ToolbarButton prop type

* Avoiding cramping all test combinations into a single test

* Move shared tests to the correct directory

* Make the function parameter order makes more sense

* Simplify SDK dashboard button visibility logic

* Make shared tests more structured

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>

* Avoid showing other subscription channels (#66126)

* Make text search easier on an enum

* Prepare state for upcoming change

* Avoid showing the NEW_PULSE screen on SDK

* Add tests

* Fix tests

* Make mocking module more idiomatic

* Update subscription sidebar email edit view content (#66258)

* Update subscription sidebar email edit view content

* Add tests

* Improve test related variable name

* Properly memoize parent callback

* Add dashboard subscriptions option to EAJS dashboards (#66309)

* Expose `withSubscriptions` to EAJS dashboards

* Close subscription sidebar when unchecking `withSubscriptions` checkbox on EAJS

* Add `withSubscriptions` to EAJS dashboards

* Add tests + adjust no email setup tooltip condition

* Add missing unit tests mock

* Only closes sidebar when subscriptions sidebar is open

* Make guest embed warning tooltip aligned with its label

* Fix a test after merging guest embeds

* Update tooltip design from using hovercard to tooltip

* Close the subscription sidebar when the last pulse is archived (#66496)

* close the subscription sidebar when the last pulse is archived

* Ensure we only close the sidebar on the last subscription deletion

* Remove unused code

* simplify mocking

---------

Co-authored-by: Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>

* Added one happy path e2e test (#66506)

* Added one happy path e2e test

* .

* .

* Pass tests on CI with SMTP server

* Remove unused interceptions

* Use explicit assertions

---------

Co-authored-by: Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>

* Run maildev in CI

* Fix admins aren't shown subscription list page after creating first subscription (#66372)

* Run maildev in CI

* Fix admins aren't shown subscription list page after creating first one

* Fix test name typo

* Apply suggestions from code review

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

* Fix tests after merging another PR

---------

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

* Make subscriptions on SDK/EAJS a Pro feature (#66392)

* Make subscriptions on SDK a Pro feature

* Add subscription only to EAJS on pro plan

* Correct directory name

* Fix InteractiveDashboard unit tests to use EE token

* Fix StaticDashboard tests to use EE token feature

* Fix EditableDashboard tests to use EE token feature

* Remove OSS tests because there's no SDK on OSS version

* Update Eajs related terms

* Allow subscriptions SDK plugin to be reinitialized

* Standardize plugin enabled property name for EAJS plugins

* Add embed wizard tests

* Add EAJS tests

* Fix OSS test

* Add missing assertions on Enterprise tests

* Optimize API calls on SDK/EAJS

* Clarify comments

* Use initialize plugin pattern for EAJS

* Fix test name

* Fix assertion because upstream content change

* Auto update EAJS subscriptions options after configure email

* Update no email setup tooltip

* Remove debugging code

* Try to fix 1 nasty E2E test

* Fix the samn test again

* Fix the E2E again™️

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
Co-authored-by: Sébastien <sebastien@metabase.com>
Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>
2025-12-05 05:06:25 +00:00
Nemanja Glumac
fd47d82ba1 E2E test environment setup based on deps.edn :e2e alias (#66431) 2025-12-05 00:55:55 +00:00
bryan
b1ececbe32 Mage sounds (#66482)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-04 17:55:56 -06:00
Oleksandr Yakushev
185aa6841a Remove transducers and core.logic deps (#66510) 2025-12-05 01:50:40 +02:00
Jeff Bruemmer
01e4247864 docs - update quickstart (#66527)
* fix up quickstart

* versions

* consolidate clones

* fix link
2025-12-04 22:06:51 +00:00
Timothy S. Dean
deafc84886 Forward-port regression tests for Issue 66405 affecting v0.56 (#66557)
Copies in regression tests for an issue fixed in 0.56 that didn't affect later versions. Relates to Very Long Names in Tables.
2025-12-04 14:55:27 -07:00
Cam Saul
b4a13bb4c6 Add Kondo linter for defendpoint without response schema (#66294)
* Add Kondo linter for defendpoint without response schema

* Fix Kondo/cljfmt
2025-12-04 21:40:57 +00:00
Edward Paget
09a24ab09d fix: remote-sync icons matching non-collections (#66558) 2025-12-04 19:31:20 +00:00
Timofey Kachalov
5568ace394 Handle unknown theme preset (#66554) 2025-12-04 23:07:24 +04:00
dpsutton
2048f84d4b When setting settings, include 5 minute cookie of updated timestamp (#66338)
* When setting settings, include 5 minute cookie of updated timestamp

if other instances have outdated settings cache, this cookie will let
them know what the requestor has seen. The instance can then know it is
out of date. This won't help for instances that aren't hit by the person
setting the setting.

Motivating example is someone who is doing an embedding onboarding
checklist. And then hits a new instance that hasn't yet loaded the "show
embedding homepage" setting so it flips back to the regular
homepage. The hope here is the person doing this checklist will let the
other instance know it is out of date, reload the settings cache and
then see the embedding setting.

* Interesting strategy here for cookies.

I hated that the route would would set a cookie at a particular key, do
timestamp stuff, etc. I know ring is a map and abstraction, but i added
a new paradigm:

```clojure
(defn- add-settings-last-updated-cookie
  "Add a cookie with the current settings-last-updated timestamp to the response."
  [response]
  (assoc-in response [:mb/cookies :cookie/settings-cache-timestamp] true))
```

This means that just the middleware is responsible for checking and
setting this key. This was largely driven by two different namespaces
having a private def of:

```clojure
(def ^:private settings-last-updated-cookie-name "metabase.SETTINGS_LAST_UPDATED")
```

And it's nice if the ring map can indicate to this middleware to handle
all the key and timestamp stuff and it just has to indicate to set this
with `cookie/settings-cache-timestamp`.

So the request looks like this:

```clojure
{:status 204
 :headers {"X-Frame-Options" "DENY"
           "X-XSS-Protection" "1; mode=block"
           "Last-Modified" "Mon, 1 Dec 2025 17:09:59 GMT"
           "Strict-Transport-Security" "max-age=31536000"
           "X-Permitted-Cross-Domain-Policies" "none"
           "Cache-Control" "max-age=0, no-cache, must-revalidate, proxy-revalidate"
           "X-Content-Type-Options" "nosniff"
           "Content-Security-Policy" "...<lots of junk>..."
           "Expires" "Tue, 03 Jul 2001 06:00:00 GMT"}
 :body nil
 :mb/cookies {:cookie/settings-cache-timestamp true} ;; <---- our new addition
 :cookies {"metabase.DEVICE" {:value "60ac9454-9dd1-439a-afa1-921ff029686d"
                              :http-only true
                              :path "/"
                              :expires "Fri, 1 Dec 2045 17:09:59 GMT"
                              :same-site :lax}}}
```

And then in practice, it looks like this:

Set the setting and get a cookie with the timestamp in response:

```
❯ http put :3000/api/setting/site-name value=foo x-api-key:$KEY
HTTP/1.1 204 No Content
...
Set-Cookie: metabase.SETTINGS_LAST_UPDATED=2025-12-01+17%3A28%3A15.450873%2B00; Path=/; Max-Age=300; SameSite=Lax
...
```

Simulate sending to another instance with a timestamp that exceeds the
currently know timestamp (i'll increment the hour based sent back in
this response)

```
❯ http get :3000/api/user/current x-api-key:$KEY Cookie:metabase.SETTINGS_LAST_UPDATED="2025-12-01+18%3A23%3A51.059155%2B00" | jq '.date_joined'
"2025-12-01T16:51:08.137822Z"
```
(note the 18 vs the 17)

And the logs are this:

```
INFO middleware.settings-cache :: Settings cookie indicates cache is out of date. Refreshing...
DEBUG middleware.log :: GET /api/user/current 200 19ms (11 DB calls) App DB connections: 0/4 Jetty threads: 5/50 (5 idle, 0 queued) (245 total active threads) Queries in flight: 0 (0 queued) {:metabase-user-id 346}
```

* fixes:

- logged known timestamp not weird cookie value
- timestamp is optional, so handle that
- typo in log konwn -> known

* Add tests, add functionality

tests:
ensure it (a) sets the cookie, (b) honors the cookie, and when it
restores the cache, to set the cookie so it doesn't keep thrashing. But
presumably it won't since it's up to date. My "in the future" version is
a bit synthetic.

Functionality wise, updating the cache now returns and this will saet
the header with the most recent cache setting
2025-12-04 10:25:59 -06:00
Sébastien
421ac355e4 Closes EMB-1042 removed flaky e2e test and adds a unit test instead (#66424)
* Closes EMB-1042 removed flaky e2e test and adds a unit test instead

* yeah no timeout

* fixed poor rebase

* better use of fetchmock in unit test
2025-12-04 17:12:51 +01:00
Ryan Laurie
4d0695b9da Make GET /api/ee/library return null instead of message (#66440)
* fancy clojure

* fix frontend to use new format

* fix test
2025-12-04 15:49:57 +00:00
Nemanja Glumac
e8a68aaac0 Upgrade NextJS again (#66547) 2025-12-04 16:12:06 +01:00
Nick Fitzpatrick
fb7d69d69a hide Our Analytics if user does not have access (#66377)
* hide Our Analytics if user does not have access

* adjusting unit tests
2025-12-04 14:52:27 +00:00
Egor Grushin
e3a6420b78 e2e: add e2e reproduction (#66351)
* e2e: add e2e reproduction for adding custom column in Detail viz without saving #63181
Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>
2025-12-04 13:13:12 +00:00
Timofey Kachalov
25fc5ea0c2 Add the "Theme preset" selection in Embed JS Wizard when no feature token is available (#66495) 2025-12-04 15:01:37 +04:00
Ryan Laurie
63fc190227 Fix icons in data studio collection table (#66530)
* fix icons in data studio collection table

* add unit tests for collectionPage

---------

Co-authored-by: Nick Fitzpatrick <nick@metabase.com>
2025-12-04 02:53:54 +00:00
Anderson
438230281b Add Snowplow Events for Data Studio (#66383)
* Add Snowplow Events for Data Studio

* Clean up event list

* Drop data_studio_dependency_graph_opened
2025-12-04 00:20:11 +00:00
bryan
2aec7ccbe1 update mage alias + fix it for fish (#66526) 2025-12-03 16:32:36 -07:00
Nemanja Glumac
b748b7f206 dx: Dev bootstrap (#66501) 2025-12-04 00:12:12 +01:00
bryan
021ac994c9 fix port handling + remove top-level invocation (#66473) 2025-12-03 23:48:45 +01:00
Mohamed Elkmeshi
7ad8025757 Use Fixed Postgres Version and Add Persistent Volume to Prevent Data Loss (#66109)
Updated PostgreSQL image version to 16 and added volume for data persistence.
2025-12-03 17:16:53 -05:00
Nick Fitzpatrick
6d1a2ef106 drill into library collections when apropriate (#66438) 2025-12-03 16:49:53 -04:00
Noah Moss
7a5e659c14 Revert "Experimental options for improving Metabot Search (#65691)" (#66522)
This reverts commit c75dd94d02.
2025-12-03 20:37:39 +00:00
Aleksandr Lesnenko
c7acd66fbd Revert "data studio application permission (#66265)" (#66505)
This reverts commit e675d614d7.
2025-12-03 15:17:43 -05:00
Chris Truter
c75dd94d02 Experimental options for improving Metabot Search (#65691) 2025-12-03 19:02:11 +00:00
Riley Thompson
8ce3b6b406 use json unquote (#66512) 2025-12-03 18:29:31 +00:00
Egor Grushin
554ab26066 fix: show confirmation on escape, clickoutside and browser's back actions for SidebarCacheForm (#66173)
* fix: show confirmation on escape, clickoutside and browser's back actions for SidebarCacheForm (#53825)

additional: refactor useConfirmOnRouteLeave hook, add an ability to get router across application without property drilling using hook instead

# Conflicts:
#	frontend/src/metabase/plugins/index.ts

* fix: small adjustment

* fix: small adjustment

* fix: tests

* fix: tests

* fix: created useStackedSidesheets hook to help control stacked sidesheets

* adds a test for useStackedSidesheets that covers #53825 issue

* adds tests for useConfirmOnRouteLeave that cover #53825 issue

* rename useStackedSidesheets to useStackedModals. Add backward compatibility prop opened

* fix: add history provider as well for the future purposes.

* fix typings

* fix code based on comments from PR

* fix tests

* fix tests

* fix tests

* remove useStackedModals. Write e2e for all "closing" actions

* remove useStackedModals. Write e2e for all "closing" actions

* adjusted code according to PR comments

* fix tests

* make tests that asserts the confirmation modal showing if there are dirty form explicit in order to see which of them is broken in CI

* fix tests

* remove "forward" browser's button testing on trying to close a dirty form

* fix tests

* fix tests
2025-12-03 17:56:35 +00:00
Sébastien
3f83679f50 flaky flaky, eggs and baky (#66312) 2025-12-03 17:29:32 +01:00
Sébastien
f17e7985fa Closes EMB-1069 create new embed -> embed (#66457)
* Closes EMB-1069 create new embed - embed

* .
2025-12-03 17:28:48 +01:00
Eric Normand
e883cd1a66 Continue sync even if a table fails (#66432)
* Add reproduction test

* Fix for clickhouse
2025-12-03 10:18:56 -06:00
Oleksandr Yakushev
c9f40f60fc Replace nano-id dependency with already included Encore (#66413) 2025-12-03 14:33:59 +00:00
Sébastien
71a8b3f4c1 fix(sdk-cli): Fixes CLI quickstart not passing in the proper revision in query (#66493)
* Fixes CLI quickstart not passing in the proper revision in query

* .
2025-12-03 11:16:14 +01:00
Anderson
a33f7f45ee Fix sub-collections toggle to stick when permissions selector is closed / Handle permissions dirty state gracefully (#65928)
* Fix sub-collections toggle to stick when permission seletor is closed / Handle dirty state gracefully

* Add e2e tests

* Fix outstanding e2e tests

* Remove e2e test that was expecting the previous undesired behavior

* Update test that accounts for issue #30494

* Add clarifying comment
2025-12-03 00:00:33 -03:00
Anderson
f8d9445828 Keep bars with 100% height when hiding a segment in a 100% stacked chart (#66477) 2025-12-02 23:51:45 -03:00
LP
6a366df534 Fixes 60942 (#61080)
Fixes https://github.com/metabase/metabase/issues/60942

Co-authored-by: Riley Thompson <riley@metabase.com>
2025-12-02 23:09:52 +00:00
Denis Berezin
cd301be781 Persist selected theme in account settings (#66250)
* Persist selected theme in account settings

* Persist selected theme in account settings

* Add e2e

* Add e2e

* Review fixes

* Refactor initial value get to fix e2e tests

* fix e2e

* Fix BE module test

* Fix CI

---------

Co-authored-by: John Swanson <john.d.swanson@gmail.com>
2025-12-03 02:07:10 +03:00
Nick Fitzpatrick
ceb7f93db9 handle users with no first or last names in document comments (#66468) 2025-12-02 17:46:56 -04:00
Timofey Kachalov
581e723cc7 Fix props normalization. Adjust Interactive Embedding text. (#66465) 2025-12-03 01:18:05 +04:00
dpsutton
c8d0e466a3 better tests mimicing what i did in the backport (#66472) 2025-12-02 15:16:29 -06:00
Gabriel Moreno
f6a25e57ce UXW-2404 Remove toggle to disable anonymous analytics on cloud (#66469)
* fix: hide anonymous tracking toggle on cloud plans

* test: update general settings page suite

* fix: feedback on testing & token feature extraction
2025-12-02 15:56:06 -04:00
Aleksandr Lesnenko
e675d614d7 data studio application permission (#66265)
* data studio app permission

* actually transforms are for admins

* check permission for open in data studio

* Auto-set library permissions on data studio permission changes

* Fixed module references

* initial library collection perms

* Fixed module references

* Fixed module references

* Fixed lint errors

* perms

* specs, fixes

* ci

* data studio permission

* Added data-studio permission check to glossary

---------

Co-authored-by: Nathan Voxland <nathan@metabase.com>
2025-12-02 14:34:29 -05:00
Nemanja Glumac
e50e049a35 Remove superfluous cache-key in e2e stress-test workflow (#66462) 2025-12-02 19:54:29 +01:00
Gabriel Moreno
36a0145de8 UXW-804 Fix collection name & description character limits (#66380)
* feat: add `maxLength` attributes to collection `name` and `description`

* test: update suites for `CollectionHeader`

* feat: update max length validation for `CollectionInfoSidebar`

* feat: update max length validation for `NewCollectionDialog`

* test: update `CollectionInfoSidebar` and `CollectionCaption` tests

* style: update toast color

* refactor: remove unreachable checks & assertions

* test: remove unnecessary checks and render spread
2025-12-02 17:56:31 +00:00
Sébastien
68fb668302 Closes EMB-1055 static embedding without a theme defaults to dark mode or system settings (#66320)
* Closes EMB-1055 static embedding without a theme defaults to dark mode or system settings

* types

* .
2025-12-02 17:53:04 +01:00
dpsutton
107738831d Lets not log when a user cancels a query (#66292)
* Lets not log when a user cancels a query

look how gross this is

```
2025-11-25 23:03:09,543 ERROR middleware.catch-exceptions :: Error processing query: ERROR: canceling statement due to user request
{:database_id 613,
 :parameterized false,
 :started_at #t "2025-11-25T23:03:03.698696Z[UTC]",
 :via
 [{:status :failed,
   :class clojure.lang.ExceptionInfo,
   :error "Error executing query: ERROR: canceling statement due to user request",
   :stacktrace
   ["--> driver.sql_jdbc.execute$execute_reducible_query$fn__452061$fn__452062.invoke(execute.clj:772)"
    "driver.sql_jdbc.execute$execute_reducible_query$fn__452061.invoke(execute.clj:767)"
    "driver.sql_jdbc.execute$eval451741$fn__451742$fn__451743.invoke(execute.clj:422)"
    "driver.sql_jdbc.execute$fn__451652$do_with_resolved_connection451651__451653.invoke(execute.clj:347)"
    "driver.sql_jdbc.execute$fn__451652$fn__451658.invoke(execute.clj:327)"
    "driver.sql_jdbc.execute$eval451741$fn__451742.invoke(execute.clj:416)"
    "driver.sql_jdbc.execute$execute_reducible_query.invokeStatic(execute.clj:760)"
    "driver.sql_jdbc.execute$execute_reducible_query.invoke(execute.clj:749)"
    ...
     :state "57014",
 :error_type :invalid-query,
 :json_query
 {:lib/type "mbql/query",
  :stages [{:native "select 1, pg_sleep(40)", :lib/type "mbql.stage/native", :template-tags {}}],
  :database 613,
  :parameters [],
  :middleware {:js-int-to-string? true, :userland-query? true, :add-default-userland-constraints? true}},
 :status :failed,
 :class org.postgresql.util.PSQLException,
 :stacktrace
 ["org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2734)"
  "org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2421)"
  "org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:372)"
  "org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:518)"
  "org.postgresql.jdbc.PgStatement.execute(PgStatement.java:435)"
  "org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:357)"
  "org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:342)"
  "org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:318)"
  ...
    "query_processor.streaming$_streaming_response$fn__108781$fn__108782$fn__108783.invoke(streaming.clj:225)"
  "query_processor.streaming$_streaming_response$fn__108781$fn__108782.invoke(streaming.clj:223)"
  "query_processor.streaming$do_with_streaming_rff.invokeStatic(streaming.clj:214)"
  "query_processor.streaming$do_with_streaming_rff.invoke(streaming.clj:201)"
  "query_processor.streaming$_streaming_response$fn__108781.invoke(streaming.clj:220)"
  "server.streaming_response$do_f_STAR_.invokeStatic(streaming_response.clj:83)"
  "server.streaming_response$do_f_STAR_.invoke(streaming_response.clj:81)"
  "server.streaming_response$do_f_async$task__108307.invoke(streaming_response.clj:98)"],
 :card_id nil,
 :context :ad-hoc,
 :error "ERROR: canceling statement due to user request",
 :row_count 0,
 :running_time 0,
 :data {:rows [], :cols []}}

2025-11-25 23:03:09,570 DEBUG middleware.log :: POST /api/dataset 202 [ASYNC: canceled] 5888ms (8 DB calls) App DB connections: 0/6 Jetty threads: 5/50 (4 idle, 0 queued) (228 total active threads) Queries in flight: 0 (0 queued); postgres DB 613 connections: 0/1 (0 threads blocked) {:metabase-user-id 1}
```

how embarassing. we're just canceling a query. we don't need a stacktrace.

and after:

```
2025-11-25 23:39:40,197 DEBUG middleware.log :: POST /api/dataset 202 [ASYNC: canceled] 3076ms (8 DB calls) App DB connections: 1/10 Jetty threads: 4/50 (2 idle, 0 queued) (233 total active threads) Queries in flight: 0 (0 queued); postgres DB 613 connections: 0/2 (0 threads blocked) {:metabase-user-id 1}
```

note the post is cancelled but no big stack trace

* postgres test

* format file

* move postgres tests into postgres
2025-12-02 09:43:57 -06:00
github-automation-metabase
5009187cc3 Update generated docs (master) (#66451)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-02 10:09:22 -05:00
Jakub Chodorowicz
921351ca94 Gdgt 1216 table search should expand dbschema context for matches (#66393)
* WIP: add hierarchical search view

* refactor: reuse existing node models

* feat: handle schema and db selection

* feat: add expansions capability to search

* refactor: small cleanup

* refactor: reuse bulk selection utils on tree and search

* refactor: remove unused getParentSchemaTables

* feat: hide schemas in single schema dbs

* fix: tables in nameless schema are hidden

* test: add cypress tree search results tests

* refactor: type guards function names

* fix: clear selection when search results change

* refactor: handleItemSelect

* rework: use type guard helpers in more places

* rework: unneeded conditional

* refactor: simplify param passed to TablePickerResults

* refactor: remove type casting

* rework: remove unneded type casting

* refactor: simplify conditional

* internal: use existing key serializer

* feat: non languate dependend fallback db name

* rework: improve types

* rework: improve tree node types

* internal: improve useExpandedState to default to closed state

* refactor: use useCallback hook

* refactor: improve type

* refactor: remove confusing return in forEach
2025-12-02 15:34:13 +01:00
Jeff Bruemmer
367bb055ba docs - IAM auth note on postgresql (#66212)
* IAM auth note on postgresql

* move to rds

* rds

* mysql note on verify-ca

* Update docs/databases/connections/aws-rds.md

Co-authored-by: Alex Yarosh <alexandra@metabase.com>

---------

Co-authored-by: Alex Yarosh <alexandra@metabase.com>
2025-12-02 11:17:12 -03:00
Sébastien
eb3d8eb251 Closes EMB-1063 docs url (#66460) 2025-12-02 14:46:36 +01:00
Nemanja Glumac
aad6641a4b Remove custom MB_IS_CYPRESS flag (#66459)
We don't need it anymore because running Cypress now requires
a backend to be running in e2e mode.
2025-12-02 14:08:49 +01:00
Dan Stone
7626544f50 Data studio table filtering improvements (#66362)
* Add display_name filtering to table list

* Re-introduce mixed case LIKE for mysql/maria

Must have been lost in a merge conflict

* Escaping rules

* Kondo
2025-12-02 10:44:12 +00:00
Timofey Kachalov
bfc0e2077a feat(sdk, embed-js): Add Guest Embeds via Embed JS and SDK (#64850) 2025-12-02 13:22:11 +04:00
bryan
1591300b49 updated-files returns all-files + Mage cleanup (#66332) 2025-12-02 00:44:09 +00:00
Gabriel Moreno
741d2ddbab UXW-2310 Fix upsell CTA misalignment & stepper card overflow on custom fonts (#66443)
* fix: avoid breaking spaces on upsell CTA link

* fix: exchange `h` for `mih` on stepper card components and allow for flexible height
2025-12-01 19:20:58 -04:00
github-automation-metabase
0c4c8c06ab Update generated docs (master) (#66353)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-01 16:21:30 -05:00
Cam Saul
7f68894e80 New deps graph tooling to power Mage test watching (#66345) 2025-12-01 19:53:40 +00:00
Ryan Laurie
b933496d37 Don't use entities for Icons (#65633)
* dont need entities for collections methinks

* entities don't handle icons anymore

* revert url change (for now)

* fix tests

* fix verified model icon

* consistent handling of verified model icons
2025-12-01 12:32:53 -07:00
Jeff Bruemmer
32d69c1a4f remove env vars that now have defsettings (#66434) 2025-12-01 19:23:55 +00:00
Alex Yarosh
7096051905 Docs: DBs for editable tables (#66276)
* Add Metabase Sample Database to editable tables support

Updated the list of databases that support editable tables to include Metabase Sample Database.

* Update docs/data-modeling/editable-tables.md

* Update docs/data-modeling/editable-tables.md
2025-12-01 14:07:10 -05:00
Nemanja Glumac
e88075f7d4 Fix snapshots for backport compatibility tests (#66433) 2025-12-01 19:50:28 +01:00
github-automation-metabase
13db04d7a0 Update generated docs (master) (#66300)
Co-authored-by: github-actions <github-actions@github.com>
2025-12-01 13:43:39 -05:00
Jeff Bruemmer
3ae80a41da don't run on draft prs (#66426) 2025-12-01 12:13:37 -05:00
Eric Normand
6414a9d73b Closed connection with many fields (#66051)
Fix legacy path (for snowflake with large number of fields)
2025-12-01 15:53:12 +00:00
Gabriel Moreno
19a79d96c1 Add gantoreno to team.json and github-slack-map.json (#66334)
* feat: add myself (gantoreno) to `team.json` and `github-slack-map.json`

* fix: correct username alphabetical order
2025-12-01 11:01:41 -04:00
Nemanja Glumac
637fa143ff Provide minimal sane defaults to the Cypress runner (#66398)
- If you decide to build the backend, you should run it
- There are no more derived options - everything is explicit
- Running Docker containers is a non-negotiable
    - Tests need these supporting services to run
    - If you really insist on not running them, either comment out those lines temporarily or do not use this script to set up the e2e environment
    - Because of this, there are no more custom envs `QA_DB_ENABLED` and `CYPRESS_QA_DB_MONGO`
- Alternative location (directory) for the e2e copy of the sample-application.db is now set to be `e2e/tmp` since it's already gitignored
2025-12-01 15:44:48 +01:00
Riley Thompson
8393eb2820 Use backfill specific event to prevent card revisions (#66401)
* use backfill specific event

* fix kondo

* add test

* fix config modules

* add migration

* remove migrations
2025-12-01 14:20:52 +00:00
Brad Anderson
e67f25b401 UXW-2209 Update datamodel tracking triggered_from (#66259)
* UXW-2209 Updates datamodel tracking triggered_from to be either "data_studio" or "admin" depending on where the metadata is being edited

* Updates e2e tests
2025-12-01 09:13:11 -05:00
Brad Anderson
39dfac795e UXW-2352 Fix issue where CopyCardForm resets when the destination collection is changed (#66275)
* UXW-2352 Fix issue where CopyCardForm resets when the destination collection is changed

* Unskips now-passing e2e tests

* Fix issue where Duplicate modal doesn't close on success
2025-12-01 09:12:42 -05:00
Egor Grushin
9bef191295 small ui fixes GDGT-1276 (#66406)
* fix GDGT-1276

* fix tests
2025-12-01 12:07:18 +00:00
Nathan Voxland
520de22c5e Fixed semantic-search filtering by collection (#66286) 2025-11-30 20:28:21 -06:00
Oleksandr Yakushev
67a99bb92d [perf] More efficient validator-cache old key eviction (#65890) 2025-11-29 20:03:33 +02:00
Nick Fitzpatrick
cbe07addba should show library (#66343)
* should show library

* tests

* more tests

* types

* uxw-2344

* I guess I forgot this?
2025-11-28 14:33:53 -04:00
Nemanja Glumac
4efe26824e Explicitly use the backend JAR for local Cypress runs (#66349)
The previous version of the build script (`build-for-test`) had a weird quirk that could be both confusing and dangerous. It was building a backend-only JAR in the same location and under same name as the full-blown, all-in-one Metabase JAR. This means that, by running Cypress locally, one could easily override the previously built healthy JAR. It's not catastrophic but it was confusing.

This PR makes it perfectly clear what we're doing, and there should be no conflicts between the JARs any longer.
2025-11-28 12:01:27 +00:00
Nemanja Glumac
b7ff644e78 Have a dedicated runner for SDK host/sample apps (#66378) 2025-11-28 10:09:03 +01:00
Nick Fitzpatrick
ccbda1251f updating watermark svg color and opacity (#66339)
* updating watermark svg color and opacity

* static viz development mark has same color and opacity as dynamic viz
2025-11-27 12:40:49 -04:00
Stas Gavrylov
a07c3b654e Incremental transforms (#65842)
* library collection search

* Fix e2e tests from group-16

* Fix a couple tests from group 42

* Fix e2e tests from group-17

* Fix e2e tests from group-18

* tests: add bulk publishing scenario

fix wrong collection link in case of root collection

* UXW-2315, UXW-2314

* UXW-2294

* more UXW-2315, UXW-2314

* more UXW-2315, UXW-2314

* correct collection types

* Remove Browsing Memory Feature

* Revert "Revert "Don't return library collections by default from APIs""

This reverts commit 814c49473b.

* Revert "Revert "Fixed null type filtering""

This reverts commit 25e0d78408.

* fetch full tree to have library collections visible

* show library in permissions

* Fixing tests

* fix infinite re-render in tree

* rewrite unit tests and fix max depth problem

* fix: publish property not validated in the tree view after table publishing

* Move bulk editing apis to enterprise (#65968)

* Make sidebar sticky

* test: bulk attribute actions for tables, schemas and dbs

* fix more unit tests

* Copy preview section tests

* Copy error handling tests

* Copy undos tests

* Update test

* test: update new ee endpoints paths

* Make new bulk table APIs ee-only (fe)
- Closes GDGT-1251

* Fix global H.DataModel.visit overrides

* Remove redundant cy.reload

* Remove redundant cy.reload

* add select/deselect tests

* use helper

* data picker using proper library endpoint. Fixing types I broke. Endless Shame

* Fix Tree skeleton resizing multiple times during loading
- Closes GDGT-1253

* Improve icon

* Fill content

* don't call getCollectionItems on database collection

* add search tests and support shift click in search

* default table publish collection

* fox: reset bulk form values when selection changes

* Fix e2e tests from group-19

* fix:  fix missing dependencies in useEffect gdgt-1245

* test: refactor test setup action order

* Fix e2e tests from group-20

* Fix e2e tests from group-22

* Fix e2e tests from group-23

* test: restore default db as the first step

* Kondo the kondo config

* default collections for metrics and models outside of data studio

* Move edit test to ee

* Fix list filtering now default is bronze

* Move bulk-edit-test to ee

* Fix table metadata for test

* Revert "Added `collection` argument to search"

This reverts commits:
- 21999e01
- b0f71c03ea
- 4fa0c3b422

* Fixed OSS loading of tables

* Fixed OSS loading of tables

* add tests for filtering

* Fix e2e tests from group 41 / joins-repros

* more tests

* Fix e2e tests from group-20

* Fix e2e tests from group-23

* Fix e2e tests from group-24

* Fix e2e tests from group-26

* Fix e2e tests from group-27

* Fix e2e tests from group-28

* Fix e2e tests from group-30

* constuct initial paths from library collections

* segments editor, hasEnabledNestedQueries

* Fix a couple more (something between groups 40 and 43)

* Fixed module config

* keyboard navigation

* Added library/tree API

* Fix some e2e tests from groups 40 and 42

* Fixing tests

* disable scoped search on the 'database collection', models.cy.spec should be passing now

* Fix e2e tests from group-33

* Minor cleanup

* Fix e2e tests from group-34

* Fixing tests

* Fix e2e tests from group 37 (except one depending on Recents tab)

* Starts fixing e2e tests from oss group

* cleanup

* wait to focus

* hide our analytics in the data studio

* Added library/tree API

* merge library and data studio

* change backend library flag validation to data-studio

* tidy things up

* Make bulk edit inputs non-clearable
- This prevents sending "empty" requests when clearing values
- And clearing does not really make sense here

* fix: test: table rescan and discard mocks are wrong

* fix: test: wrong mock in oss sync table schema

* Remove ^:parallel from bulk edit tests

They can contend and cause deadlocks

* fix: test: failure due to repeated mocking of same route

* test: refactor: cypress table tests

* Update e2e test

* Update e2e test

* Update e2e test

* fix browse nav section test

* Add missing token

* add check icon for published tables

* Removed unused import

* Updates some e2e tests from oss group, removes some now-invalid tests

* test: use default external db, skip transform test

* Starts fixing e2e tests from mongo group

* remove background from not active table in search

* specs

* Fix e2e tests from group-15

* hack fix ci while i'm on meetings

* scoped search is back

* Fix some e2e tests from group-32

* table picker fixes

* Fixed merge

* Fix e2e test from group-42

* merge fixes

* re-enable the recents tab on the data picker modal

* Avoid race condition on list-table-filtering-test

* fix embedding types

* mini picker unit tests

* Fixing tests

* ci, fixes

* fix library collection bugs

* cleanup data studio plugin

* fix lots of unit tests

* fix import

* fix

* Fixed unused import

* Fixed accidental #p

* ci

* revert util

* specs

* specs

* specs

* fix bug / bad type in SchemaFormSelect (#65995)

* Use actual anti join in GET /table query

* Remove old comments

* Activate token after restore

* test: unskip table metadata transform test

* test: fix search tables e2e test

* fix: test: selection in table picker

* Fix Source input disabled when filtering by Metabase transform
- Closes GDGT-1259

* test: fix: filter unused table

* Fix e2e test

* fix: test: datamodel toasts and errors

* Fix e2e test

* Fix e2e tests from group-9

* Fix flaky tests

* GDGT-1244: Fix DB tree virtualization (#66125)

* GDGT-1244: Fix tree virtualization. Replace top with translateY to improve performance

* GDGT-1244: Fix scroll bug. Refactor border styling

* bring back modeling empty state

* test: adjust publishing test

* Fix e2e test from group-22

* Fix e2e test from group-25

* fix allowing cross DB joins

* properly disable invalid items in MiniPicker

* Fix e2e test from group-26

* Fix straggler from oss group

* Starts fixing e2e tests from group-32

* unit test adjustments

* Fix remaining issue with e2e group 37

* fix item filtering

* Update Loki Snapshots

* add recent views to mini picker

* test recents and backparsing

* additional filtering test

* fix minipicker shows items it should not show

* Fixed :here in library API

* Fixed :here in library API

* UXW-2358 publishing outside of the data studio

* Fixed :here in library API

* snapshot

* Fix most e2e tests from group-32

* Lint fixes

* Fixed failing test

* revert fix

* Reapply "Added `collection` argument to search"

This reverts commit f28d9d5af9.

* Quick fix in CollectionPicker/utils.ts

* Fix flaky Remote Sync test (#65862)

* Clean up backend-test matrix (#66158)

* Fix timeseries value detection (#66161)

* Prevent driver tests (#66156)

Co-authored-by: Bryan Maass <bryan.maass@gmail.com>

* Fetch uberjar using a proper action (#66165)

* fix embedding column picking

* Trying CI with search_index.verified

* Fixed failing test

* Translate label

* Fixed failing test

* fix: published info not updated in the tree picker after deleting model

* fix: refactor: publish collection link tests

* Fixed failing test

* Fix remaining e2e tests from group-32

* FileUploadStatus unit test, quesiton reproductions

* create data studio plugin file

* fix hidden items some more

* Fix issue where confirmation modal closes then reopens again then closes again when you archive a dashboard

* fix dark mode

* UXW-2367

* UXW-2378

* Fixed merge issues

* this element is not visible because you can't even open incompatible sample database db

* Fix e2e test from group-14

* fix embedding data picker clicks

* filtering fixes for transforms

* UXW-2372

* update mini picker specs after a fix

* fix flaky join test

* Fixing in-place support for collections

* fix: cannot scroll search results

* ui: tweak search results checkbox spacing to match tree results

* fix: scroll position jump when entering field sort mode gdgt-1269

* Revert "fix: scroll position jump when entering field sort mode gdgt-1269"

This reverts commit bfecdec661.

* UXW-2279 Changes Data Studio's Glossary page background color to background-secondary

* Fix linters

* Fix e2e tests

* fixes for sqlserver

* fix driver changelog

* fix

* more fix

* fix: support params in bigq

* fix: inline params for sqlserver

* fix test

* fix: we do want the unique key

* fix: missing nil in test

* fix clickhouse

---------

Co-authored-by: Ryan Laurie <iethree@gmail.com>
Co-authored-by: Brad Anderson <brad@metabase.com>
Co-authored-by: Anderson <anderson@metabase.com>
Co-authored-by: Jakub Chodorowicz <jakub@chodorowicz.com>
Co-authored-by: Aleksandr Lesnenko <alxnddr@gmail.com>
Co-authored-by: Nathan Voxland <nathan@metabase.com>
Co-authored-by: Uladzimir Havenchyk <uladzimir@metabase.com>
Co-authored-by: Uladzimir Havenchyk <125459446+uladzimirdev@users.noreply.github.com>
Co-authored-by: Ngoc Khuat <qn.khuat@gmail.com>
Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>
Co-authored-by: Nick Fitzpatrick <nickfitz.582@gmail.com>
Co-authored-by: Dan Stone <wotbrew@gmail.com>
Co-authored-by: Sloan Sparger <sloansparger@users.noreply.github.com>
Co-authored-by: Aleksandr Lesnenko <alxnddr@users.noreply.github.com>
Co-authored-by: Metabase Automation <github-automation@metabase.com>
Co-authored-by: John Swanson <john.swanson@metabase.com>
Co-authored-by: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>
Co-authored-by: Denis Berezin <denis.berezin@metabase.com>
Co-authored-by: dpsutton <dan@dpsutton.com>
Co-authored-by: Bryan Maass <bryan.maass@gmail.com>
Co-authored-by: Nicola Mometto <nicola.mometto@metabase.com>
2025-11-27 15:52:19 +00:00
Anderson
e80478b006 Prevent database sync status element to overlap pagination (#66225) 2025-11-27 11:16:01 -03:00
Anderson
c8d87bdf7b Do not allow setting up remote sync if git url is not set (#66281) 2025-11-27 11:14:41 -03:00
Anderson
e2ec2f6aff Fix broken PDF export layout due to CSP violation for inline styles (#66337) 2025-11-27 11:14:20 -03:00
Nick Fitzpatrick
ce9ac84ecc Update selector for loki test in Palette.stories (#66333) 2025-11-27 10:07:03 -04:00
Nemanja Glumac
66b5043940 Make file-path triggers more robust (#66311)
This pull request refactors and streamlines the configuration for CI workflows and file path groupings in .github/file-paths.yaml and updates related workflow logic in .github/workflows/run-tests.yml. The changes focus on consolidating shared configuration, improving maintainability, and removing redundant or unused path groups.
2025-11-27 14:01:33 +01:00
Ngoc Khuat
2b607f547a fix false positive logs (#66325) 2025-11-27 12:50:47 +00:00
Jakub Chodorowicz
0400e1bf07 fix: scroll position jump when entering field sort mode gdgt-1269 (#66318)
* fix: scroll position jump when entering field sort mode gdgt-1269

* test: fix failing unit test selector

* fix: e2e test selectors

* fix: test selectors for sync button

* test: adjust sync button selector

* test: fix semantic selector

* Update enterprise/frontend/src/metabase-enterprise/data-studio/data-model/components/TableSection/TableSection.tsx

Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>

---------

Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>
2025-11-27 10:48:43 +01:00
appleby
df5abbd1b9 Add :database_type to metabot tools that return column metadata (#66302)
* Add :database_type to metabot tools that return column metadata

Add :database_type to metabot tools that return column metadata in order to give metabot information about the real
database type when generating SQL.

Examples of places the :database_type now appears:

- :used_tables in :user_is_viewing context
- {table,card,metric}-details
- get-query-details
- enhanced-database-tables

* Fix test after rebase onto #66271

Fix get-table-details-database-type-test after rebase (1) use new field-id formatting (2) get-table-details no longer returns implicitly-joinable fields
in the top-level `:fields`.
2025-11-26 23:32:44 +00:00
Egor Grushin
99fa786ec8 fix: flake test number 29943 (#66283)
* fix: flake test number 29943

* mark moveDnDKitElement as deprecated, fix singleused constant
2025-11-26 22:08:24 +00:00
Noah Moss
b561b5c8b9 Revised approach to related_tables and consistent field IDs for implicitly-joined fields (#66271)
* More flexible approach to resolving columns from metabot field_ids

* fix one field-stats-test

* fix field-stats-test

* support nano-ids in field ids (?)

* remove some dead code

* Exclude implicitly joinable fields when fetching cols for table

* try switching field format to use dash

* fix field IDs in a number of tests

* Kondo

* add some unit tests for new field parsing & column lookup helper fns

* Fix more tests

* Fix more tests

* fix regex

* New approach -- use wide field IDs in related_tables and add a related_by field for each table

* Fix some tests

* remove unneeded table

* cleanup, new test

* Revert to passing in & matching on expected prefix

* Address tyler's comments

* accept a regex for the prefix as well

* add back small malli group-by fix from the last PR - removed unintentionally during revision
2025-11-26 15:48:30 -05:00
Nathan Voxland
f2e8e294f8 Add warning for when mismatch in serdes version during loading (#66140) 2025-11-26 14:30:15 -06:00
Riley Thompson
8257c072a9 Revert "Bump com.clickhouse/clickhouse-jdbc from 0.8.4 to 0.9.2 (#64168)" (#66326)
This reverts commit 31f76f5856.
2025-11-26 17:59:28 +00:00
Denis Berezin
08770c8e8f UXW-1778 remove chart hover effects when exporting to png (#66200)
* UXW-1778 remove chart hover effects when exporting to png

* Fix typing and unit tests

* review fix
2025-11-26 19:02:51 +03:00
Nemanja Glumac
4ef178f794 Support building an uberjar with a custom filename (#66315)
* Make uberjar (artifact) file name configurable via env var

Add the ability to customize the output filename for the uberjar build
via the MB_JAR_FILENAME environment variable. This allows backend-only
test builds to use a separate filename (e.g., metabase-backend.jar)
to avoid overwriting the regular all-in-one metabase.jar.
2025-11-26 15:45:19 +00:00
Gabriel Moreno
89443cda94 UXW-2228 Properly mention available subscription & alert channels for non-admins (#66273)
* fix: add missing channels to copy & rendering logic

Mentioned webhooks and Slack where necessary to stay consistent with the
admin UI

* fix: standardize lowercase 'admin' & prefer 'email' over 'SMTP'

* fix: remove extra comma on wording

* test: adjust e2e test assertions

* test: add `DashboardSubscriptionMenuItem.unit.spec.tsx`

* test: extract single case from `describe` block

* test: fix subscriptions e2e case & text lookup on alert spec
2025-11-26 15:04:34 +00:00
Edward Paget
99fd1809cb Get user attributes from attributes map (#66274)
* Get user attributes from attributes map

* fixup! e2e test
2025-11-26 14:38:33 +00:00
Braden Shepherdson
868fb6da0a [MBQL lib] Allow string literals as arg to aggregations like :max (#66220)
Fixes #66199.

`metabase.legacy-mbql.schema`, now used for normalizing MBQL 4 in
place of the old bespoke normalization in earlier versions, regressed in
this weird but legitimate use case: Writing a custom aggregation like
`MAX("String Literal")`.

That's an odd thing to do, but it can be useful to provide a label in an
aggregated query. This is the MBQL equivalent of
`(SELECT ..., 'A' as label FROM ...) UNION ALL (SELECT ..., 'B' as label ...)`
2025-11-26 13:28:57 +00:00
Nicolò Pretto
8a56f6b3bb update file path to include tsx extension for component tests (#66254) 2025-11-26 11:00:31 +01:00
github-automation-metabase
384d24a75b Bump org.clojure/tools.cli from 1.1.230 to 1.2.245 (#64159)
Inspect dependency changes here: https://github.com/clojure/tools.cli/blob/v1.2.245/CHANGELOG.md

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-26 00:04:43 +00:00
Cam Saul
e94dd16252 Split Redshift driver tests into two jobs (#66289) 2025-11-25 15:39:13 -08:00
Fraser
561d578043 Fix eslint cache (#66066) 2025-11-26 12:29:56 +13:00
github-automation-metabase
6f778c9269 Bump com.google.guava/guava from 33.4.8-jre to 33.5.0-jre (#63796)
Inspect dependency changes here:

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
Co-authored-by: bryan <bryan.maass@gmail.com>
2025-11-25 23:03:44 +00:00
bryan
9b93bfe279 Only real app-dbs should print setup instructions (#66255) 2025-11-25 23:03:06 +00:00
Nemanja Glumac
dc89b2bbeb Decouple the cleanup logic from running Cypress (#66236)
This pull request refactors the Cypress runner utility to simplify error handling and improve consistency in how test failures are reported. The main change is that runCypress now throws errors on test failures instead of relying on an external exit or cleanup function, which streamlines its usage across different scripts.

This ensures consistent error propagation and simplifies the control flow for callers.
2025-11-25 23:10:02 +01:00
github-automation-metabase
538ebb5f08 Bump cheshire/cheshire from 6.0.0 to 6.1.0 (#63217)
* Bump cheshire/cheshire from 6.0.0 to 6.1.0

Inspect dependency changes here: https://github.com/dakrone/cheshire/blob/6.1.0/ChangeLog.md

* update timestamps to match new cheshire parsing

---------

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
Co-authored-by: Bryan Maass <bryan.maass@gmail.com>
2025-11-25 22:02:13 +00:00
Nemanja Glumac
e4325d4e02 Always pass the input conditions to sdk jobs (#66269) 2025-11-25 22:56:17 +01:00
bryan
b453baf5ed Upgrades mage run-tests (#66108) 2025-11-25 21:42:28 +00:00
github-automation-metabase
773a588692 Bump org.apache.commons/commons-lang3 from 3.18.0 to 3.19.0 (#64150)
Inspect dependency changes here:

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
Co-authored-by: bryan <bryan.maass@gmail.com>
2025-11-25 21:38:24 +00:00
github-automation-metabase
31f76f5856 Bump com.clickhouse/clickhouse-jdbc from 0.8.4 to 0.9.2 (#64168)
Inspect dependency changes here:

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
Co-authored-by: bryan <bryan.maass@gmail.com>
2025-11-25 21:35:15 +00:00
github-automation-metabase
81f10bdb3c Update generated docs (master) (#66228)
Co-authored-by: github-actions <github-actions@github.com>
2025-11-25 21:34:41 +00:00
github-automation-metabase
3dcfbce301 Bump org.apache.calcite.avatica/avatica from 1.26.0 to 1.27.0 (#64402)
Inspect dependency changes here: https://github.com/apache/calcite-avatica/compare/avatica-1.26.0-rc0...avatica-1.27.0-rc0

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-25 21:17:19 +00:00
appleby
5c10e2d7a3 Add :database_engine to metabot table-details and card-details (#66227)
These tools already included :database_id in the results; we now include the :database_engine as well, to give metabot
a reminder about which SQL dialect it should generate.
2025-11-25 12:03:13 -08:00
github-automation-metabase
53f51fa289 Bump org.apache.arrow/arrow-memory-netty from 17.0.0 to 18.3.0 (#64401)
* Bump org.apache.arrow/arrow-memory-netty from 17.0.0 to 18.3.0

Inspect dependency changes here:

* Upgrade arrow-memory-core to version 18.3.0

Updated the version of arrow-memory-core from 17.0.0 to 18.3.0.

* Consolidate changes

* Fix formatting

---------

Co-authored-by: bryan <bryan.maass@gmail.com>
Co-authored-by: Luis Paolini <paoliniluis@gmail.com>
Co-authored-by: Cam Saul <github@camsaul.com>
Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-25 19:41:46 +00:00
github-automation-metabase
4280e1af7a Bump org.jsoup/jsoup from 1.21.1 to 1.21.2 (#62652)
Inspect dependency changes here: https://github.com/jhy/jsoup/blob/jsoup-1.21.2/CHANGES.md

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
Co-authored-by: bryan <bryan.maass@gmail.com>
2025-11-25 19:31:30 +00:00
Phoomparin Mano
0a2255c36f ci(sdk): only setup specific enterprise plugins in sdk unit tests as needed (#66238) 2025-11-26 02:03:22 +07:00
bryan
e1e8d53234 add deprecation support to defendpoint dox-gen (#66053) 2025-11-25 18:35:00 +00:00
Nemanja Glumac
cca02fcf31 Fix JAR health check condition logic (#66266)
Addresses this finding by the Claude code review:
https://github.com/metabase/metabase/pull/66237#discussion_r2560704357
2025-11-25 19:23:11 +01:00
Noah Moss
eb4a9f528e Move audit installation before search initialization again (#66222) 2025-11-25 12:02:01 -05:00
Nemanja Glumac
6e30ce468c Run JAR health check only on master and release branches (#66237) 2025-11-25 17:43:27 +01:00
Alexander Polyankin
96eac2d9da Data Studio (#65281)
* Fix some e2e tests from group-9

* test: add bulk sync action e2e test

* fix column selection

* Fixed module config

* Fix a few e2e tests from oss group

* Fix e2e tests from groups 46 and 47

* Fix e2e tests from groups 44 and 45

* Fix group-3 straggler, some of group-8

* Potentially disastrous change (increases item-picker-level of SchemaList and TableList) to fix test in group-8

* Fix group-6 straggler, some more of group-8

* Updates some more e2e tests from group-9 (some actual failures left)

* Fix e2e tests from group-14

* do enterprise code correctly

* library collection search

* Fix e2e tests from group-16

* Fix a couple tests from group 42

* Fix e2e tests from group-17

* Fix e2e tests from group-18

* tests: add bulk publishing scenario

fix wrong collection link in case of root collection

* UXW-2315, UXW-2314

* UXW-2294

* more UXW-2315, UXW-2314

* more UXW-2315, UXW-2314

* correct collection types

* Remove Browsing Memory Feature

* Revert "Revert "Don't return library collections by default from APIs""

This reverts commit 814c49473b.

* Revert "Revert "Fixed null type filtering""

This reverts commit 25e0d78408.

* fetch full tree to have library collections visible

* show library in permissions

* Fixing tests

* fix infinite re-render in tree

* rewrite unit tests and fix max depth problem

* fix: publish property not validated in the tree view after table publishing

* Move bulk editing apis to enterprise (#65968)

* Make sidebar sticky

* test: bulk attribute actions for tables, schemas and dbs

* fix more unit tests

* Copy preview section tests

* Copy error handling tests

* Copy undos tests

* Update test

* test: update new ee endpoints paths

* Make new bulk table APIs ee-only (fe)
- Closes GDGT-1251

* Fix global H.DataModel.visit overrides

* Remove redundant cy.reload

* Remove redundant cy.reload

* add select/deselect tests

* use helper

* data picker using proper library endpoint. Fixing types I broke. Endless Shame

* Fix Tree skeleton resizing multiple times during loading
- Closes GDGT-1253

* Improve icon

* Fill content

* don't call getCollectionItems on database collection

* add search tests and support shift click in search

* default table publish collection

* fox: reset bulk form values when selection changes

* Fix e2e tests from group-19

* fix:  fix missing dependencies in useEffect gdgt-1245

* test: refactor test setup action order

* Fix e2e tests from group-20

* Fix e2e tests from group-22

* Fix e2e tests from group-23

* test: restore default db as the first step

* Kondo the kondo config

* default collections for metrics and models outside of data studio

* Move edit test to ee

* Fix list filtering now default is bronze

* Move bulk-edit-test to ee

* Fix table metadata for test

* Revert "Added `collection` argument to search"

This reverts commits:
- 21999e01
- b0f71c03ea
- 4fa0c3b422

* Fixed OSS loading of tables

* Fixed OSS loading of tables

* add tests for filtering

* Fix e2e tests from group 41 / joins-repros

* more tests

* Fix e2e tests from group-20

* Fix e2e tests from group-23

* Fix e2e tests from group-24

* Fix e2e tests from group-26

* Fix e2e tests from group-27

* Fix e2e tests from group-28

* Fix e2e tests from group-30

* constuct initial paths from library collections

* segments editor, hasEnabledNestedQueries

* Fix a couple more (something between groups 40 and 43)

* Fixed module config

* keyboard navigation

* Added library/tree API

* Fix some e2e tests from groups 40 and 42

* Fixing tests

* disable scoped search on the 'database collection', models.cy.spec should be passing now

* Fix e2e tests from group-33

* Minor cleanup

* Fix e2e tests from group-34

* Fixing tests

* Fix e2e tests from group 37 (except one depending on Recents tab)

* Starts fixing e2e tests from oss group

* cleanup

* wait to focus

* hide our analytics in the data studio

* Added library/tree API

* merge library and data studio

* change backend library flag validation to data-studio

* tidy things up

* Make bulk edit inputs non-clearable
- This prevents sending "empty" requests when clearing values
- And clearing does not really make sense here

* fix: test: table rescan and discard mocks are wrong

* fix: test: wrong mock in oss sync table schema

* Remove ^:parallel from bulk edit tests

They can contend and cause deadlocks

* fix: test: failure due to repeated mocking of same route

* test: refactor: cypress table tests

* Update e2e test

* Update e2e test

* Update e2e test

* fix browse nav section test

* Add missing token

* add check icon for published tables

* Removed unused import

* Updates some e2e tests from oss group, removes some now-invalid tests

* test: use default external db, skip transform test

* Starts fixing e2e tests from mongo group

* remove background from not active table in search

* specs

* Fix e2e tests from group-15

* hack fix ci while i'm on meetings

* scoped search is back

* Fix some e2e tests from group-32

* table picker fixes

* Fixed merge

* Fix e2e test from group-42

* merge fixes

* re-enable the recents tab on the data picker modal

* Avoid race condition on list-table-filtering-test

* fix embedding types

* mini picker unit tests

* Fixing tests

* ci, fixes

* fix library collection bugs

* cleanup data studio plugin

* fix lots of unit tests

* fix import

* fix

* Fixed unused import

* Fixed accidental #p

* ci

* revert util

* specs

* specs

* specs

* fix bug / bad type in SchemaFormSelect (#65995)

* Use actual anti join in GET /table query

* Remove old comments

* Activate token after restore

* test: unskip table metadata transform test

* test: fix search tables e2e test

* fix: test: selection in table picker

* Fix Source input disabled when filtering by Metabase transform
- Closes GDGT-1259

* test: fix: filter unused table

* Fix e2e test

* fix: test: datamodel toasts and errors

* Fix e2e test

* Fix e2e tests from group-9

* Fix flaky tests

* GDGT-1244: Fix DB tree virtualization (#66125)

* GDGT-1244: Fix tree virtualization. Replace top with translateY to improve performance

* GDGT-1244: Fix scroll bug. Refactor border styling

* bring back modeling empty state

* test: adjust publishing test

* Fix e2e test from group-22

* Fix e2e test from group-25

* fix allowing cross DB joins

* properly disable invalid items in MiniPicker

* Fix e2e test from group-26

* Fix straggler from oss group

* Starts fixing e2e tests from group-32

* unit test adjustments

* Fix remaining issue with e2e group 37

* fix item filtering

* Update Loki Snapshots

* add recent views to mini picker

* test recents and backparsing

* additional filtering test

* fix minipicker shows items it should not show

* Fixed :here in library API

* Fixed :here in library API

* UXW-2358 publishing outside of the data studio

* Fixed :here in library API

* snapshot

* Fix most e2e tests from group-32

* Lint fixes

* Fixed failing test

* revert fix

* Reapply "Added `collection` argument to search"

This reverts commit f28d9d5af9.

* Quick fix in CollectionPicker/utils.ts

* Fix flaky Remote Sync test (#65862)

* Clean up backend-test matrix (#66158)

* Fix timeseries value detection (#66161)

* Prevent driver tests (#66156)

Co-authored-by: Bryan Maass <bryan.maass@gmail.com>

* Fetch uberjar using a proper action (#66165)

* fix embedding column picking

* Trying CI with search_index.verified

* Fixed failing test

* Translate label

* Fixed failing test

* fix: published info not updated in the tree picker after deleting model

* fix: refactor: publish collection link tests

* Fixed failing test

* Fix remaining e2e tests from group-32

* FileUploadStatus unit test, quesiton reproductions

* create data studio plugin file

* fix hidden items some more

* Fix issue where confirmation modal closes then reopens again then closes again when you archive a dashboard

* fix dark mode

* UXW-2367

* UXW-2378

* Fixed merge issues

* this element is not visible because you can't even open incompatible sample database db

* Fix e2e test from group-14

* fix embedding data picker clicks

* filtering fixes for transforms

* UXW-2372

* update mini picker specs after a fix

* fix flaky join test

* Fixing in-place support for collections

* fix: cannot scroll search results

* ui: tweak search results checkbox spacing to match tree results

* fix: scroll position jump when entering field sort mode gdgt-1269

* Revert "fix: scroll position jump when entering field sort mode gdgt-1269"

This reverts commit bfecdec661.

* UXW-2279 Changes Data Studio's Glossary page background color to background-secondary

---------

Co-authored-by: Nathan Voxland <nathan@metabase.com>
Co-authored-by: Brad Anderson <brad@metabase.com>
Co-authored-by: Jakub Chodorowicz <jakub@chodorowicz.com>
Co-authored-by: Ryan Laurie <iethree@gmail.com>
Co-authored-by: Anderson <anderson@metabase.com>
Co-authored-by: Aleksandr Lesnenko <alxnddr@gmail.com>
Co-authored-by: Uladzimir Havenchyk <uladzimir@metabase.com>
Co-authored-by: Uladzimir Havenchyk <125459446+uladzimirdev@users.noreply.github.com>
Co-authored-by: Ngoc Khuat <qn.khuat@gmail.com>
Co-authored-by: Kamil Mielnik <kamil@kamilmielnik.com>
Co-authored-by: Nick Fitzpatrick <nickfitz.582@gmail.com>
Co-authored-by: Dan Stone <wotbrew@gmail.com>
Co-authored-by: Sloan Sparger <sloansparger@users.noreply.github.com>
Co-authored-by: Stas Gavrylov <stas@metabase.com>
Co-authored-by: Aleksandr Lesnenko <alxnddr@users.noreply.github.com>
Co-authored-by: Metabase Automation <github-automation@metabase.com>
Co-authored-by: John Swanson <john.swanson@metabase.com>
Co-authored-by: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>
Co-authored-by: Denis Berezin <denis.berezin@metabase.com>
Co-authored-by: dpsutton <dan@dpsutton.com>
Co-authored-by: Bryan Maass <bryan.maass@gmail.com>
2025-11-25 08:09:59 -08:00
Gabriel Moreno
15bb72ee66 fix: anchor table info popover to bottom (#66226)
Since `position` was set to `top`, the popover had little space to
expand upwards, and the box was cut-off before reaching the anchor
point.
2025-11-25 14:15:12 +00:00
Stas Gavrylov
ce0232662d GDGT-1252: Respect show mini bar chart setting in list view (#66012)
* GDGT-1252: Make list view consider mini-bar-chart setting

* GDGT-1252: Fix incorrect model settings update when changing columns settings

* GDGT-1252: e2e test

* GDGT-1252: Fix unit test for ListViewItem

* GDGT-1252: Address PR comments. Minor refactoring

* GDGT-1252: Refactor DatasetEditor to get rid of modelSettings hack

* GDGT-1252: Update e2e test to cover settings persistence

* Update Loki Snapshots

* Revert Loki update

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-11-25 12:48:09 +02:00
Nemanja Glumac
076267ed7c chore: Upgrade nextjs to resolve dependabot alert (#66203) 2025-11-25 10:08:00 +01:00
Dennis Schridde
a7f3165348 Fix purchase page for paid Metabase AI add-on for non-store users (#66086)
### Description

Missing billing information is treated as an error for purposes of
displaying the purchase page with prices.  Non-store users cannot
retrieve billing information.  Thus, previously, they would always see
an error page: "Error fetching information about available add-ons."
With this change, they see the "Please ask a Metabase Store Admin" page
as intended.

We achieve this by splitting the page content for store users from that
of non-store users.  Only the former needs to load data (billing and
add-on information), so only that page needs `LoadingAndErrorWrapper`.
For store users we show no dynamic content that could fail to load
(apart from a store user's email address, which we gracefully omit if
it is missing).

### How to verify

1. Ensure you have a token with the `offer-metabase-ai-tiered`
   feature, but without the `metabot-v3` and `offer-metabase-ai`
   features.
2. As a Metabase user with an email address that *does not* match any
   of the token's organization's store user email addresses, navigate
   to `/admin/metabot` and see "Please ask a Metabase Store Admin".
3. As a Metabase user with an email address that *does* match any
   of the token's organization's store user email addresses, navigate
   to `/admin/metabot` and see the purchase page with tier selector.

### Checklist

- [x] Tests have been added/updated to cover changes in this PR

Fixes: 2b76c38e1f
Closes: https://metaboat.slack.com/archives/C07RMUQ0GE5/p1763644357893079
2025-11-25 02:37:44 +01:00
Nemanja Glumac
1881164422 Improve how skipped SDK tests are handled (#66211) 2025-11-24 23:29:37 +01:00
Nemanja Glumac
81ba716093 Check for project requirements (#66192)
This PR adds a non-destructive dev script whose only job is to detect and report on your local development environment setup.

## What it does

**`./bin/dev-requirements`** detects:
  - Version managers:
      -  nvm, fnm, n (Node.js version managers)
      - volta, asdf, mise (multi-language support)
      - jenv, sdkman (Java version managers)
  - Installed development tools and their versions
  - Whether your setup meets Metabase's requirements

It cross-references detected versions against project configuration files:
  - Node.js version from `.nvmrc`
  - Clojure version from `deps.edn`
  - Java 21 Temurin distribution requirement

## What it doesn't do

  - No installations
  - No modifications
  - No assumptions about your preferences

The script is purely informational - it shows you what you have, what's required, and recommends mise for version management. Perfect for new contributors or when troubleshooting setup issues.
2025-11-24 22:09:43 +01:00
Nemanja Glumac
f90fbb06ce Delete now unused ci-test-config.json (#66189) 2025-11-24 21:23:35 +01:00
Brad Anderson
76cf73dde5 Fix #65501 - Resets search back to first page when filters change (#66104) 2025-11-24 15:07:39 -05:00
Noah Moss
74b8adabe6 Two quality-of-life improvements for @-mentions (#66131)
* QoL improvements for @-mentions

* Add a unit test for new tab click behavior
2025-11-24 19:30:31 +00:00
Riley Thompson
7d7595996c Add snowflake collate expression (#65944)
* get collate working

* add collate test

* add changelog

* oragnize collate code

* fix driver changelog typo
2025-11-24 14:09:59 -05:00
Riley Thompson
8f23a5b725 Cancel jobs in bigquery (#66054)
* cancel bigquery jobs

* move .cancel to promise handling

* wrap .cancel in try catch finally

* use getqueryresults instead of .query
2025-11-24 19:07:31 +00:00
Edward Paget
05b294f47a feat: use boolean flag for remote-sync status (#66048)
* feat: use boolean flag for remote-sync status

It turns out type is too overloaded to have a 'remote-synced' collection
type. This is behavior that we might want to share around other typed
collections, so this migrates us to use a boolean column for this value instead.

* fixup! e2e test find synced collection

* fixup! e2e collection fixture has correct values

* fixup! make sure flag is set on insert/update
2025-11-24 12:16:43 -06:00
Nemanja Glumac
cb37ce8108 chore: Upgrade zx to resolve dependabot alert (#66207)
Should resolve
https://github.com/metabase/metabase/security/dependabot/275
2025-11-24 18:40:46 +01:00
Denis Berezin
0b42ad89a9 Fix trend viz dates diff calculation for a year unit (#65985) 2025-11-24 18:34:33 +03:00
dpsutton
857bdadd45 bump databricks (#66123)
* bump databricks

This moves over to a thin jar (or regular jar) which provides jdbc
classes and lists its dependencies. We can now bump or pin as we
like. The previous versions were uberjars that had their dependencies
packaged inside.

```clojure
clj -Sdeps '{:deps {com.databricks/databricks-jdbc-thin {:mvn/version "3.0.5"}}}'
Clojure 1.12.1
user=> (Class/forName "com.databricks.client.jdbc.Driver")
com.databricks.client.jdbc.Driver
```

```clojure
clj -Xdeps tree :extra '{:deps {com.databricks/databricks-jdbc-thin {:mvn/version "3.0.5"}}}'
org.clojure/clojure 1.12.1
  . org.clojure/spec.alpha 0.5.238
  . org.clojure/core.specs.alpha 0.4.74
com.databricks/databricks-jdbc-thin 3.0.5
  . com.databricks/databricks-sdk-java 0.69.0
    X org.slf4j/slf4j-api 2.0.9 :older-version
    . org.apache.commons/commons-configuration2 2.11.0 :newer-version
      X org.apache.commons/commons-lang3 3.14.0 :older-version
      . org.apache.commons/commons-text 1.12.0
        X org.apache.commons/commons-lang3 3.14.0 :older-version
      . commons-logging/commons-logging 1.3.2 :newer-version
    X com.fasterxml.jackson.core/jackson-databind 2.15.2 :older-version
...
```

contrasted with

```clojure
❯ clj -Xdeps tree :extra '{:deps {com.databricks/databricks-jdbc {:mvn/version "3.0.1"}}}'
org.clojure/clojure 1.12.1
  . org.clojure/spec.alpha 0.5.238
  . org.clojure/core.specs.alpha 0.4.74
com.databricks/databricks-jdbc 3.0.1
```

* bump to run drivers

* include test namespace change to trigger driver tests
2025-11-24 09:14:19 -06:00
Nemanja Glumac
eed6736230 Fix uberjar fetching for SDK host-apps (#66194) 2025-11-24 15:53:22 +01:00
Noah Moss
144b0b33f8 Move audit installation after search init; change some logs to debug (#66045)
* Move audit installation after search init; change some logs to debug

* change another warn to debug
2025-11-24 14:48:35 +00:00
Sébastien
dcca252247 Closes EMB-997 add a reset function to plugins (#65958)
* reorg

* added reinit fns to oss plugins

* ಠ_ಠ

* Added doc and eslint to prevent import of individual reinitialize functions

* added short doc to reinitialize functions to indicate they're internal
2025-11-24 15:15:15 +01:00
Denis Berezin
a183e8b5b4 Add translation for boolean dash filter value (#66050)
* Add translation for boolean dash filter value

* Fix CI
2025-11-24 16:55:44 +03:00
Edward Paget
3b837a15a0 fix: google auth returns given_name/family_name (#66151)
this was incorrectly using first_name/last_name. This also updates the
existing mocks to return the correct fields.
2025-11-24 13:01:08 +00:00
Nemanja Glumac
6679039b45 Revert "Pin the NodeJS version to the version 22 (#66152)" (#66187)
This reverts commit 58867cac0b.
2025-11-24 12:37:57 +01:00
Nemanja Glumac
58867cac0b Pin the NodeJS version to the version 22 (#66152) 2025-11-24 11:49:49 +01:00
Nemanja Glumac
2e4b7adbcb Parallelize embedding SDK package and uberjar builds (#66122) 2025-11-24 11:47:29 +01:00
Fraser
5aeffcf173 Skip BarChart Watermark loki (#66176) 2025-11-24 10:30:48 +00:00
Nemanja Glumac
721db4d40f Fetch uberjar using a proper action (#66165) 2025-11-21 23:58:57 +01:00
dpsutton
442fd726a3 Prevent driver tests (#66156)
Co-authored-by: Bryan Maass <bryan.maass@gmail.com>
2025-11-21 15:36:19 -07:00
Denis Berezin
9e65cc60bf Fix timeseries value detection (#66161) 2025-11-21 23:59:43 +03:00
Nemanja Glumac
44ab6decf0 Clean up backend-test matrix (#66158) 2025-11-21 20:40:40 +01:00
John Swanson
8b369333c3 Fix flaky Remote Sync test (#65862) 2025-11-21 11:29:00 -08:00
Nicolò Pretto
c9e602db2f chore(sdk): remove excessive logs in sdk fixup script (#66133) 2025-11-21 18:19:38 +01:00
Nemanja Glumac
b1fb103a3f Remove redundant static-viz files changed condition (#66138) 2025-11-21 17:41:36 +01:00
Jeff Bruemmer
b631ee88a4 docs - fix docstring (#66134)
* doc string

* edit
2025-11-21 11:39:49 -05:00
Riley Thompson
2df87d3a7f Add empty state to native query DB dropdown (#66090)
* add global search to db dropdown

* Add tests
2025-11-21 10:04:44 -05:00
Egor Grushin
f486c415f9 chore: Add egorgrushin as a team member (#66043)
* chore: Adds egorgrushin to ~/.github/team.json and ~/release/github-slack-map.json.

* chore: fixed the usernames order
2025-11-21 15:02:00 +00:00
Nemanja Glumac
ba5804041b Consolidate embedding CI workflows (#66075) 2025-11-21 11:40:00 +00:00
Nemanja Glumac
9d6564cdaf Fix backend cache paths (#66103) 2025-11-21 11:41:08 +01:00
Sébastien
591b453e4c Closes EMB-1037 preview_embed endpoint for filter search (#66077) 2025-11-21 09:11:52 +01:00
Sébastien
5d087d0d18 Closes EMB-1038 wrong endpoint for embed maps preview (#66063) 2025-11-21 09:11:43 +01:00
Riley Thompson
719ebd0a7b Fix caching of postgres domains in arrays (#66059)
* custom nippy handling for pgobject

* Add domain caching test

* simplify test comparison
2025-11-20 23:22:50 +00:00
Fraser
ff6ec328f3 Create use-page-title hook and remove SetTitle Hoc (#65782) 2025-11-21 10:59:40 +13:00
dpsutton
78978219a6 minimal tests to be run when the label is minimal-tests (#66024)
* minimal tests to be run when the label is `minimal-tests`

* include enterprise tests, fix syntax

* bump CI

* don't fail if label is absent
2025-11-20 15:31:11 -06:00
Jeff Bruemmer
7c8a8f3694 docs - update docs workflow (#66096)
* update docs workflow

* update perms

* more perms

* perms to delete pending reviews

* review deletion

* delete comments

* update skill
2025-11-20 16:23:51 -05:00
Jeff Bruemmer
45abe078f9 docs - supporting text (#66088)
* supporting text

* image

* edits
2025-11-20 15:06:42 -05:00
Jeff Bruemmer
82b95611cf docs - light weeding (#66023)
* spelling

* docstring
2025-11-20 14:21:28 -05:00
Noah Moss
f04fb1bff2 Fix template tag parsing for model references in transforms generated by metabot (#65630)
* Try to fix model references in transforms generated by metabot

* Add an e2e test

* move test later in file

* simplify implementation

* address bot comments

* add comment
2025-11-20 14:10:41 -05:00
Jeff Bruemmer
f200fbe20c docs - lychee action version (#66091)
* lychee action version

* bump versions
2025-11-20 14:09:01 -05:00
Jeff Bruemmer
3413313d3a docs - links workflow (#66087) 2025-11-20 13:46:09 -05:00
Nicolò Pretto
b5c0d93f8e chore(sdk): fix sdk storybook (#66078)
* chore(sdk): fix sdk storybook

* use rootRepoPath for appConfig
2025-11-20 18:24:13 +01:00
Edward Paget
71f7cbc41b fix: handle invalid email address in auth-identity (#66022)
...migrations.

Handles cases where emails were set to longer than the valid length of
254 bytes. Those emails would fail on this migration previously. We're
not currently using auth-identity to lookup email addresses so this
won't cause any incorrect behavior, but also if any emails like this
exist they weren't valid anyway.

Also sets the validCheckSum to ANY like some other SQL migrations to
handle cases where this migration has already been run successfully, as
on stats.
2025-11-20 10:59:43 -06:00
github-automation-metabase
c2619a5036 Auto-update documentation for master (#66056)
* Update generated docs (master)

* Update docs/configuring-metabase/environment-variables.md

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2025-11-20 14:24:59 +00:00
Nicolò Pretto
e4728d22b8 chore(sdk,ci): fix stress tests for sdk tests (#66065)
* chore(sdk,ci): fix stress tests for sdk tests

* fix baseUrl, cypress explodes if we pass it in ct test config
2025-11-20 11:37:10 +01:00
Timofey Kachalov
2d1b6c4a02 refactor(embed-js): Move EmbedJS + EmbedJS wizard files to OSS folder (#65973) 2025-11-20 14:32:30 +04:00
Ngoc Khuat
b8eb7d65f9 Add bottom padding for Attach results as files section (#62483) 2025-11-20 10:25:16 +01:00
Anderson
28b5fb79f1 Collect customer consent to grant instance access to Metabase success engineers (#65701)
* feat: add api for manage support access grants

* Setup frontend endpoint logic and start work on UI

* Implement create access grant; revoke; UI clean up

* Move section to tools > help / Adjust main UI

* feat: migration to new auth-identity module

* Fix schema migration tests

* Adjust backend fields structure on the backend / Update types and table in the UI

* Implement invitation mechanism and auth provider

* Create a route for the access grant modal

* Fix fe types / Fix clj spaces

* Add some test placeholders

* Remove stray #p

* Add missing index

* refix broken migration

* Change the way we temporarily make the new feature always enabled

* Add email sending on grant creation

* Add login and tests

* Make auths expirable

* Remove extraneous test

* Fix bad syntax in test

* Split two column migration into two migrations

* Fix test syntax issue

* Better expires at test

* Create e2e tests / Split troubleshooting.cy.spec and move to ts

* Add fe unit tests

* Add fe unit tests

* Fix kondo

* Fix config file and settings require

* Revert added disallowed exported namespaces

* Correctly test expiration

* Add tests for revoked at behavior

* Better better expires_at test

* Fix help.cy.spec.ts / Self review updates

* Fixup last issues with module config

* Make password reset is disabled for support users

Improve some email copy

* Real token check

* Move test relying on EE-code out of OSS code

* Send invitation notification after sso user creations

* Fix module config

* fixup! BE feedback

* fixup! altered not found msg

* Use user email as fallack when name is not set on support grants table

---------

Co-authored-by: Edward Paget <ed.paget@gmail.com>
Co-authored-by: Edward Paget <edpaget@users.noreply.github.com>
2025-11-19 23:59:02 -03:00
Sloan Sparger
53cf2ab305 [Metabot] Request cancellation (#65511)
* fix cut not removing text from input

* ensure we fetch all data for all possible models for smart links

* remove unused comment

* fixes smart links in metabot input sometimes degrading into their text representation and fixes some cases where wrong model name ("model" instead of "dataset") was used for metabot links

* fix unit tests

* ui for cancelling a request, handles state updates for canceled requests

* press esc to cancel metabot request, fix state being incorrect on requests after an aborted request

* add test coverage for ui, update test utils to enable aborting requests in unit tests, small bits of clean up

* add tests to processStream function

* update snapshot
2025-11-19 17:35:13 -06:00
Nemanja Glumac
135abb44a5 Consolidate caches (#66036) 2025-11-19 23:03:23 +01:00
Alex Yarosh
8699037548 Change images for development and production settings (#66039)
Updated images in the remote sync documentation to reflect new settings.
2025-11-19 20:50:12 +00:00
Alex Yarosh
03dad76c9f Update plans-blockquote inclusion for documents (#66038) 2025-11-19 15:49:12 -05:00
github-automation-metabase
dca22d0865 Bump org.postgresql/postgresql from 42.7.7 to 42.7.8 (#63804)
Inspect dependency changes here: https://github.com/pgjdbc/pgjdbc/blob/REL42.7.8/CHANGELOG.md

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-19 19:21:50 +00:00
github-automation-metabase
a6f98dbd68 Bump com.amazon.redshift/redshift-jdbc42 from 2.1.0.34 to 2.2.0 (#64830)
Inspect dependency changes here: https://github.com/aws/amazon-redshift-jdbc-driver/blob/v2.2.0/CHANGELOG.md

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-19 19:09:59 +00:00
github-automation-metabase
2fe9ebdec1 Bump org.apache.tika/tika-core from 3.2.2 to 3.2.3 (#63799)
Inspect dependency changes here:

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-19 19:03:52 +00:00
github-automation-metabase
c31762e244 Bump clj-kondo/clj-kondo from 2025.07.28 to 2025.10.23 (#65029)
* Bump clj-kondo/clj-kondo from 2025.07.28 to 2025.10.23

Inspect dependency changes here: https://github.com/clj-kondo/clj-kondo/blob/v2025.10.23/CHANGELOG.md

* Fix Kondo warning

---------

Co-authored-by: Cam Saul <github@camsaul.com>
2025-11-19 19:00:12 +00:00
Nicolò Pretto
5585815455 fix(docs): fix sdk docs not being generated correctly (#66030) 2025-11-19 11:58:18 -05:00
Jeff Bruemmer
2f8cc0f153 skills (#65676)
* skills

* docs review workflow

* update skills

* update bug fix workflow to use skills

* headings

* update code workflow to use skills

* updates

* add workflow dispatch to docs review

* edits
2025-11-19 16:54:05 +00:00
Jeff Bruemmer
d00a66f474 Fix YAML syntax for target_branch in workflow (#66018) 2025-11-19 09:50:38 -05:00
Braden Shepherdson
19ba6a165a [QP] Allow one-sided :number/between parameter values (#65987)
Fixes #65714.

These are sent as `:number/<=` or `:number/>=` and the validation was
too strict from 57 onward. Added a test for none, min, max, and both
ends of a Between filter.
2025-11-19 09:35:09 -05:00
Jeff Bruemmer
e0e3099787 Docs 57 latest (#65666)
* update release workflow to 57

* string
2025-11-19 09:27:52 -05:00
Jeff Bruemmer
6d62827416 docs - X version note and cleanup (#65756)
* X version note and cleanup

* note on hotfix x

* edit

* note on beta

* changelog link
2025-11-19 09:14:54 -05:00
Fraser
5a8ec6631a Cache yarn in CI (#65946) 2025-11-19 14:31:11 +01:00
Abed Habli
d5a7dc2e49 Docs: reusing snippet parameters (#65723)
* reusing snippet parameters

* Update docs/questions/native-editor/snippets.md

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

* updating the section

---------

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2025-11-19 13:25:17 +01:00
Thomas Schmidt
0a3a826537 Metabot tool endpoitns should support MBQL5 (#65844)
* Metabot tool endpoitns should support MBQL5

* Update filter tool to work with MBQL 5

* Fix find-outliers-wrong-query-test

Was attempting to assoc-in/dissoc-in MBQL4 query keys on an MBQL5 query.

---------

Co-authored-by: Mike Appleby <86076+appleby@users.noreply.github.com>
2025-11-19 10:32:39 +00:00
Fraser
04cbeab190 Remove ModalWithTrigger (#65994) 2025-11-19 10:22:51 +01:00
Nemanja Glumac
248a95e704 De-clutter the Cypress (nodejs) Module runner (#65881)
Running Cypress tests doesn't have to be hard.

This PR is moving us in a direction where (1) there's some logic that sets up the environment for e2e testing, and then (2) there's a simple command to invoke cypress (aka "decoupling" or "separation of concerns")

Cypress only needs to know which config to look at. It contains all the information it needs to run.

There are two ways to invoke Cypress:

1. Cypress cli
2. Cypress Module API (programmatic entry point)

They should be compatible and interchangeable. Anything you pass to the node module as options can be passed as individual flags to the cli.

```
npx cypress run --config-file path/to/some/config --spec path/to/spec.cy.spec.ts
```

is equivalent to

```
cypress.run({ configFile: "path/to/some/config", spec: "path/to/spec.cy.spec.ts" });
```

This PR removes all abstractions from the actual node module runner.
2025-11-19 10:20:14 +01:00
Kamil Mielnik
c7e2dcd254 GDGT-1235 Fix flaky dashboard parameters test (#65902)
* Fix flaky test

* Remove broken findDashCardAction helper
2025-11-19 15:17:19 +07:00
Fraser
fafd6bb3d8 Refactor ActionExecuteModal (#65573) 2025-11-19 14:38:44 +13:00
Fraser
4fe0ecbeb9 Refactor CustomURLPicker (#65574) 2025-11-19 14:23:46 +13:00
eliotmetabase
e1c31c0d8e Update label placeholder text to Optional for Gauge visualization (#65989)
* Update label placeholder text to Optional for Gauge visualization

* Update unit test
2025-11-18 17:04:14 -08:00
dpsutton
a8e592718f Turn off db routing for clickhouse and it's trick. (#65984)
* Turn off db routing for clickhouse and it's trick.

DB routing needs a "degree of freedom" to run the exact same query
against a different schema/db/instance whatever. Clickhouse only has
database.table. so to db route on the same clickhouse instance you have
to omit the database and let it resolve during query time.

`select * from db.table` can't work. Have to do `select * from table`
and let the connection dictate db1 or db2.

In 56, tables look like this:

```clojure
{:name "upload_records_10k_20251118164620", :schema "db_eafc4346850f435e"}
```

In 57, now they look like this for single db clickhouse things:

```clojure
{:name "upload_records_10k_20251118164620", :schema nil}
```

There are two critical problems here:
1. When uploading, it's not aware to omit the schema. So a table is
created with that schema. During the next sync that table is archived
and a new one with a nil'd schema is created. So the model created for
the uploaded CSV would break as it points to an inactive table. This has
a further compounding issue because now there "appear" to be two schema:
the faked nil one and also a new one like `db_eafc...`.
2. But _all_ tables will be archived in the same manner which were
initially found in 56 or below. These tables will be marked as inactive
and new ones created. Meaning all mbql queries based on clickhouse will
fail.

I wanted to revert this change but there's actually a bit more in the PR
and some conflicts. It also does more than just enabling db-routing so I
think we can perhaps undo the damage in this way more easily.

* remove outdated test
2025-11-18 18:45:46 -05:00
github-automation-metabase
0b5bbd260f Bump compojure/compojure from 1.7.1 to 1.7.2 (#63797)
Inspect dependency changes here: https://github.com/weavejester/compojure/blob/1.7.2/CHANGELOG.md

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-18 20:49:24 +00:00
github-automation-metabase
38c0aebd00 Bump io.github.eerohele/pp from 4998a1fdd9d3713d7034d04509e9212204773bf2 to ffc4edc482c057cd9412c62f018a41e9140c618b (#63473)
Inspect dependency changes here: 4998a1fdd9...ffc4edc482

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-18 20:40:55 +00:00
Riley Thompson
41b5904d52 Fix order by custom expression aggregations (#65937)
* fix bigquery order by aggregate custom expression

* add import

* make test work for all drivers
2025-11-18 13:58:53 -05:00
Alex Yarosh
a2975bdb44 Revise quickstart options for Embedded Analytics SDK (#65830)
Reorganized quickstart section for clarity based on user setup.
2025-11-18 12:41:33 -05:00
Edward Paget
e996561416 fix: allow analytics collection perms to be set (#65927)
* fix: allow analytics collection perms to be set

In #65098, we did not fully replicate the behavior of the old graph
endpoint where collection namespacing rules aren't applied to the
"analytics" namespace. Collections in this namespace can be modified as
though they are part of the root `nil` namespace. The bug was in
removing collections not part of the targetted namespace of the
`update-graph!` funciton from the graph to update.

This restores the old behavior by not excluding collection permissions
updates for collections in the "analytics" namespace in the
`remove-collections-from-other-namespaces` function.

it also updates our tests for the collection graph to make sure mock
analytics collections have the right namespace set rather than a `nil` namespace.

* fixup! reset revisions

* fixup! tests to EE module fix tests in EE module
2025-11-18 09:40:22 -06:00
Stas Gavrylov
10e76e3040 Update Table Editing e2e tests to use Postgres instead of SampleDB (#65955)
* Update Table Editing e2e tests to use Postgres instead of SampleDB

* Update table editing e2e tests to include different column types

* Address PR comments
2025-11-18 17:40:06 +02:00
Oleksandr Yakushev
25a97838db Bump Malli to 0.20.0 (#65909) 2025-11-18 17:15:12 +02:00
Brad Anderson
54c23276d7 Documents supporting text - Drag-and-drop (#65854)
Co-authored-by: Denis Berezin <denis.berezin@metabase.com>
2025-11-18 10:14:27 -05:00
Denis Berezin
58df0d448e Fix incorrect tooltip metric sum in row chart (#65938)
* Fix incorrect tooltip metric sum in row chart

* Review fixes
2025-11-18 18:08:51 +03:00
Nicola Mometto
35c649f88b Nicola/glossary creator api (#65961)
* feat: glossary, actually add creator_id on create endpoints

* feat: add creator_id tests on api
2025-11-18 15:08:26 +00:00
Nicolò Pretto
d981e64f0a move sdk bundle code to the oss folder (#65753)
* move the actual sdk folders

* update rspack config and eslint config

* fix relative import in CommonSdkStoryWrapper

* allow default exports in preview.tsx

* update eslint config to allow imports from frontend/src/embedding-sdk-shared

* remove legacy eslint disable directive

* temporarily 'disable' eslint-disable-next-line no-external-references-for-sdk-package-code that has not been ported yet

* update rspack config to use new paths

* update jest config to use new paths

* add `embedding-sdk-package` to restricted imports

* copy eslint files to apply to the new sdk folders

* add eslint-disable-next-line no-restricted-imports to some places where we need emotion

* fix jest setup

* add and use setupEmbeddingSdkEnterprisePlugins

* use `useSetting` instead of `getApplicationColors` to remove enterprise import

* move defineMetabaseAuthConfig to embedding-sdk-shared

* move MetabotProvider to embedding-sdk-bundle

* fix docs generation issue about types

* fix prettier ignore file

* move back tests to ee folder

* remove ../../../ from imports

* fix eslint issues

* fix, again, jest config :sad:
2025-11-18 15:56:43 +01:00
Sébastien
425856f92a Closes EMB-1021 flaky test e2e tests metabase browser read only mode (#65851)
* .

* .

* .
2025-11-18 15:33:42 +01:00
Anderson
5c87a6c12b Make sure 'Pull changes' button is not truncated on remote sync settings (#65932) 2025-11-18 10:41:45 -03:00
Sébastien
a033c12089 Closes EMB-982 embedding stuck on 404 when navigating with postMessage (#65662)
* Closes EMB-982 postmessage 404

* actual fix

* .

* .

* .
2025-11-18 12:51:32 +01:00
Nicola Mometto
39821ae14e Add creator to transform content view, and include glossary (#65957)
* feat: add creator_id to content view for transforms

* feat: add creator to glossary

* feat: glossary entries in content

* add creator test

* missing creator_id
2025-11-18 11:37:27 +00:00
6434 changed files with 708917 additions and 413658 deletions

View File

@@ -0,0 +1,12 @@
Generate a CI failure report for PR $PR_NUM_OR_URL (or current branch if no argument given).
Run `./bin/mage ci-report $PR_NUM_OR_URL` to generate the report, then:
1. **Summarize the failures** - What tests failed and in which jobs?
2. **Categorize** - Are these real failures, flaky tests, or infrastructure issues?
3. **Recommend next steps**:
- If flaky: suggest rerunning with `gh run rerun <run-id> --failed -R metabase/metabase`
- If real: identify the root cause and suggest fixes
- If infrastructure: note the issue type (timeout, OOM, network)
Focus on actionable insights. If all checks are passing, confirm that briefly.

View File

@@ -0,0 +1,86 @@
## Linting and Formatting
- **Lint PR:** `./bin/mage kondo-updated master` (or whatever target branch)
- Call the command one time at the beginning, record the results, then work through the problems one at a time.
- If the solution is obvious, then please apply the fix. Otherwise skip it.
- If you fix all the issues (and verify by rerunning the kondo-updated command):
- commit the change with a succinct and descriptive commit message
- **Lint File:** `./bin/mage kondo <file or files>`
- Use the linter as a way to know that you are adhering to conventions in place in the codebase
- **Lint Changes:** `./bin/mage kondo-updated HEAD`
- **Format:** `./bin/mage cljfmt-files [path]`
## Testing
- **Run a test:** `./bin/mage run-tests namespace/test-name`
- **Run all tests in a namespace:** `./bin/mage run-tests namespace`
- **Run all tests for a module:** `./bin/mage run-tests test/metabase/notification` Because the module lives in that directory.
Note: the `./bin/mage run-tests` command accepts multiple args, so you can pass
`./bin/mage run-tests namespace/test-name namespace/other-test namespace/third-test`
to run 3 tests, or
`./bin/mage run-tests test/metabase/module1 test/metabase/module2` to run 2 modules.
## Code Readability
- **Check Code Readability:** `./bin/mage -check-readable <file> [line-number]`
- Run after every change to Clojure code
- Check specific line first, then entire file if readable
## REPL Usage
> **Note:** If you have `clojure-mcp` tools available (check for tools like `clojure_eval`),
> **always prefer those over `./bin/mage -repl`**. The MCP tools provide better integration,
> richer feedback, and avoid shell escaping issues. Only use `./bin/mage -repl` as a fallback
> when clojure-mcp is not available.
- **Evaluating Clojure Code:** `./bin/mage -repl '<code>'`
- See "Sending Code to the REPL" section for more details
### Sending Code to the REPL
- Send code to the metabase process REPL using: `./bin/mage -repl '(+ 1 1)'` where `(+ 1 1)` is your Clojure code.
- See `./bin/mage -repl -h` for more details.
- If the Metabase backend is not running, you'll see an error message with instructions on how to start it.
#### Working with Files and Namespaces
1. **Load a file and call functions with fully qualified names**:
To call `your.namespace/your-function` on `arg1` and `arg2`:
```
./bin/mage -repl --namespace your.namespace '(your-function arg1 arg2)'
```
DO NOT use "require", "load-file" etc in the code string argument.
#### Understanding the Response
The `./bin/mage -repl` command returns three separate, independent outputs:
- `value`: The return value of the last expression (best for data structures)
- `stdout`: Any printed output from `println` etc. (best for messages)
- `stderr`: Any error messages (best for warnings and errors)
Example call:
```bash
./bin/mage -repl '(println "Hello, world!") '\''({0 1, 1 3, 2 0, 3 2} {0 2, 1 0, 2 3, 3 1})'
```
Example response:
```
ns: user
session: 32a35206-871c-4553-9bc9-f49491173d1c
value: ({0 1, 1 3, 2 0, 3 2} {0 2, 1 0, 2 3, 3 1})
stdout: Hello, world!
stderr:
```
For effective REPL usage:
- Return data structures as function return values
- Use `println` for human-readable messages
- Print errors to stderr

View File

@@ -0,0 +1,153 @@
# Metabase Clojure Style Guide
This guide covers Clojure and ClojureScript coding conventions for Metabase. See also: `CLOJURE_STYLE_GUIDE.adoc` for the Community Clojure Style Guide.
## Naming Conventions
**General Naming:**
- Acceptable abbreviations: `acc`, `i`, `pred`, `coll`, `n`, `s`, `k`, `f`
- Use `kebab-case` for all variables, functions, and constants
**Function Naming:**
- Pure functions should be nouns describing the value they return (e.g., `age` not `calculate-age` or `get-age`)
- Functions with side effects must end with `!`
- Don't repeat namespace alias in function names
**Destructuring:**
- Map destructuring should use kebab-case local bindings even if the map uses `snake_case` keys
## Documentation Standards
**Docstrings:**
- Every public var in `src` or `enterprise/backend/src` must have docstring
- Format using Markdown conventions
- Reference other vars with `[[other-var]]` not backticks
**Comments:**
- `TODO` format: `;; TODO (Name YYYY-MM-DD) -- description`
## Code Organization
**Visibility:**
- Make everything `^:private` unless it is used elsewhere
- Try to organize namespaces to avoid `declare` (put public functions near the end)
**Size and Structure:**
- Break up functions > 20 lines
- Lines ≤ 120 characters
- No blank non-comment lines within definition forms (except pairwise `let`/`cond`)
## Style Conventions
**Keywords and Metadata:**
- Prefer namespaced keywords for internal use: `:query-type/normal` not `:normal`
- Tag variables with `:arglists` metadata if they're functions but wouldn't otherwise have it
## Tests
**Organization:**
- Break large tests into separate `deftest` forms for logically separate test cases
- Test names should end in `-test` or `-test-<number>`
**Performance:**
- Mark pure function tests `^:parallel`
## Modules
**OSS Modules:**
- Follow `metabase.<module>.*` pattern
- Source in `src/metabase/<module>/`
**Enterprise Modules:**
- Follow `metabase-enterprise.<module>.*` pattern
- Source in `enterprise/backend/src/metabase_enterprise/<module>/`
**Module Structure:**
- REST API endpoints go in `<module>.api` or `<module>.api.*` namespaces
- Put module public API in `<module>.core` using Potemkin imports
- Put Toucan models in `<module>.models.*`
- Put settings in `<module>.settings`
- Put schemas in `<module>.schema`
**Module Linters:**
- Do not cheat module linters with `:clj-kondo/ignore [:metabase/modules]`
## REST API Endpoints
**Required Elements:**
- All new endpoints must have response schemas (`:- <schema>` after route string)
- All endpoints need Malli schemas for parameters (detailed and complete)
- All new REST API endpoints MUST HAVE TESTS
**Naming Conventions:**
- Query parameters use kebab-case
- Request bodies use `snake_case`
- Routes use singular nouns (e.g., `/api/dashboard/:id`)
**Behavior:**
- `GET` endpoints should not have side effects (except analytics)
- `defendpoint` forms should be small wrappers around Toucan model code
## MBQL (Metabase Query Language)
**Restrictions:**
- No raw MBQL introspection outside of `lib`, `lib-be`, or `query-processor` modules
- Use Lib and MBQL 5 in new source code; avoid legacy MBQL
## Database and Models
**Naming:**
- Model names and table names should be singular nouns
- Application database uses `snake_case` identifiers
**Best Practices:**
- Use `t2/select-one-fn` instead of fetching entire rows for one column
- Put correct behavior in Toucan methods, not separate helper functions
## Drivers
**Documentation:**
- New driver multimethods must be mentioned in `docs/developers-guide/driver-changelog.md`
**Implementation:**
- Driver implementations should pass `driver` argument to other driver multimethods
- Don't hardcode driver names in implementations
- Minimize logic inside `read-column-thunk` in JDBC-based drivers
## Miscellaneous
**Examples:**
- Example data should be bird-themed if possible
**Linter Suppressions:**
- Use proper format for kondo suppressions
- No `#_:clj-kondo/ignore` (keyword form)
**Configurable Options:**
- Don't define configurable options that can only be set with environment variables
- Use `:internal` `defsetting` instead

View File

@@ -0,0 +1,8 @@
# Autonomous Development Workflow
- Do not attempt to read or edit files outside the project folder
- Add failing tests first, then fix them
- Work autonomously in small, testable increments
- Run targeted tests, and lint continuously during development
- Prioritize understanding existing patterns before implementing
- Don't commit changes, leave it for the user to review and make commits

View File

@@ -0,0 +1,84 @@
# Metabase Writing Style Guide
## Core Principles
Write like you're talking to a colleague. Be conversational, not formal. Get people what they need quickly. Know your audience and match the complexity.
## Tone and Voice
**Do:**
- Use contractions ("can't" not "cannot")
- Say "people" or "companies" instead of "users"
- Be friendly but not peppy
- Acknowledge limitations honestly ("that's on us, not them")
- Jokes and Easter eggs are okay (permit them, don't suggest them)
**Don't:**
- Use exclamation points excessively
- Rely on tired tropes about nerdiness
- Use corporate jargon ("utilize", "offerings", "actionable insights")
- Tell people something is cool (show them instead)
## Structure and Clarity
**Lead with the important stuff:**
- Most important information first
- Lead with the ask, then provide context
- Cut text that adds little value (when in doubt, cut it)
- Each paragraph should have one clear purpose
**Make headings do the work:**
- Convey your actual point, not just the topic
- "Use headings to highlight key points" not "How to write a good heading"
- Use sentence case, no punctuation except question marks
- No links in headings unless entire heading is a link
## Instructions and Examples
**Tell people what to do:**
- Give the action before explaining why
- Put commands in execution order
- Provide context, steps, and reasoning
- Don't describe tasks as "easy" or "simple"
**Answer unasked questions:**
- Include answers to "dumb" questions you had when learning
- Don't literally include the question, just give the answer
## Formatting
**Code vs. UI elements:**
- Backticks for code, variable names, parameters only
- **Bold** for UI elements and labels (e.g., "Click the **Save** button")
- Don't use backticks or quotes for UI elements
## Writing Mechanics
- Limit pronouns when introducing new terms (repeat the term to reinforce it)
- Ampersands only in proper nouns, never as substitute for "and"
## Terminology Preferences
Use familiar terms from tools people already know:
- "Summarize" (like Excel) instead of "aggregate"
- "Take a look at" instead of "reference"
- "Filter" instead of technical database terms when appropriate
## Red Flags
Avoid these patterns:
- Multiple exclamation points
- Linking "here"
- Bullet lists to explain (use prose)
- Numbers that will change (guard against change)
- Describing things as "easy" or "simple"
- Stock photography-worthy content

View File

@@ -0,0 +1,21 @@
## Linting and Formatting
- **Lint:** `yarn lint-eslint-pure`
- Run ESLint on the codebase
- **Format:** `yarn prettier`
- Format code using Prettier
- **Type Check:** `yarn type-check-pure`
- Run TypeScript type checking
## Testing
### JavaScript/TypeScript Tests
- **Test a specific file:** `yarn test-unit-keep-cljs path/to/file.unit.spec.js`
- **Test by pattern:** `yarn test-unit-keep-cljs -t "pattern"`
- Runs tests matching the given pattern
### ClojureScript Tests
- **Test ClojureScript:** `yarn test-cljs`
- Run ClojureScript tests

View File

@@ -0,0 +1,420 @@
---
name: add-malli-schemas
description: Efficiently add Malli schemas to API endpoints in the Metabase codebase with proper patterns, validation timing, and error handling
---
# Add Malli Schemas to API Endpoints
This skill helps you efficiently and uniformly add Malli schemas to API endpoints in the Metabase codebase.
## Reference Files (Best Examples)
- `src/metabase/warehouses/api.clj` - Most comprehensive schemas, custom error messages
- `src/metabase/api_keys/api.clj` - Excellent response schemas
- `src/metabase/collections/api.clj` - Great named schema patterns
- `src/metabase/timeline/api/timeline.clj` - Clean, simple examples
## Quick Checklist
When adding Malli schemas to an endpoint:
- [ ] Route params have schemas
- [ ] Query params have schemas with `:optional true` and `:default` where appropriate
- [ ] Request body has a schema (for POST/PUT)
- [ ] Response schema is defined (using `:-` after route string)
- [ ] Use existing schema types from `ms` namespace when possible
- [ ] Consider creating named schemas for reusable or complex types
- [ ] Add contextual error messages for validation failures
## Basic Structure
### Complete Endpoint Example
```clojure
(mr/def ::Color [:enum "red" "blue" "green"])
(mr/def ::ResponseSchema
[:map
[:id pos-int?]
[:name string?]
[:color ::Color]
[:created_at ms/TemporalString]])
(api.macros/defendpoint :post "/:name" :- ::ResponseSchema
"Create a resource with a given name."
[;; Route Params:
{:keys [name]} :- [:map [:name ms/NonBlankString]]
;; Query Params:
{:keys [include archived]} :- [:map
[:include {:optional true} [:maybe [:= "details"]]]
[:archived {:default false} [:maybe ms/BooleanValue]]]
;; Body Params:
{:keys [color]} :- [:map [:color ::Color]]
]
;; endpoint implementation, ex:
{:id 99
:name (str "mr or mrs " name)
:color ({"red" "blue" "blue" "green" "green" "red"} color)
:created_at (t/format (t/formatter "yyyy-MM-dd'T'HH:mm:ssXXX") (t/zoned-date-time))}
)
```
## Common Schema Patterns
1. Route Params (the 5 in `api/user/id/5`)
2. Query Params (the sort+asc pair in `api/users?sort=asc`)
3. Body Params (the contents of a request body. Almost always decoded from json into edn)
4. The Raw Request map
Of the 4 arguments, deprioritize usage of the raw request unless necessary.
### Route Params
Always required, typically just a map with an ID:
```clojure
[{:keys [id]} :- [:map [:id ms/PositiveInt]]]
```
For multiple route params:
```clojure
[{:keys [id field-id]} :- [:map
[:id ms/PositiveInt]
[:field-id ms/PositiveInt]]]
```
### Query Params
Add properties for `{:optional true ...}` and `:default` values:
```clojure
{:keys [archived include limit offset]} :- [:map
[:archived {:default false} [:maybe ms/BooleanValue]]
[:include {:optional true} [:maybe [:= "tables"]]]
[:limit {:optional true} [:maybe ms/PositiveInt]]
[:offset {:optional true} [:maybe ms/PositiveInt]]]
```
### Request Body (POST/PUT)
```clojure
{:keys [name description parent_id]} :- [:map
[:name ms/NonBlankString]
[:description {:optional true} [:maybe ms/NonBlankString]]
[:parent_id {:optional true} [:maybe ms/PositiveInt]]]
```
### Response Schemas
#### Simple inline response:
```clojure
(api.macros/defendpoint :get "/:id" :- [:map
[:id pos-int?]
[:name string?]]
"Get a thing"
...)
```
#### Named schema for reuse:
```clojure
(mr/def ::Thing
[:map
[:id pos-int?]
[:name string?]
[:description [:maybe string?]]])
(api.macros/defendpoint :get "/:id" :- ::Thing
"Get a thing"
...)
(api.macros/defendpoint :get "/" :- [:sequential ::Thing]
"Get all things"
...)
```
## Common Schema Types
### From `metabase.util.malli.schema` (aliased as `ms`)
Prefer the schemas in the ms/* namespace, since they work better with our api infrastructure.
For example use `ms/PositiveInt` instead of `pos-int?`.
```clojure
ms/PositiveInt ;; Positive integer
ms/NonBlankString ;; Non-empty string
ms/BooleanValue ;; String "true"/"false" or boolean
ms/MaybeBooleanValue ;; BooleanValue or nil
ms/TemporalString ;; ISO-8601 date/time string (for REQUEST params only!)
ms/Map ;; Any map
ms/JSONString ;; JSON-encoded string
ms/PositiveNum ;; Positive number
ms/IntGreaterThanOrEqualToZero ;; 0 or positive
```
**IMPORTANT:** For response schemas, use `:any` for temporal fields, not `ms/TemporalString`!
Response schemas validate BEFORE JSON serialization, so they see Java Time objects.
### Built-in Malli Types
```clojure
:string ;; Any string
:boolean ;; true/false
:int ;; Any integer
:keyword ;; Clojure keyword
pos-int? ;; Positive integer predicate
[:maybe X] ;; X or nil
[:enum "a" "b" "c"] ;; One of these values
[:or X Y] ;; Schema that satisfies X or Y
[:and X Y] ;; Schema that satisfies X and Y
[:sequential X] ;; Sequential of Xs
[:set X] ;; Set of Xs
[:map-of K V] ;; Map with keys w/ schema K and values w/ schema V
[:tuple X Y Z] ;; Fixed-length tuple of schemas X Y Z
```
Avoid using sequence schemas unless completely necessary.
## Step-by-Step: Adding Schemas to an Endpoint
### Example: Adding return schema to `GET /api/field/:id/related`
**Before:**
```clojure
(api.macros/defendpoint :get "/:id/related"
"Return related entities."
[{:keys [id]} :- [:map [:id ms/PositiveInt]]]
(-> (t2/select-one :model/Field :id id) api/read-check xrays/related))
```
**Step 1:** Check what the function returns (look at `xrays/related`)
**Step 2:** Define response schema based on return type:
```clojure
(mr/def ::RelatedEntity
[:map
[:tables [:sequential [:map [:id pos-int?] [:name string?]]]]
[:fields [:sequential [:map [:id pos-int?] [:name string?]]]]])
```
**Step 3:** Add response schema to endpoint:
```clojure
(api.macros/defendpoint :get "/:id/related" :- ::RelatedEntity
"Return related entities."
[{:keys [id]} :- [:map [:id ms/PositiveInt]]]
(-> (t2/select-one :model/Field :id id) api/read-check xrays/related))
```
## Advanced Patterns
### Custom Error Messages
```clojure
(def DBEngineString
"Schema for a valid database engine name."
(mu/with-api-error-message
[:and
ms/NonBlankString
[:fn
{:error/message "Valid database engine"}
#(u/ignore-exceptions (driver/the-driver %))]]
(deferred-tru "value must be a valid database engine.")))
```
### Enum with Documentation
```clojure
(def PinnedState
(into [:enum {:error/message "pinned state must be 'all', 'is_pinned', or 'is_not_pinned'"}]
#{"all" "is_pinned" "is_not_pinned"}))
```
### Complex Nested Response
```clojure
(mr/def ::DashboardQuestionCandidate
[:map
[:id ms/PositiveInt]
[:name ms/NonBlankString]
[:description [:maybe string?]]
[:sole_dashboard_info
[:map
[:id ms/PositiveInt]
[:name ms/NonBlankString]
[:description [:maybe string?]]]]])
(mr/def ::DashboardQuestionCandidatesResponse
[:map
[:data [:sequential ::DashboardQuestionCandidate]]
[:total ms/PositiveInt]])
```
### Paginated Response Pattern
```clojure
(mr/def ::PaginatedResponse
[:map
[:data [:sequential ::Item]]
[:total integer?]
[:limit {:optional true} [:maybe integer?]]
[:offset {:optional true} [:maybe integer?]]])
```
## Common Pitfalls
### Don't: Forget `:maybe` for nullable fields
```clojure
[:description ms/NonBlankString] ;; WRONG - fails if nil
[:description [:maybe ms/NonBlankString]] ;; RIGHT - allows nil
```
### Don't: Forget `:optional true` for optional query params
```clojure
[:limit ms/PositiveInt] ;; WRONG - required but shouldn't be
[:limit {:optional true} [:maybe ms/PositiveInt]] ;; RIGHT
```
### Don't: Forget `:default` values for known params
```clojure
[:limit ms/PositiveInt] ;; WRONG - required but shouldn't be
[:limit {:optional true :default 0} [:maybe ms/PositiveInt]] ;; RIGHT
```
### Don't: Mix up route params, query params, and body
```clojure
;; WRONG - all in one map
[{:keys [id name archived]} :- [:map ...]]
;; RIGHT - separate destructuring
[{:keys [id]} :- [:map [:id ms/PositiveInt]]
{:keys [archived]} :- [:map [:archived {:default false} ms/BooleanValue]]
{:keys [name]} :- [:map [:name ms/NonBlankString]]]
```
### Don't: Use `ms/TemporalString` for Java Time objects in response schemas
```clojure
;; WRONG - Java Time objects aren't strings yet
[:date_joined ms/TemporalString]
;; RIGHT - schemas validate BEFORE JSON serialization
[:date_joined :any] ;; Java Time object, serialized to string by middleware
[:last_login [:maybe :any]] ;; Java Time object or nil
```
**Why:** Response schemas validate the internal Clojure data structures BEFORE they are serialized to JSON. Java Time objects like `OffsetDateTime` get converted to ISO-8601 strings by the JSON middleware, so the schema needs to accept the raw Java objects.
### Don't: Use `[:sequential X]` when the data is actually a set
```clojure
;; WRONG - group_ids is actually a set
[:group_ids {:optional true} [:sequential pos-int?]]
;; RIGHT - matches the actual data structure
[:group_ids {:optional true} [:maybe [:set pos-int?]]]
```
**Why:** Toucan hydration methods often return sets. The JSON middleware will serialize sets to arrays, but the schema validates before serialization.
### Don't: Create anonymous schemas for reused structures
Use `mr/def` for schemas used in multiple places:
```clojure
(mr/def ::User
[:map
[:id pos-int?]
[:email string?]
[:name string?]])
```
## Finding Return Types
1. **Look at the function being called**
```clojure
(api.macros/defendpoint :get "/:id"
[{:keys [id]}]
(t2/select-one :model/Field :id id)) ;; Returns a Field instance
```
2. **Check Toucan models for structure**
Look in `src/metabase/*/models/*.clj` for model definitions.
3. **Use clojure-mcp or REPL to inspect**
```bash
./bin/mage -repl '(require '\''metabase.xrays.core) (doc metabase.xrays.core/related)'
```
4. **Check tests**
Tests often show the expected response structure.
## Understanding Schema Validation Timing
**CRITICAL CONCEPT:** Schemas validate at different points in the request/response lifecycle:
### Request Parameter Schemas (Query/Body/Route)
- Validate AFTER JSON parsing
- Data is already deserialized (strings, numbers, booleans)
- Use `ms/TemporalString` for date/time inputs
- Use `ms/BooleanValue` for boolean query params
### Response Schemas
- Validate BEFORE JSON serialization
- Data is still in Clojure format (Java Time objects, sets, keywords)
- Use `:any` for Java Time objects
- Use `[:set X]` for sets
- Use `[:enum :keyword]` for keyword enums
### Serialization Flow
```
Request: JSON string → Parse → Coerce → Handler
Response: Handler → Schema Check → Encode → Serialize → JSON string
```
## Workflow Summary
1. **Read the endpoint** - understand what it does
2. **Identify params** - route, query, body
3. **Add parameter schemas** - use existing types from `ms`
4. **Determine return type** - check the implementation
5. **Define response schema** - inline or named with `mr/def`
6. **Test** - ensure the endpoint works and validates correctly
## Testing Your Schemas
After adding schemas, verify:
1. **Valid requests work** - test with correct data
2. **Invalid requests fail gracefully** - test with wrong types
3. **Optional params work** - test with/without optional params
4. **Error messages are clear** - check validation error responses
## Tips
- **Start simple** - begin with basic types, refine later
- **Reuse schemas** - if you see the same structure twice, make it a named schema
- **Be specific** - use `ms/PositiveInt` instead of `pos-int?`
- **Document intent** - add docstrings to named schemas
- **Follow conventions** - look at similar endpoints in the same namespace
- **Check the actual data** - use REPL to inspect what's actually returned before serialization
## Additional Resources
- [Malli Documentation](https://github.com/metosin/malli)
- Metabase Malli utilities: `src/metabase/util/malli/schema.clj`
- Metabase schema registry: `src/metabase/util/malli/registry.clj`

View File

@@ -0,0 +1,504 @@
---
name: analytics-events
description: Add product analytics events to track user interactions in the Metabase frontend
allowed-tools: Read, Write, Edit, Grep, Glob
---
# Frontend Analytics Events Skill
This skill helps you add product analytics (Snowplow) events to track user interactions in the Metabase frontend codebase.
## Quick Reference
Analytics events in Metabase use Snowplow with typed event schemas. All events must be defined in TypeScript types before use.
**Key Files:**
- `frontend/src/metabase-types/analytics/event.ts` - Event type definitions
- `frontend/src/metabase-types/analytics/schema.ts` - Schema registry
- `frontend/src/metabase/lib/analytics.ts` - Core tracking functions
- Feature-specific `analytics.ts` files - Tracking function wrappers
## Quick Checklist
When adding a new analytics event:
- [ ] Define event type in `frontend/src/metabase-types/analytics/event.ts`
- [ ] Add event to appropriate union type (e.g., `DataStudioEvent`, `SimpleEvent`)
- [ ] Create tracking function in feature's `analytics.ts` file
- [ ] Import and call tracking function at the interaction point
- [ ] Use `trackSimpleEvent()` for basic events (most common)
## Event Schema Types
### 1. Simple Events (Most Common)
Use `SimpleEventSchema` for straightforward tracking. It supports these standard fields:
```typescript
type SimpleEventSchema = {
event: string; // Required: Event name (snake_case)
target_id?: number | null; // Optional: ID of affected entity
triggered_from?: string | null; // Optional: UI location/context
duration_ms?: number | null; // Optional: Duration in milliseconds
result?: string | null; // Optional: Outcome (e.g., "success", "failure")
event_detail?: string | null; // Optional: Additional detail/variant
};
```
**When to use:** 90% of events fit this schema. Use for clicks, opens, closes, creates, deletes, etc.
### 2. Custom Schemas (legacy, no events are being added)
Consider adding new event schema only in very special cases.
**Examples:** `DashboardEventSchema`, `CleanupEventSchema`, `QuestionEventSchema`
## Step-by-Step: Adding a Simple Event
### Example: Track when a user applies filters in a table picker
#### Step 1: Define Event Types
Add event type definitions to `frontend/src/metabase-types/analytics/event.ts`:
```typescript
export type DataStudioTablePickerFiltersAppliedEvent = ValidateEvent<{
event: "data_studio_table_picker_filters_applied";
}>;
export type DataStudioTablePickerFiltersClearedEvent = ValidateEvent<{
event: "data_studio_table_picker_filters_cleared";
}>;
```
#### Step 2: Add to Union Type
Find or create the appropriate union type and add your events:
```typescript
export type DataStudioEvent =
| DataStudioLibraryCreatedEvent
| DataStudioTablePublishedEvent
| DataStudioGlossaryCreatedEvent
| DataStudioGlossaryEditedEvent
| DataStudioGlossaryDeletedEvent
| DataStudioTablePickerFiltersAppliedEvent // <- Add here
| DataStudioTablePickerFiltersClearedEvent; // <- Add here
```
#### Step 3: Create Tracking Functions
In your feature's `analytics.ts` file (e.g., `enterprise/frontend/src/metabase-enterprise/data-studio/analytics.ts`):
```typescript
import { trackSimpleEvent } from "metabase/lib/analytics";
export const trackDataStudioTablePickerFiltersApplied = () => {
trackSimpleEvent({
event: "data_studio_table_picker_filters_applied",
});
};
export const trackDataStudioTablePickerFiltersCleared = () => {
trackSimpleEvent({
event: "data_studio_table_picker_filters_cleared",
});
};
```
#### Step 4: Use in Components
Import and call the tracking function at the interaction point:
```typescript
import {
trackDataStudioTablePickerFiltersApplied,
trackDataStudioTablePickerFiltersCleared,
} from "metabase-enterprise/data-studio/analytics";
function FilterPopover({ filters, onSubmit }) {
const handleReset = () => {
trackDataStudioTablePickerFiltersCleared(); // <- Track here
onSubmit(emptyFilters);
};
return (
<form
onSubmit={(event) => {
event.preventDefault();
trackDataStudioTablePickerFiltersApplied(); // <- Track here
onSubmit(form);
}}
>
{/* form content */}
</form>
);
}
```
## Using SimpleEventSchema Fields
### Example: Event with target_id
```typescript
// Type definition
export type DataStudioLibraryCreatedEvent = ValidateEvent<{
event: "data_studio_library_created";
target_id: number | null;
}>;
// Tracking function
export const trackDataStudioLibraryCreated = (id: CollectionId) => {
trackSimpleEvent({
event: "data_studio_library_created",
target_id: Number(id),
});
};
// Usage
trackDataStudioLibraryCreated(newLibrary.id);
```
### Example: Event with triggered_from
```typescript
// Type definition
export type NewButtonClickedEvent = ValidateEvent<{
event: "new_button_clicked";
triggered_from: "app-bar" | "empty-collection";
}>;
// Tracking function
export const trackNewButtonClicked = (location: "app-bar" | "empty-collection") => {
trackSimpleEvent({
event: "new_button_clicked",
triggered_from: location,
});
};
// Usage
<Button onClick={() => {
trackNewButtonClicked("app-bar");
handleCreate();
}}>
New
</Button>
```
### Example: Event with event_detail
```typescript
// Type definition
export type MetadataEditEvent = ValidateEvent<{
event: "metadata_edited";
event_detail: "type_casting" | "semantic_type_change" | "visibility_change";
triggered_from: "admin" | "data_studio";
}>;
// Tracking function
export const trackMetadataChange = (
detail: "type_casting" | "semantic_type_change" | "visibility_change",
location: "admin" | "data_studio"
) => {
trackSimpleEvent({
event: "metadata_edited",
event_detail: detail,
triggered_from: location,
});
};
// Usage
trackMetadataChange("semantic_type_change", "data_studio");
```
### Example: Event with result and duration
```typescript
// Type definition
export type MoveToTrashEvent = ValidateEvent<{
event: "moved-to-trash";
target_id: number | null;
triggered_from: "collection" | "detail_page" | "cleanup_modal";
duration_ms: number | null;
result: "success" | "failure";
event_detail: "question" | "model" | "metric" | "dashboard";
}>;
// Tracking function
export const trackMoveToTrash = (params: {
targetId: number | null;
triggeredFrom: "collection" | "detail_page" | "cleanup_modal";
durationMs: number | null;
result: "success" | "failure";
itemType: "question" | "model" | "metric" | "dashboard";
}) => {
trackSimpleEvent({
event: "moved-to-trash",
target_id: params.targetId,
triggered_from: params.triggeredFrom,
duration_ms: params.durationMs,
result: params.result,
event_detail: params.itemType,
});
};
// Usage with timing
const startTime = Date.now();
try {
await moveToTrash(item);
trackMoveToTrash({
targetId: item.id,
triggeredFrom: "collection",
durationMs: Date.now() - startTime,
result: "success",
itemType: "question",
});
} catch (error) {
trackMoveToTrash({
targetId: item.id,
triggeredFrom: "collection",
durationMs: Date.now() - startTime,
result: "failure",
itemType: "question",
});
}
```
## Naming Conventions
### Event Names (snake_case)
```typescript
// Good
"data_studio_library_created"
"table_picker_filters_applied"
"metabot_chat_opened"
// Bad
"DataStudioLibraryCreated" // Wrong case
"tablePickerFiltersApplied" // Wrong case
"filters-applied" // Use underscore, not hyphen
```
### Event Type Names (PascalCase with "Event" suffix)
```typescript
// Good
DataStudioLibraryCreatedEvent
TablePickerFiltersAppliedEvent
MetabotChatOpenedEvent
// Bad
dataStudioLibraryCreated // Wrong case
DataStudioLibraryCreated // Missing "Event" suffix
```
### Tracking Function Names (camelCase with "track" prefix)
```typescript
// Good
trackDataStudioLibraryCreated
trackTablePickerFiltersApplied
trackMetabotChatOpened
// Bad
DataStudioLibraryCreated // Missing "track" prefix
track_library_created // Wrong case
logLibraryCreated // Use "track" prefix
```
## Common Patterns
### Pattern 1: Feature-Specific Union Types
Group related events together:
```typescript
export type DataStudioEvent =
| DataStudioLibraryCreatedEvent
| DataStudioTablePublishedEvent
| DataStudioGlossaryCreatedEvent;
export type MetabotEvent =
| MetabotChatOpenedEvent
| MetabotRequestSentEvent
| MetabotFixQueryClickedEvent;
// Then add to SimpleEvent union
export type SimpleEvent =
| /* other events */
| DataStudioEvent
| MetabotEvent
| /* more events */;
```
### Pattern 2: Conditional Tracking
Track different events based on user action:
```typescript
const handleSave = async () => {
if (isNewItem) {
await createItem(data);
trackItemCreated(newItem.id);
} else {
await updateItem(id, data);
trackItemUpdated(id);
}
};
```
## Common Pitfalls
### Don't: Add custom fields to SimpleEvent
```typescript
// WRONG - SimpleEvent doesn't support custom fields
export const trackFiltersApplied = (filters: FilterState) => {
trackSimpleEvent({
event: "filters_applied",
data_layer: filters.dataLayer, // ❌ Not in SimpleEventSchema
data_source: filters.dataSource, // ❌ Not in SimpleEventSchema
with_owner: filters.hasOwner, // ❌ Not in SimpleEventSchema
});
};
// RIGHT - Use only standard SimpleEventSchema fields
export const trackFiltersApplied = () => {
trackSimpleEvent({
event: "filters_applied",
});
};
// Or use event_detail for a single variant
export const trackFilterApplied = (filterType: string) => {
trackSimpleEvent({
event: "filter_applied",
event_detail: filterType, // ✓ "data_layer", "data_source", etc.
});
};
```
### Don't: Forget to add event to union type
```typescript
// Define the event
export type NewFeatureClickedEvent = ValidateEvent<{
event: "new_feature_clicked";
}>;
// ❌ WRONG - Forgot to add to SimpleEvent union
// Event won't be recognized by TypeScript
// ✓ RIGHT - Add to appropriate union
export type SimpleEvent =
| /* other events */
| NewFeatureClickedEvent;
```
### Don't: Mix up event name formats
```typescript
// WRONG
event: "dataStudioLibraryCreated" // camelCase
event: "data-studio-library-created" // kebab-case
event: "Data_Studio_Library_Created" // Mixed case
// RIGHT
event: "data_studio_library_created" // snake_case
```
### Don't: Track PII or sensitive data
```typescript
// WRONG - Don't track user emails, names, or sensitive data
trackSimpleEvent({
event: "user_logged_in",
event_detail: user.email, // ❌ PII
});
// RIGHT - Track non-sensitive identifiers only
trackSimpleEvent({
event: "user_logged_in",
target_id: user.id, // ✓ Just the ID
});
```
### Don't: Forget to track both success and failure
```typescript
// WRONG - Only tracking success
try {
await saveData();
trackDataSaved();
} catch (error) {
// ❌ No tracking for failure case
}
// RIGHT - Track both outcomes
try {
await saveData();
trackDataSaved({ result: "success" });
} catch (error) {
trackDataSaved({ result: "failure" });
}
```
## Testing Analytics Events
While developing, you can verify events are firing:
1. **Check browser console** - When `SNOWPLOW_ENABLED=true` in dev, events are logged
2. **Use shouldLogAnalytics** - Set in `metabase/env` to see all analytics in console
3. **Check Snowplow debugger** - Browser extension for Snowplow events
Example console output:
```
[SNOWPLOW EVENT | event sent:true], data_studio_table_picker_filters_applied
```
## File Organization
### Where to put tracking functions:
```
Feature-specific analytics functions:
frontend/src/metabase/{feature}/analytics.ts
enterprise/frontend/src/metabase-enterprise/{feature}/analytics.ts
Event type definitions (all in one place):
frontend/src/metabase-types/analytics/event.ts
Core tracking utilities:
frontend/src/metabase/lib/analytics.ts
```
## Real-World Examples
See these files for reference:
- **Simple events**: `enterprise/frontend/src/metabase-enterprise/data-studio/analytics.ts`
- **Events with variants**: `frontend/src/metabase/dashboard/analytics.ts`
- **Complex events**: `frontend/src/metabase/query_builder/analytics.js`
- **Event type examples**: `frontend/src/metabase-types/analytics/event.ts`
## Workflow Summary
1. **Identify the user interaction** to track
2. **Decide on event name** (snake_case, descriptive)
3. **Define event type** in `event.ts` using `ValidateEvent`
4. **Add to union type** (create feature union if needed)
5. **Create tracking function** in feature's `analytics.ts`
6. **Import and call** at the interaction point
7. **Test** that events fire correctly
## Tips
- **Be specific** - `filters_applied` is better than `action_performed`
- **Use past tense** - `library_created` not `create_library`
- **Group related events** - Create feature-specific event union types
- **Track meaningful actions** - Not every click needs tracking
- **Consider the data** - What would you want to analyze later?
- **Stay consistent** - Follow existing naming patterns in the codebase
- **Document context** - Use `triggered_from` to track where the action happened

View File

@@ -0,0 +1,144 @@
---
name: clojure-review
description: Review Clojure and ClojureScript code changes for compliance with Metabase coding standards, style violations, and code quality issues. Use when reviewing pull requests or diffs containing Clojure/ClojureScript code.
allowed-tools: Read, Grep, Bash, Glob
---
# Clojure Code Review Skill
@./../_shared/clojure-style-guide.md
@./../_shared/clojure-commands.md
## Review guidelines
**What to flag:**
- Check compliance with the Metabase Clojure style guide (included above)
- If `CLOJURE_STYLE_GUIDE.adoc` exists in the working directory, also check compliance with the community Clojure style guide
- Flag all style guide violations
**What NOT to post:**
- Do not post comments congratulating someone for trivial changes or for following style guidelines
- Do not post comments confirming things "look good" or telling them they did something correctly
- Only post comments about style violations or potential issues
Example bad code review comments to avoid:
> This TODO comment is properly formatted with author and date - nice work!
> Good addition of limit 1 to the query - this makes the test more efficient without changing its behavior.
> The kondo ignore comment is appropriately placed here
> Test name properly ends with -test as required by the style guide.
**Special cases:**
- Do not post comments about missing parentheses (these will be caught by the linter)
## Quick review checklist
Use this to scan through changes efficiently:
### Naming
- [ ] Descriptive names (no `tbl`, `zs'`)
- [ ] Pure functions named as nouns describing their return value
- [ ] `kebab-case` for all variables and functions
- [ ] Side-effect functions end with `!`
- [ ] No namespace-alias repetition in function names
### Documentation
- [ ] Public vars in `src` or `enterprise/backend/src` have useful docstrings
- [ ] Docstrings use Markdown conventions
- [ ] References use `[[other-var]]` not backticks
- [ ] `TODO` comments include author and date: `;; TODO (Name 2025-01-01) -- description`
### Code Organization
- [ ] Everything `^:private` unless used elsewhere
- [ ] No `declare` when avoidable (public functions near end)
- [ ] Functions under 20 lines when possible
- [ ] No blank, non-comment lines within definition forms (except pairwise constructs in `let`/`cond`)
- [ ] Lines ≤ 120 characters
### Tests
- [ ] Separate `deftest` forms for distinct test cases
- [ ] Pure tests marked `^:parallel`
- [ ] Test names end in `-test` or `-test-<number>`
### Modules
- [ ] Correct module patterns (OSS: `metabase.<module>.*`, EE: `metabase-enterprise.<module>.*`)
- [ ] API endpoints in `<module>.api` namespaces
- [ ] Public API in `<module>.core` with Potemkin
- [ ] No cheating module linters with `:clj-kondo/ignore [:metabase/modules]`
### REST API
- [ ] Response schemas present (`:- <schema>`)
- [ ] Query params use kebab-case, bodies use `snake_case`
- [ ] Routes use singular nouns (e.g., `/api/dashboard/:id`)
- [ ] `GET` has no side effects (except analytics)
- [ ] Malli schemas detailed and complete
- [ ] All new endpoints have tests
### MBQL
- [ ] No raw MBQL manipulation outside `lib`, `lib-be`, or `query-processor` modules
- [ ] Uses Lib and MBQL 5, not legacy MBQL
### Database
- [ ] Model and table names are singular nouns
- [ ] Uses `t2/select-one-fn` instead of selecting full rows for one column
- [ ] Logic in Toucan methods, not helper functions
### Drivers
- [ ] New multimethods documented in `docs/developers-guide/driver-changelog.md`
- [ ] Passes `driver` argument to other driver methods (no hardcoded driver names)
- [ ] Minimal logic in `read-column-thunk`
### Miscellaneous
- [ ] Example data is bird-themed when possible
- [ ] Kondo linter suppressions use proper format (not `#_:clj-kondo/ignore` keyword form)
## Pattern matching table
Quick scan for common issues:
| Pattern | Issue |
| -------------------------------------------- | ----------------------------------------------------------- |
| `calculate-age`, `get-user` | Pure functions should be nouns: `age`, `user` |
| `update-db`, `save-model` | Missing `!` for side effects: `update-db!`, `save-model!` |
| `snake_case_var` | Should use kebab-case |
| Public var without docstring | Add docstring explaining purpose |
| `;; TODO fix this` | Missing author/date: `;; TODO (Name 2025-01-01) -- description` |
| `(defn foo ...)` in namespace used elsewhere | Should be `(defn ^:private foo ...)` |
| Function > 20 lines | Consider breaking up into smaller functions |
| `/api/dashboards/:id` | Use singular: `/api/dashboard/:id` |
| Query params with `snake_case` | Use kebab-case for query params |
| New API endpoint without tests | Add tests for the endpoint |
## Feedback format examples
**For style violations:**
> This pure function should be named as a noun describing its return value. Consider `user` instead of `get-user`.
**For missing documentation:**
> This public var needs a docstring explaining its purpose, inputs, and outputs.
**For organization issues:**
> This function is only used in this namespace, so it should be marked `^:private`.
**For API conventions:**
> Query parameters should use kebab-case. Change `user_id` to `user-id`.

View File

@@ -0,0 +1,69 @@
---
name: clojure-write
description: Guide Clojure and ClojureScript development using REPL-driven workflow, coding conventions, and best practices. Use when writing, developing, or refactoring Clojure/ClojureScript code.
---
# Clojure Development Skill
## Tool Preference
When `clojure-mcp` tools are available (e.g., `clojure_eval`, `clojure_edit`), **always use them**
instead of shell commands like `./bin/mage -repl`. The MCP tools provide:
- Direct REPL integration without shell escaping issues
- Better error messages and feedback
- Structural Clojure editing that prevents syntax errors
Only fall back to `./bin/mage` commands when clojure-mcp is not available.
@./../_shared/development-workflow.md
@./../_shared/clojure-style-guide.md
@./../_shared/clojure-commands.md
## REPL-Driven Development Workflow
- Start with small, fundamental functions:
- Identify the core features or functionalities required for your task.
- Break each feature down into the smallest, most basic functions that can be developed and tested independently.
- Write and test in the REPL:
- Write the code for each small function directly in the REPL (Read-Eval-Print Loop).
- Test it thoroughly with a variety of inputs, including typical use cases and relevant edge cases, to ensure it
behaves as expected.
- Integrate into source code:
- Once a function works correctly in the REPL, move it from the REPL environment into your source code files (e.g.,
within appropriate namespaces).
- Gradually increase complexity:
- Build upon tested, basic functions to create more complex functions or components.
- Compose smaller functions together, testing each new composition in the REPL to verify correctness step by step.
- Ensure dependency testing:
- Make sure every function is fully tested in the REPL before it is depended upon by other functions.
- This ensures that each layer of your application is reliable before you build on it.
- Use the REPL fully:
- Use the REPL as your primary tool to experiment with different approaches, iterate quickly, and get immediate
feedback on your code.
- Follow functional programming principles:
- Keep functions small, focused, and composable.
- Use Clojure's functional programming features—like immutability, higher-order functions, and the standard
library—to write concise, effective code.
## How to Evaluate Code
### Bottom-up Dev Loop
1. Write code into a file.
2. Evaluate the file's namespace and make sure it loads correctly with:
```
./bin/mage -repl --namespace metabase.app-db.connection
```
3. Call functions in the namespace with test inputs, and observe that the outputs are correct
Feel free to copy these REPL session trials into actual test cases using `deftest` and `is`.
4. Once you know these functions are good, return to 1, and compose them into the task that you need to build.
## Critical Rules for Editing
- Be careful with parentheses counts when editing Clojure code
- After EVERY change to Clojure code, verify readability with `-check-readable`
- End all files with a newline
- When editing tabular code, where the columns line up, try to keep them aligned
- Spaces on a line with nothing after it is not allowed

View File

@@ -0,0 +1,163 @@
---
name: docs-review
description: Review documentation changes for compliance with the Metabase writing style guide. Use when reviewing pull requests, files, or diffs containing documentation markdown files.
allowed-tools: Read, Grep, Bash, Glob
---
# Documentation Review Skill
@./../_shared/metabase-style-guide.md
## Review mode detection
**IMPORTANT: Before starting the review, determine which mode to use:**
1. **PR review mode**: If the `mcp__github__create_pending_pull_request_review` tool is available, you are reviewing a GitHub PR
- Use the pending review workflow to post all issues as one cohesive review
- Follow the workflow steps in "PR review mode format" below
2. **Local review mode**: If the MCP tool is NOT available, output issues in the conversation
- Format all issues in a numbered markdown list (as described in "Feedback format" below)
## Review process
1. **Detect review mode** - Check if `mcp__github__create_pending_pull_request_review` is available
2. Read the changes through once to understand intent
3. Check all issues that violate style guide or significantly impact readability
4. Only flag issues worth mentioning - if it won't make a material difference to the reader, skip it
5. **REQUIRED: Number ALL feedback sequentially** - Start from Issue 1 and increment for each issue found
## Review checklist
Run through the diff looking for these issues:
**Tone and voice:**
- [ ] Formal/corporate language ("utilize" not "use", "offerings", etc.)
- [ ] "Users" instead of "people" or "companies"
- [ ] Excessive exclamation points or overly peppy tone
- [ ] Telling readers something is cool instead of showing them
**Structure and clarity:**
- [ ] Important information buried instead of leading
- [ ] Verbose text that adds little value
- [ ] Paragraphs without clear purpose
- [ ] Vague headings that don't convey the point
- [ ] Instructions explain "why" before telling "what to do"
- [ ] Tasks described as "easy" or "simple"
**Links and references:**
- [ ] Linking the word "here" instead of descriptive text
- [ ] Links in headings (unless entire heading is a link)
**Formatting:**
- [ ] Ampersands as "and" substitute (except proper nouns)
- [ ] Inconsistent list formatting
**Code and examples:**
- [ ] Code examples that don't work or would error
- [ ] Commands not in execution order
- [ ] Full-width screenshots instead of scoped UI elements
- [ ] Excessive or unnecessary images
**Sentence construction:**
- [ ] Overuse of pronouns when introducing new terms
## Quick scan table
| Pattern | Issue |
| ----------------------------- | --------------------------------------------- |
| we can do X, our feature | Should be "Metabase" or "it" |
| click here, read more here | Need descriptive link text |
| easy, simple, just | Remove condescending qualifiers |
| users | Should be "people" or "companies" if possible |
## Feedback format
**MANDATORY REQUIREMENT: Every single issue MUST be numbered sequentially starting from Issue 1.**
This numbered format is NON-NEGOTIABLE. It allows users to efficiently reference specific issues (e.g., "fix issues 1, 3, and 5") and track which feedback has been addressed.
### Local review mode format
When outputting issues in the conversation (local mode), use this format:
```markdown
## Issues
**Issue 1: [Brief title]**
Line X: Succinct description of the issue
[code or example]
Suggested fix or succinct explanation
**Issue 2: [Brief title]**
Line Y: Description of the issue
Suggested fix or explanation
**Issue 3: [Brief title]**
...
```
**Examples:**
> **Issue 1: Formal tone**
> Line 15: This could be more conversational. Consider: "You can't..." instead of "You cannot..."
> **Issue 2: Vague heading**
> Line 8: The heading could be more specific. Try stating the point directly: "Run migrations before upgrading" vs "Upgrade process"
### PR review mode format
When posting to GitHub (PR mode), use the **pending review workflow**:
**Workflow steps:**
1. **Start a review**: Use `mcp__github__create_pending_pull_request_review` to begin a pending review
- This creates a draft review that won't be visible until submitted
2. **Get diff information**: Use `mcp__github__get_pull_request_diff` to understand the code changes and line numbers
- This helps you determine the correct file paths and line numbers for comments
3. **Identify ALL issues**: Read through all changes and identify every issue worth mentioning
- Collect all issues before posting any comments
- Number them sequentially (Issue 1, Issue 2, Issue 3, etc.)
4. **Add review comments**: Use `mcp__github__add_pull_request_review_comment_to_pending_review` for each issue
- **CRITICAL**: Post ALL comments in a SINGLE response using multiple tool calls in parallel
- Each comment should reference a specific file path and line number from the diff
- Start each comment body with `**Issue N: [Brief title]**`
- Include the description and suggested fix
5. **Submit the review**: Use `mcp__github__submit_pending_pull_request_review` to publish all comments at once
- Use event type `"COMMENT"` (NOT "REQUEST_CHANGES") to make it non-blocking
- **Do NOT include a body message** - Leave the body empty or omit it entirely
- All comments will appear together as one cohesive review
**Comment format example:**
```
**Issue 1: Formal tone**
This could be more conversational. Consider: "You can't..." instead of "You cannot..."
```
**IMPORTANT**:
- Each issue gets its own review comment attached to the pending review
- Number ALL comments sequentially (Issue 1, Issue 2, Issue 3, etc.)
- Always start the comment body with `**Issue N: [Brief title]**`
- **MUST add all comments in parallel in a single response** - Do NOT add them one after another in separate responses
- Do NOT output a summary message to the conversation - only post GitHub review comments
- When submitting the review, do NOT include a body parameter (or leave it empty) to avoid cluttering the PR with summary text
- The review will appear as a single review with multiple comments when submitted
## Final check
1. Remove any issues from your assessment that won't make a material difference to the reader if addressed. Only flag issues worth the author's time to fix.
2. **Verify all issues are numbered sequentially** starting from Issue 1 with no gaps in numbering.
3. Confirm the format exactly matches: `**Issue N: [Brief title]**` where N is the issue number.
4. **In PR mode**: Verify each issue was posted as a separate GitHub comment (not output to conversation).

View File

@@ -0,0 +1,96 @@
---
name: docs-write
description: Write documentation following Metabase's conversational, clear, and user-focused style. Use when creating or editing documentation files (markdown, MDX, etc.).
allowed-tools: Read, Write, Grep, Bash, Glob
---
# Documentation Writing Skill
@./../_shared/metabase-style-guide.md
## When writing documentation
### Start here
1. **Who is this for?** Match complexity to audience. Don't oversimplify hard things or overcomplicate simple ones.
2. **What do they need?** Get them to the answer fast. Nobody wants to be in docs longer than necessary.
3. **What did you struggle with?** Those common questions you had when learning? Answer them (without literally including the question).
### Writing process
**Draft:**
- Write out the steps/explanation as you'd tell a colleague
- Lead with what to do, then explain why
- Use headings that state your point: "Set SAML before adding users" not "SAML configuration timing"
**Edit:**
- Read aloud. Does it sound like you talking? If it's too formal, simplify.
- Cut anything that doesn't directly help the reader
- Check each paragraph has one clear purpose
- Verify examples actually work (don't give examples that error)
**Polish:**
- Make links descriptive (never "here")
- Backticks only for code/variables, **bold** for UI elements
- American spelling, serial commas
- Keep images minimal and scoped tight
**Format:**
- Run prettier on the file after making edits: `yarn prettier --write <file-path>`
- This ensures consistent formatting across all documentation
### Common patterns
**Instructions:**
```markdown
Run:
\`\`\`
command-to-run
\`\`\`
Then:
\`\`\`
next-command
\`\`\`
This ensures you're getting the latest changes.
```
Not: "(remember to run X before Y...)" buried in a paragraph.
**Headings:**
- "Use environment variables for configuration" ✅
- "Environment variables" ❌ (too vague)
- "How to use environment variables for configuration" ❌ (too wordy)
**Links:**
- "Check out the [SAML documentation](link)" ✅
- "Read the docs [here](link)" ❌
### Watch out for
- Describing tasks as "easy" (you don't know the reader's context)
- Using "we" when talking about Metabase features (use "Metabase" or "it")
- Formal language: "utilize", "reference", "offerings"
- Too peppy: multiple exclamation points
- Burying the action in explanation
- Code examples that don't work
- Numbers that will become outdated
### Quick reference
| Write This | Not This |
| -------------------------- | ------------------ |
| people, companies | users |
| summarize | aggregate |
| take a look at | reference |
| can't, don't | cannot, do not |
| **Filter** button | \`Filter\` button |
| Check out [the docs](link) | Click [here](link) |

View File

@@ -0,0 +1,19 @@
---
name: typescript-review
description: Review TypeScript and JavaScript code changes for compliance with Metabase coding standards, style violations, and code quality issues. Use when reviewing pull requests or diffs containing TypeScript/JavaScript code.
allowed-tools: Read, Grep, Bash, Glob
---
# TypeScript/JavaScript Code Review Skill
@./../_shared/typescript-commands.md
## Code Review Guidelines
Review pull requests with a focus on:
- Compliance with project coding standards and conventions
- Code quality and best practices
- Clear and correct JSDoc comments
- Type safety and proper TypeScript usage
- React best practices (when applicable)

View File

@@ -0,0 +1,9 @@
---
name: typescript-write
description: Write TypeScript and JavaScript code following Metabase coding standards and best practices. Use when developing or refactoring TypeScript/JavaScript code.
---
# TypeScript/JavaScript Development Skill
@./../_shared/development-workflow.md
@./../_shared/typescript-commands.md

View File

@@ -65,8 +65,10 @@
:metabase/missing-test-expr-requires-in-cljs {:level :warning}
:metabase/modules {:level :warning} ; more config in `.clj-kondo/config/modules/config.edn`
:metabase/namespace-name {:level :warning}
:metabase/no-jsqlparser-imports {:level :warning}
:metabase/require-shape-checker {:level :warning}
:metabase/test-helpers-use-non-thread-safe-functions {:level :warning} ; more config in `.clj-kondo/config/test-helpers/config.edn`
:metabase/tests-must-live-in-known-modules {:level :warning}
:metabase/validate-defendpoint-route-uses-kebab-case {:level :warning}
:metabase/validate-defendpoint-query-params-use-kebab-case {:level :warning}
:metabase/validate-logging {:level :warning}
@@ -229,9 +231,6 @@
{:exclude
[(build.uberjar/with-duration-ms)
(cljs.test/is [=? malli=])
(clojure.core.logic/fresh)
(clojure.core.logic/matcha)
(clojure.core.logic/run)
(clojure.test/is [=? malli= qv=])
(clojure.tools.macro/macrolet)
instaparse.core/transform
@@ -298,9 +297,11 @@
metabase.lib.convert/->legacy-MBQL {:message "Conversion to legacy MBQL is discouraged, please use Lib to manipulate MBQL queries"}
metabase.lib.core/->legacy-MBQL {:message "Conversion to legacy MBQL is discouraged, please use Lib to manipulate MBQL queries"}
metabase.lib.equality/find-column-indexes-for-refs {:message "Use lib.equality/closest-matches-in-metadata or lib.equality/find-closest-matches-for-refs instead of lib.equality/find-column-indexes-for-refs"}
metabase-enterprise.transforms.interface/execute! {:message "Use metabase-enterprise.transforms.execute/execute! instead of metabase-enterprise.transforms.interface/execute!"}
next.jdbc/active-tx? {:message "Use metabase.app-db.core/in-transaction? to see if we are in a transaction"}
toucan2.core/debug {:message "Don't commit code using t2/debug"}
toucan2.tools.debug/debug {:message "Don't commit code using t2/debug"}}
toucan2.tools.debug/debug {:message "Don't commit code using t2/debug"}
macaw.core/parsed-query {:message "Use metabase.driver.util/parsed-query instead of macaw.core/parsed-query"}}
:discouraged-namespace
{camel-snake-kebab.core {:message "CSK is not Turkish-safe, use the versions in metabase.util instead."}
@@ -410,7 +411,6 @@
:lint-as
{cljs.cache/defcache clojure.core/deftype
clojure.core.cache/defcache clojure.core/deftype
clojure.core.logic/defne clj-kondo.lint-as/def-catch-all
clojure.test.check.clojure-test/defspec clojure.test/deftest
clojure.test.check.properties/for-all clojure.core/let
clojurewerkz.quartzite.jobs/defjob clojure.core/defn
@@ -452,8 +452,8 @@
metabase.premium-features.settings/define-premium-feature clojure.core/def
metabase.pulse.dashboard-subscription-test/with-dashboard-sub-for-card clojure.core/let
metabase.pulse.send-test/with-pulse-for-card clojure.core/let
metabase.query-processor-test.pipeline-queries-test/pmbql-query clojure.core/->
metabase.query-processor-test.pipeline-queries-test/run-pmbql-query clojure.core/->
metabase.query-processor.pipeline-queries-test/pmbql-query clojure.core/->
metabase.query-processor.pipeline-queries-test/run-pmbql-query clojure.core/->
metabase.query-processor.error-type/deferror clojure.core/def
metabase.query-processor.middleware.cache.impl/with-reducible-deserialized-results clojure.core/let
metabase.query-processor.middleware.process-userland-query-test/with-query-execution! clojure.core/let
@@ -524,8 +524,10 @@
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.dependencies.api-test/with-dependents-test! hooks.common/with-two-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.api-test/with-serialization-test-data! hooks.common/with-three-bindings
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
metabase.api.common.internal-test/with-jetty-server hooks.common/with-one-binding
@@ -543,7 +545,7 @@
metabase.dashboards-rest.api-test/with-simple-dashboard-with-tabs hooks.common/with-one-binding
metabase.dashboards.models.dashboard-tab-test/with-dashtab-in-personal-collection hooks.common/with-one-top-level-binding
metabase.dashboards.models.dashboard-test/with-dash-in-collection! hooks.common/with-three-bindings
metabase.driver.bigquery-cloud-sdk-test/calculate-bird-scarcity hooks.metabase.query-processor-test.expressions-test/calculate-bird-scarcity
metabase.driver.bigquery-cloud-sdk-test/calculate-bird-scarcity hooks.metabase.query-processor.expressions-test/calculate-bird-scarcity
metabase.driver.mongo-test/with-describe-table-for-sample hooks.metabase.driver.mongo-test/with-describe-table-for-sample
metabase.driver.oracle-test/with-temp-user hooks.common/let-one-with-optional-value
metabase.driver/register! hooks.metabase.driver/register!
@@ -580,11 +582,11 @@
metabase.pulse.models.pulse-test/with-dashboard-subscription-in-collection! hooks.common/with-four-bindings
metabase.pulse.models.pulse-test/with-pulse-in-collection! hooks.common/with-four-bindings
metabase.pulse.test-util/checkins-query-card hooks.metabase.test.data/$ids
metabase.queries.api.card-test/with-card-param-values-fixtures hooks.common/let-one-with-optional-value
metabase.queries.api.card-test/with-temp-native-card hooks.common/with-two-bindings
metabase.queries.api.card-test/with-temp-native-card-with-params hooks.common/with-two-bindings
metabase.query-processor-test.expressions-test/calculate-bird-scarcity hooks.metabase.query-processor-test.expressions-test/calculate-bird-scarcity
metabase.query-processor-test.filter-test/count-with-filter-clause hooks.metabase.test.data/$ids
metabase.queries-rest.api.card-test/with-card-param-values-fixtures hooks.common/let-one-with-optional-value
metabase.queries-rest.api.card-test/with-temp-native-card hooks.common/with-two-bindings
metabase.queries-rest.api.card-test/with-temp-native-card-with-params hooks.common/with-two-bindings
metabase.query-processor.expressions-test/calculate-bird-scarcity hooks.metabase.query-processor.expressions-test/calculate-bird-scarcity
metabase.query-processor.filter-test/count-with-filter-clause hooks.metabase.test.data/$ids
metabase.query-processor.middleware.cache-test/with-mock-cache! hooks.common/with-two-bindings
metabase.request.core/with-current-request hooks.common/with-used-first-arg
metabase.request.core/with-current-user hooks.common/with-used-first-arg
@@ -683,7 +685,7 @@
metabase.parameters.chain-filter-test/chain-filter-search macros.metabase.parameters.chain-filter-test/chain-filter
metabase.public-sharing-rest.api-test/with-sharing-enabled-and-temp-card-referencing! macros.metabase.public-sharing-rest.api-test/with-sharing-enabled-and-temp-card-referencing!
metabase.public-sharing-rest.api-test/with-sharing-enabled-and-temp-dashcard-referencing! macros.metabase.public-sharing-rest.api-test/with-sharing-enabled-and-temp-dashcard-referencing!
metabase.queries.api.card-test/with-ordered-items macros.metabase.queries.api.card-test/with-ordered-items
metabase.queries-rest.api.card-test/with-ordered-items macros.metabase.queries-rest.api.card-test/with-ordered-items
metabase.query-analysis.models.query-analysis-test/with-test-setup macros.metabase.query-analysis.models.query-analysis-test/with-test-setup
metabase.query-analysis.task.test-setup/with-test-setup! macros.metabase.query-analysis.task.test-setup/with-test-setup!
metabase.query-processor.streaming/streaming-response macros.metabase.query-processor.streaming/streaming-response
@@ -752,7 +754,10 @@
;; `metabase-enterprise.sandbox.query-processor*-test`
;;
{:pattern "^metabase(?:((?:-enterprise\\.sandbox)?\\.query-processor)|(?:\\.driver\\.sql(?!server)(?!ite))).*-test$"
:name general-qp-and-driver-test-namespaces}]
:name general-qp-and-driver-test-namespaces}
{:pattern "(?:^mage.*)"
:name mage-namespaces}]
:config-in-ns
{test-namespaces
@@ -776,9 +781,10 @@
source-namespaces
{:linters
{:metabase/validate-escaped-single-quotes-in-i18n {:level :warning}
:metabase/validate-string-or-str-args-to-i18n {:level :warning}
:metabase/discourage-millis-duration {:level :warning}
{:metabase/discourage-millis-duration {:level :warning}
:metabase/validate-defendpoint-has-response-schema {:level :warning}
:metabase/validate-escaped-single-quotes-in-i18n {:level :warning}
:metabase/validate-string-or-str-args-to-i18n {:level :warning}
:discouraged-var
{clojure.core/with-redefs {:message "Don't use with-redefs outside of tests"}
@@ -907,6 +913,7 @@
clojure.core/every? {:message "Use metabase.util.performance/every?"}
clojure.core/mapv {:message "Use metabase.util.performance/mapv"}
clojure.core/run! {:message "Use metabase.util.performance/run!"}
clojure.core/get-in {:message "Use metabase.util.performance/get-in"}
clojure.core/select-keys {:message "Use metabase.util.performance/select-keys"}
clojure.core/some {:message "Use metabase.util.performance/some"}
clojure.core/update-keys {:message "Use metabase.util.performance/update-keys"}
@@ -947,4 +954,11 @@
toucan2.tools.with-temp/with-temp {:message "Use lib.tu/mock-metadata-provider in QP tests. Exceptions: tests for code that doesn't use MPs or models not supported by MPs"}}
:metabase/disallow-hardcoded-driver-names-in-tests
{:level :warning}}}}}
{:level :warning}}}
mage-namespaces
{:linters
{:discouraged-java-method
{java.lang.System {exit
{:level :error
:message "Don't use System/exit directly. Instead use mage.util/exit and let mage handle exiting the process"}}}}}}}

View File

@@ -10,7 +10,7 @@
;; ## `team`:
;;
;; The team that owns this module. This has to match one of the team names in `.github/team.json` EXACTLY. You can
;; run [metabase.core.modules-test/all-modules-have-teams-test]] to make sure you did this correctly.
;; run [[metabase.core.modules-test/all-modules-have-teams-test]] to make sure you did this correctly.
;;
;; ## `api`:
;;
@@ -39,6 +39,17 @@
;; 2. A set of module symbols. This is the list of modules that are allowed to be referenced. An empty set means no
;; other modules are allowed to be referenced; this is the default for any modules that aren't listed here.
;;
;; ## `friends`:
;;
;; 'Friend' in the C++ sense; set of modules that are allowed free access into the internals of this module including
;; namespaces that are not `:api` namespaces. This is useful when writing modules that are 'extensions' of other
;; modules, for example `enterprise/search` might be enterprise extensions of `search`, or `search-rest` might be the
;; REST API component for `search`.
;;
;; search
;; {...
;; :friends #{enterprise/search search-rest}}
;;
;; ## Tips
;;
;; PRO TIP: Check out the [[dev.deps-graph]] namespace for helpful tools to see where a module is used externally, and
@@ -93,7 +104,6 @@
config
events
models
premium-features
util}}
analytics
@@ -106,7 +116,6 @@
:uses #{api
app-db
appearance
channel
config
driver
eid-translation
@@ -170,7 +179,8 @@
api-routes
{:team "UX West"
:api #{metabase.api-routes.core}
:api #{metabase.api-routes.cmd
metabase.api-routes.core}
:uses :any}
app-db
@@ -208,8 +218,8 @@
auth-identity
{:team "UX West"
:api #{metabase.auth-identity.core
metabase.auth-identity.init}
:api #{metabase.auth-identity.core
metabase.auth-identity.init}
:uses #{channel
events
login-history
@@ -237,8 +247,7 @@
:api #{metabase.bookmarks.api}
:uses #{api
app-db
config
premium-features
collections
queries
util}}
@@ -352,7 +361,8 @@
{:team "UX West"
:api #{metabase.collections.core
metabase.collections.models.collection
metabase.collections.models.collection.root}
metabase.collections.models.collection.root
metabase.collections.schema}
:uses #{api
api-keys
app-db
@@ -368,11 +378,11 @@
collections-rest
{:team "UX West"
:api #{metabase.collections-rest.api}
:api #{metabase.collections-rest.api
metabase.collections-rest.init}
:uses #{api
app-db
collections
config
eid-translation
events
lib-be
@@ -383,9 +393,24 @@
queries
request
revisions
settings
upload
util}}
comments
{:team "UX West"
:api #{metabase.comments.api
metabase.comments.init}
:uses #{analytics
api
channel
events
models
request
users
users-rest
util}}
;; technically this 'uses' `enterprise/core` and `test` since it tries to load them to see if they exists so we know
;; if EE/test code is available; however we can ignore them since they're not real usages.
config
@@ -480,6 +505,29 @@
:api #{metabase.database-routing.core}
:uses #{premium-features}}
documents
{:team "UX West"
:api #{metabase.documents.api
metabase.documents.core
metabase.documents.init
metabase.documents.prose-mirror
metabase.documents.schema}
:uses #{activity-feed
api
app-db
batch-processing
collections
events
models
public-sharing
queries
query-permissions
query-processor
revisions
search
util
view-log}}
driver
{:team "Drivers"
:api #{metabase.driver
@@ -565,7 +613,6 @@
metabase.embedding.validation}
:uses #{analytics
api
config
premium-features
server
settings
@@ -666,19 +713,16 @@
lib
{:team "Querying"
:api #{metabase.lib.binning
metabase.lib.binning.util
metabase.lib.card
metabase.lib.computed ; temporarily so that `qp.compile` can use it as lib memoization evolves
metabase.lib.convert ; Only so [[metabase.queries.models.card]] can set dynamic vars.
metabase.lib.core
metabase.lib.equality
metabase.lib.field
metabase.lib.field.resolution
metabase.lib.filter
metabase.lib.filter.desugar.jvm ; only so [[metabase.legacy-mbql.jvm-util]] can use defined regexes
metabase.lib.hierarchy
metabase.lib.init
metabase.lib.join.util
metabase.lib.metadata
metabase.lib.metadata.cached-provider
metabase.lib.metadata.column
metabase.lib.metadata.invocation-tracker
metabase.lib.metadata.protocols
metabase.lib.metadata.result-metadata
@@ -699,25 +743,28 @@
metabase.lib.schema.join
metabase.lib.schema.literal
metabase.lib.schema.mbql-clause
metabase.lib.schema.measure
metabase.lib.schema.metadata
metabase.lib.schema.metadata.fingerprint
metabase.lib.schema.middleware-options
metabase.lib.schema.order-by
metabase.lib.schema.parameter
metabase.lib.schema.ref
metabase.lib.schema.settings
metabase.lib.schema.template-tag
metabase.lib.schema.temporal-bucketing
metabase.lib.schema.util
metabase.lib.schema.validate
metabase.lib.temporal-bucket
metabase.lib.types.isa
metabase.lib.util
metabase.lib.util.match
metabase.lib.walk}
:uses #{config
graph
legacy-mbql
types
util}}
util}
:friends #{query-processor}}
lib-be
{:team "Querying"
@@ -752,6 +799,19 @@
settings
util}}
measures
{:team "Querying"
:api #{metabase.measures.api}
:uses #{api
events
lib
lib-be
models
permissions
remote-sync
search
util}}
model-persistence
{:team "Querying"
:api #{metabase.model-persistence.api
@@ -881,11 +941,13 @@
{:team "UX West"
:api #{metabase.permissions-rest.api}
:uses #{api
app-db
audit-app
events
permissions
premium-features
request
settings
util}}
pivot
@@ -911,8 +973,10 @@
app-db
classloader
config
events
internal-stats
settings
task
util}}
product-feedback
@@ -969,6 +1033,7 @@
collections
config
driver
embedding
events
lib
models
@@ -985,11 +1050,10 @@
queries
{:team "Querying"
:api #{metabase.queries.api
metabase.queries.core
:api #{metabase.queries.core
metabase.queries.init
metabase.queries.models.query ; TODO FIXME
metabase.queries.schema} ; TODO FIXME
metabase.queries.schema}
:uses #{analytics
analyze
api
@@ -1001,8 +1065,7 @@
config
content-verification
dashboards
eid-translation
embedding
documents
events
lib
lib-be
@@ -1015,12 +1078,34 @@
query-permissions
query-processor
request
revisions
search
util
view-log
warehouse-schema}}
queries-rest
{:team "Querying"
:api #{metabase.queries-rest.api}
:uses #{analyze
api
collections
eid-translation
embedding
events
lib
lib-be
models
parameters
permissions
public-sharing
queries
query-permissions
query-processor
request
revisions
search
util}}
query-permissions
{:team "UX West"
:api #{metabase.query-permissions.core}
@@ -1118,7 +1203,7 @@
:uses #{api
config
embedding
permissions ; FIXME
permissions ; FIXME
session
settings
users
@@ -1193,11 +1278,11 @@
metabase.segments.schema}
:uses #{api
events
legacy-mbql
lib
lib-be
models
permissions
remote-sync
search
util
xrays}}
@@ -1225,6 +1310,7 @@
session
settings
system
users
util
enterprise/sso}}
@@ -1302,6 +1388,7 @@
permissions
premium-features
settings
system
util}}
startup
@@ -1364,13 +1451,22 @@
metabase.task-history.core
metabase.task-history.init}
:uses #{api
app-db
config
models
permissions
premium-features
query-processor
request
task
util}}
tenants
{:team "Admin Webapp"
:api #{metabase.tenants.core}
:uses #{premium-features
util}}
testing-api
{:team "DevEx"
:api #{metabase.testing-api.api
@@ -1404,7 +1500,6 @@
:uses #{analytics
api
collections
config
events
models
util}}
@@ -1462,6 +1557,7 @@
settings
setup
system
tenants
util}}
users-rest
@@ -1475,10 +1571,13 @@
config
events
models
notification
permissions
premium-features
request
settings
sso
tenants
users
util
enterprise/advanced-permissions}}
@@ -1530,6 +1629,7 @@
api
app-db
audit-app
config
driver
lib
lib-be
@@ -1538,6 +1638,7 @@
permissions
premium-features
query-processor
remote-sync
search
util
warehouses}}
@@ -1554,6 +1655,8 @@
lib
models
parameters
permissions
premium-features
query-processor
request
sync
@@ -1561,7 +1664,6 @@
upload
util
warehouse-schema
warehouses-rest
xrays}}
warehouses
@@ -1613,7 +1715,6 @@
warehouses
enterprise/advanced-permissions}}
xrays
{:team "Querying"
:api #{metabase.xrays.api
@@ -1680,6 +1781,7 @@
premium-features
query-permissions
query-processor
remote-sync
util
warehouses
enterprise/impersonation}}
@@ -1750,6 +1852,8 @@
query-permissions
query-processor
settings
setup
startup
sync
users-rest
util
@@ -1757,7 +1861,7 @@
enterprise/auth-identity
{:team "UX West"
:api #{}
:api #{}
:uses #{premium-features}}
enterprise/auth-provider
@@ -1774,11 +1878,6 @@
store-api
util}}
enterprise/bookmarks
{:team "UX West"
:api #{}
:uses #{}}
enterprise/cache
{:team "UX West"
:api #{metabase-enterprise.cache.init}
@@ -1798,20 +1897,6 @@
util
enterprise/harbormaster}}
enterprise/comments
{:team "UX West"
:api #{metabase-enterprise.comments.api
metabase-enterprise.comments.init}
:uses #{analytics
api
channel
events
models
request
users
users-rest
util}}
enterprise/content-translation
{:team "UX West"
:api #{metabase-enterprise.content-translation.routes}
@@ -1840,6 +1925,22 @@
:api #{}
:uses #{premium-features}}
enterprise/data-studio
{:team "Gadget"
:api #{metabase-enterprise.data-studio.api}
:uses #{api
collections
database-routing
driver
events
models
permissions
premium-features
request
sync
util
warehouse-schema}}
enterprise/database-replication
{:team "Cloud"
:api #{metabase-enterprise.database-replication.api
@@ -1875,8 +1976,10 @@
metabase-enterprise.dependencies.init}
:uses #{analyze
api
app-db
collections
config
documents
driver
events
graph
@@ -1888,34 +1991,12 @@
premium-features
queries
query-processor
request
revisions
settings
task
util
enterprise/documents}}
enterprise/documents
{:team "UX West"
:api #{metabase-enterprise.documents.api
metabase-enterprise.documents.core
metabase-enterprise.documents.init
metabase-enterprise.documents.prose-mirror}
:uses #{activity-feed
api
app-db
batch-processing
collections
events
models
premium-features
public-sharing
queries
query-permissions
query-processor
revisions
search
util
view-log}}
enterprise/transforms}}
enterprise/email
{:team "UX West"
@@ -1934,6 +2015,7 @@
appearance
audit-app
embedding
permissions
premium-features
enterprise/sso}}
@@ -1975,6 +2057,13 @@
:uses #{premium-features
settings}}
enterprise/library
{:team "UX West"
:api #{metabase-enterprise.library.api}
:uses #{api
collections
premium-features}}
enterprise/llm
{:team "Metabot"
:api #{metabase-enterprise.llm.api
@@ -2001,6 +2090,7 @@
audit-app
collections
config
documents
driver
legacy-mbql
lib
@@ -2024,7 +2114,6 @@
warehouse-schema
warehouses-rest
enterprise/dependencies
enterprise/documents
enterprise/transforms
enterprise/transforms-python}}
@@ -2044,17 +2133,6 @@
:uses #{premium-features
util}}
enterprise/public-sharing
{:team "UX West"
:api #{metabase-enterprise.public-sharing.api}
:uses #{api
events
premium-features
public-sharing
public-sharing-rest
query-processor
util}}
enterprise/remote-sync
{:team "UX West"
:api #{metabase-enterprise.remote-sync.api
@@ -2089,6 +2167,7 @@
premium-features
query-processor
request
tenants
users
util
warehouse-schema
@@ -2150,6 +2229,8 @@
app-db
appearance
collections
config
events
logger
models
plugins
@@ -2175,7 +2256,6 @@
:uses #{api
appearance
auth-identity
channel
embedding
premium-features
request
@@ -2201,6 +2281,34 @@
settings
util}}
enterprise/support-access-grants
{:team "UX West"
:api #{metabase-enterprise.support-access-grants.api
metabase-enterprise.support-access-grants.init}
:uses #{api
auth-identity
events
models
request
settings
system
util}}
enterprise/tenants
{:team "Admin Webapp"
:api #{metabase-enterprise.tenants.api}
:uses #{api
audit-app
auth-identity
collections
events
models
permissions
premium-features
request
settings
util}}
enterprise/transforms
{:team "Querying"
:api #{metabase-enterprise.transforms.api
@@ -2208,10 +2316,13 @@
metabase-enterprise.transforms.init
metabase-enterprise.transforms.instrumentation
metabase-enterprise.transforms.interface
metabase-enterprise.transforms.schema
metabase-enterprise.transforms.util}
:uses #{analytics
api
app-db
channel
collections
driver
events
lib
@@ -2220,7 +2331,9 @@
premium-features
queries
query-processor
remote-sync
request
revisions
search
settings
sync
@@ -2237,6 +2350,8 @@
app-db
config
driver
lib
lib-be
query-processor
settings
util

View File

@@ -1,4 +1,4 @@
(ns macros.metabase.queries.api.card-test)
(ns macros.metabase.queries-rest.api.card-test)
(defmacro with-ordered-items
[collection model-and-name-syms & body]

View File

@@ -1,9 +0,0 @@
(ns macros.metabase.server.statistics-handler-test)
(defmacro with-server
[_ _ [connector chan-start-handle chan-finish-handle chan-done-request] & body]
`(let [~connector nil
~chan-start-handle nil
~chan-finish-handle nil
~chan-done-request nil]
~@body))

View File

@@ -99,12 +99,48 @@
:message "Metabase namespaces should have the form metabase[-enterprise].<module>.* [:metabase/namespace-name]"
:type :metabase/namespace-name)))))))
(defn- ns-form-node->import-node [ns-form-node]
(some (fn [node]
(when (and (hooks/list-node? node)
(let [first-child (first (:children node))]
(and (hooks/keyword-node? first-child)
(= (hooks/sexpr first-child) :import))))
node))
(:children ns-form-node)))
(defn- jsqlparser-import?
"Check if a symbol or string represents a jsqlparser import."
[s]
(str/starts-with? (str s) "net.sf.jsqlparser"))
(defn- lint-jsqlparser-imports [ns-form-node]
(when-let [import-node (ns-form-node->import-node ns-form-node)]
(doseq [node (rest (:children import-node))
:when (not (contains? (hooks.common/ignored-linters node) :metabase/no-jsqlparser-imports))]
(cond
;; Handle (net.sf.jsqlparser.foo Bar Baz) form
(hooks/list-node? node)
(let [package-node (first (:children node))
package-name (when package-node (str (hooks/sexpr package-node)))]
(when (jsqlparser-import? package-name)
(hooks/reg-finding! (assoc (meta node)
:message "Don't import net.sf.jsqlparser classes directly. This code should be agnostic to the parsing library. [:metabase/no-jsqlparser-imports]"
:type :metabase/no-jsqlparser-imports))))
;; Handle net.sf.jsqlparser.foo.Bar form (single class import)
(hooks/token-node? node)
(when (jsqlparser-import? (hooks/sexpr node))
(hooks/reg-finding! (assoc (meta node)
:message "Don't import net.sf.jsqlparser classes directly. This code should be agnostic to the parsing library. [:metabase/no-jsqlparser-imports]"
:type :metabase/no-jsqlparser-imports)))))))
(defn lint-ns [x]
(doto (:node x)
lint-require-shapes
lint-requires-on-new-lines
(lint-modules (modules/config x))
lint-namespace-name)
lint-namespace-name
lint-jsqlparser-imports)
x)
(comment

View File

@@ -2,7 +2,8 @@
(:require
[clj-kondo.hooks-api :as hooks]
[clojure.string :as str]
[hooks.common]))
[hooks.common]
[hooks.common.modules :as modules]))
(defn- warn-about-disallowed-parallel-forms [form config]
(letfn [(error! [form message]
@@ -102,7 +103,39 @@
(:children node))))]
(walk node)))
(defn deftest [{:keys [node cljc lang config]}]
(defn- test-namespace-lives-outside-of-module-system? [ns-symb]
(some (fn [prefix]
(str/starts-with? (name ns-symb) prefix))
["build-drivers."
"build."
"i18n." ; bin/i18n
"lint-migrations-file-test"
"main-test" ; bin/release-list
"metabase.deps-edn-test"
"metabase.driver."
"metabase.test."
"metabase.test.data."
"metabuild-common."])) ; utils for build scripts
(let [warned-namespaces (atom #{})]
(defn deftest-check-in-valid-module
"Check whether a `deftest` lives in a known module -- important so our system to only run a subset of tests based on
which modules have changes picks them up correctly. (DEV-1125)"
[{:keys [node], ns-symb :ns, :as input}]
(when (and ns-symb
(not (test-namespace-lives-outside-of-module-system? ns-symb))
;; only warn once per namespace
(not (contains? @warned-namespaces ns-symb)))
(swap! warned-namespaces conj ns-symb)
(let [known-modules (set (keys (:metabase/modules (modules/config input))))
current-module (modules/module ns-symb)]
(when (or (not current-module)
(not (contains? known-modules current-module)))
(hooks/reg-finding! (assoc (meta node)
:message (format "All tests must live in a known module; %s is not a known module" (pr-str current-module))
:type :metabase/tests-must-live-in-known-modules)))))))
(defn deftest [{:keys [node cljc lang config], :as input}]
;; run [[deftest-check-parallel]] only once... if this is a `.cljc` file only run it for the `:clj` analysis, no point
;; in running it twice.
(when (or (not cljc)
@@ -110,7 +143,8 @@
(deftest-check-parallel node (get-in config [:linters :metabase/validate-deftest])))
(deftest-check-not-horrifically-long node (get-in config [:linters :metabase/i-like-making-cams-eyes-bleed-with-horrifically-long-tests]))
(deftest-check-no-driver-keywords node (get-in config [:linters :metabase/disallow-hardcoded-driver-names-in-tests]))
{:node node})
(deftest-check-in-valid-module input)
input)
;;; this is a hacky way to determine whether these namespaces are required in the `ns` form or not... basically `:ns`
;;; will come back as `nil` if they are not.

View File

@@ -1,4 +1,6 @@
(ns hooks.common.modules)
(ns hooks.common.modules
(:require
[clojure.string :as str]))
(defn ignored-namespace? [config ns-symb]
(some
@@ -17,14 +19,19 @@
(module 'metabase-enterprise.whatever.core) => enterprise/whatever"
[ns-symb]
{:pre [(simple-symbol? ns-symb)]}
(or (some->> (re-find #"^metabase-enterprise\.([^.]+)" (str ns-symb))
second
(symbol "enterprise"))
(some-> (re-find #"^metabase\.([^.]+)" (str ns-symb))
second
symbol)))
;; treat something like `metabase.driver-test` (for a module that hasn't fully been updated to use `.core`
;; namespaces) as being in the `driver` module
(let [ns-symb (if (str/ends-with? (name ns-symb) "-test")
(symbol (str/replace (name ns-symb) #"-test$" ""))
ns-symb)]
(or (some->> (re-find #"^metabase-enterprise\.([^.]+)" (str ns-symb))
second
(symbol "enterprise"))
(some-> (re-find #"^metabase\.([^.]+)" (str ns-symb))
second
symbol))))
(defn module-api-namespaces
(defn- module-api-namespaces
"Set of API namespace symbols for a given module. `:any` means you can use anything, there are no API namespaces for
this module (yet). If unspecified, the default is just the `<module>.core` namespace."
[config module]
@@ -44,6 +51,12 @@
(symbol (str ns-prefix ".core"))
(symbol (str ns-prefix ".init"))}))))
(defn- module-friends
[config module]
"Set of modules that are `:friends` of `module`, i.e. allowed to use *any* namespace from the module, not just the
designated [[module-api-namespaces]]."
(set (get-in config [:metabase/modules module :friends])))
(defn allowed-modules
"Set of namespace symbols that `module` is allowed to use. `:any` means it's allowed to use anything."
[config module]
@@ -54,11 +67,13 @@
(or (= allowed-modules :any)
(contains? (set allowed-modules) required-module))))
(defn allowed-module-namespace? [config ns-symb]
(defn- allowed-module-namespace? [config current-module ns-symb]
(let [module (module ns-symb)
module-api-namespaces (module-api-namespaces config module)]
module-api-namespaces (module-api-namespaces config module)
module-friends (module-friends config module)]
(or (empty? module-api-namespaces)
(contains? module-api-namespaces ns-symb))))
(contains? module-api-namespaces ns-symb)
(contains? module-friends current-module))))
(defn usage-error
"Find usage errors when a `required-namespace` is required in the `current-module`. Returns a string describing the
@@ -74,7 +89,7 @@
current-module
current-module)
(not (allowed-module-namespace? config required-namespace))
(not (allowed-module-namespace? config current-module required-namespace))
(format "Namespace %s is not an allowed external API namespace for the %s module. [:metabase/modules %s :api]"
required-namespace
required-module

View File

@@ -90,6 +90,10 @@
:else
(recur (conj bindings x) (conj schemas nil) (list* y z more)))))]
(validate-route! route)
(when-not result-schema
(api/reg-finding! (assoc (meta node)
:message "All REST API endpoints should have a detailed response schema"
:type :metabase/validate-defendpoint-has-response-schema)))
(let [[_route-param-schema query-param-schema _body-param-schema] schemas]
(when query-param-schema
(validate-query-params! query-param-schema)))

View File

@@ -1,4 +1,4 @@
(ns hooks.metabase.query-processor-test.expressions-test
(ns hooks.metabase.query-processor.expressions-test
(:require
[clj-kondo.hooks-api :as hooks]
[hooks.metabase.test.data :as data]))

View File

@@ -97,7 +97,6 @@
metabot-get-prompt-templates-url
metabot-prompt-generator-token-limit
multi-setting-read-only
notebook-native-preview-shown
notebook-native-preview-sidebar-width
notification-link-base-url
num-metabot-choices
@@ -119,10 +118,10 @@
reset-token-ttl-hours
retired-setting
retry-initial-interval
retry-max-attempts
retry-max-retries
retry-max-interval-millis
retry-multiplier
retry-randomization-factor
retry-jitter-factor
saml-application-name
saml-attribute-email
saml-attribute-firstname

View File

@@ -43,6 +43,17 @@
'{:metabase/modules {api {:uses #{search}}
search {:api #{metabase.search.core}}}}))))
(deftest ^:parallel module-checker-friends-test
(is (= []
(lint-modules
'(ns metabase.search-rest.api
(:require
[metabase.search.config :as search.config]
[metabase.search.core :as search]))
'{:metabase/modules {search {:api #{metabase.search.core}
:friends #{search-rest}}
search-rest {:uses #{search}}}}))))
(deftest ^:parallel module-checker-api-namespaces-ignore-test
(is (empty? (lint-modules
'(ns metabase.api.search

View File

@@ -43,9 +43,6 @@
with-meta [[:default]]
;; library stuff. Libraries that specify their own `:style/indent` specs are included in the section after this
;; since it is generated automatically.
clojure.core.logic/fresh [[:block 1]]
clojure.core.logic/matcha [[:block 1]]
clojure.core.logic/run [[:block 2]]
clojure.core.match/match [[:block 1]]
clojure.test.check.properties/for-all [[:block 1]]
clojure.test.check.properties/for-all* [[:block 1]]
@@ -176,21 +173,23 @@
metabase.pulse.dashboard-subscription-test/with-link-card-fixture-for-dashboard [[:block 2]]
metabase.pulse.models.pulse-test/with-dashboard-subscription-in-collection [[:block 1]]
metabase.pulse.models.pulse-test/with-pulse-in-collection [[:inner 0]]
metabase.queries.api.card-test/with-cards-in-readable-collection [[:block 1]]
metabase.queries.api.card-test/with-cards-in-writeable-collection [[:block 1]]
metabase.queries.api.card-test/with-ordered-items [[:inner 0]]
metabase.queries.api.card-test/with-temp-native-card [[:block 1]]
metabase.queries.api.card-test/with-temp-native-card-with-params [[:block 1]]
metabase.query-processor-test.pipeline-queries-test/pmbql-query [[:block 1]]
metabase.query-processor-test.pipeline-queries-test/run-pmbql-query [[:block 1]]
metabase.queries-rest.api.card-test/with-cards-in-readable-collection [[:block 1]]
metabase.queries-rest.api.card-test/with-cards-in-writeable-collection [[:block 1]]
metabase.queries-rest.api.card-test/with-ordered-items [[:inner 0]]
metabase.queries-rest.api.card-test/with-temp-native-card [[:block 1]]
metabase.queries-rest.api.card-test/with-temp-native-card-with-params [[:block 1]]
metabase.query-processor.debug/debug> [[:block 0]]
metabase.query-processor.error-type/deferror [[:block 1]]
metabase.query-processor.middleware.cache-backend.interface/with-cached-results [[:block 4]]
metabase.query-processor.middleware.process-userland-query-test/with-query-execution [[:block 1]]
metabase.query-processor.pipeline-queries-test/pmbql-query [[:block 1]]
metabase.query-processor.pipeline-queries-test/run-pmbql-query [[:block 1]]
metabase.query-processor.store/cached [[:block 1]]
metabase.query-processor.store/with-metadata-provider [[:inner 0]]
metabase.query-processor.streaming/streaming-response [[:block 1]]
metabase.query-processor.test-util/format-rows-by [[:default]]
metabase.query-processor.timeseries-test.util/test-timeseries-drivers [[:block 0]]
metabase.query-processor.timeseries-test/run-mbql-query [[:inner 0]]
metabase.request.core/as-admin [[:block 0]]
metabase.request.core/with-current-request [[:inner 0]]
metabase.request.core/with-current-user [[:inner 0]]
@@ -278,12 +277,9 @@
metabase.test/with-temp-vals-in-db [[:block 3]]
metabase.test/with-test-user [[:inner 0]]
metabase.test/with-user-in-groups [[:inner 0]]
metabase.timeseries-query-processor-test.util/test-timeseries-drivers [[:block 0]]
metabase.timeseries-query-processor-test/run-mbql-query [[:inner 0]]
metabase.upload.impl-test/with-upload-table! [[:inner 0]]
metabase.upload.types/with-currency [[:default]]
metabase.upload.types/with-parens [[:default]]
metabase.util/for-map [[:block 1]]
metabase.util.async/cancelable-thread [[:block 0]]
metabase.util.date-2/with-time-zone-same-instant [[:default]]
metabase.util.encryption-test/with-secret-key [[:block 1]]
@@ -304,6 +300,7 @@
metabase.util.queue-test/await-test-while [[:block 1]]
metabase.util/auto-retry [[:block 1]]
metabase.util/case-enum [[:block 1]]
metabase.util/for-map [[:block 1]]
metabase.util/ignore-exceptions [[:block 0]]
metabase.util/or-with [[:block 1]]
metabase.util/profile [[:block 1]]

View File

@@ -1,23 +1,35 @@
Brite
afterAll
ags
altho
Brite
cancelation
cancelations
caracteres
copyin
datas
edn
eduction
hasTable
hasTables
horizontalX
horizontalY
juxt
methodd
nd
notIn
optionA
ot
pass-thru
requestor
re-use
re-used
ser
serieses
sortings
titel
trs
trsn
tru
trun
unparseable
withs

View File

@@ -1,3 +1,24 @@
[codespell]
skip = *.csv,*.edn,*.geojson,*.json,*.tsv,*.xml,docs/developers-guide/drivers/driver-tests.md,docs/developers-guide/e2e-tests.md,docs/questions/query-builder/expressions-list.md,docs/questions/visualizations/country-codes.md,e2e/test/scenarios/admin/i18n/content-translation/constants.ts,frontend/src/cljs,frontend/src/metabase/querying/expressions/tokenizer/lezer.js,frontend/src/metabase/static-viz/constants/char-sizes.ts,frontend/src/metabase/visualizations/lib/mapping_codes.ts,modules/drivers/mongo/src/metabase/driver/mongo/operators.clj
skip =
*.csv,
*.edn,
*.geojson,
*.json,
*.tsv,
*.unit.spec.*,
*.xml,
docs/developers-guide/drivers/driver-tests.md,
docs/developers-guide/e2e-tests.md,
docs/questions/query-builder/expressions-list.md,
docs/questions/visualizations/country-codes.md,
e2e/test/scenarios/admin/i18n/content-translation/constants.ts,
frontend/src/cljs,
frontend/src/metabase/querying/expressions/tokenizer/lezer.js,
frontend/src/metabase/query_builder/components/NativeQueryEditor/CodeMirrorEditor/language.ts,
frontend/src/metabase/static-viz/constants/char-sizes.ts,
frontend/src/metabase/visualizations/lib/mapping_codes.ts,
frontend/*/mocks/*,
modules/drivers/mongo/src/metabase/driver/mongo/operators.clj,
src/metabase/analyze/classifiers/name.clj,
src/metabase/util/currency.cljc,
ignore-words = .codespellignore

160
.env.example Normal file
View File

@@ -0,0 +1,160 @@
# ==============================================================================
# 0. METABASE DEVELOPMENT ENVIRONMENT
# ==============================================================================
#
# Central configuration for local Metabase development.
# Copy to .env and uncomment/modify values as needed.
#
# Usage:
# op inject --in-file .env.example --out-file .env (populate using CLI)
# cp .env.example .env (populate manually)
#
# Hint: Auto-load environment variables with mise or direnv:
# mise - mise.toml: [settings] env_file = ".env" (https://mise.jdx.dev)
# direnv - Create .envrc with: dotenv .env (https://direnv.net)
#
# Full Metabase environment configuration reference:
# https://www.metabase.com/docs/latest/configuring-metabase/environment-variables
#
# ⚠️ Make sure the same var is not exported multiple times in different contexts.
# ==============================================================================
# 1. GLOBAL CONTEXT
# ==============================================================================
#
# Shared credentials and tokens used across multiple dev workflows.
# GitHub - For gh CLI, API access, and CI integrations
# https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
# GITHUB_TOKEN=your-PAT
# AWS - For S3, Athena, Redshift, and other AWS services
# https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
# AWS_ACCESS_KEY_ID=your-access-key
# AWS_SECRET_ACCESS_KEY=your-secret-key
# AWS_REGION=us-east-1
# Docker Hub - Avoid rate limits when pulling images
# https://docs.docker.com/security/for-developers/access-tokens/
# DOCKER_USERNAME=your-username
# DOCKER_PASSWORD=your-access-token
# ==============================================================================
# 2. LOCAL METABASE DEVELOPMENT
# ==============================================================================
#
# Settings for running Metabase locally. Most have sensible defaults—only
# configure what you need.
# 2.1 Application Database
# ------------------------------------------------------------------------------
# Where Metabase stores its own data (dashboards, users, settings, etc.).
# https://www.metabase.com/docs/latest/installation-and-operation/configuring-application-database
# Option A: Individual connection parameters
# MB_DB_TYPE="postgres"
# MB_DB_HOST="localhost"
# MB_DB_PORT=5432
# MB_DB_DBNAME="metabase"
# MB_DB_USER="<username>"
# MB_DB_PASS="<password>"
# Option B: Single connection URI (overrides individual params)
# MB_DB_CONNECTION_URI="jdbc:postgresql://localhost:5432/metabase?user=<username>&password=<password>"
# 2.2 Server & Integrations
# ------------------------------------------------------------------------------
# https://www.metabase.com/docs/latest/configuring-metabase/customizing-jetty-webserver
# Jetty server (defaults: localhost:3000)
# MB_JETTY_HOST="localhost"
# MB_JETTY_PORT=3000
# SMTP for testing email notifications (use with maildev/maildev container)
MB_EMAIL_SMTP_HOST="localhost"
MB_EMAIL_SMTP_PORT=1025
MB_EMAIL_SMTP_USERNAME="admin"
MB_EMAIL_SMTP_PASSWORD="admin"
# 2.3 Feature Flags & Tokens
# ------------------------------------------------------------------------------
# Use staging server for license validation (avoids hitting production)
METASTORE_DEV_SERVER_URL="https://token-check.staging.metabase.com"
# Metabase license token
# Uncomment this line only when running local dev and NEVER when running Cypress
# Tests need to start from zero, and set different tokens programmatically (on-demand)
# MB_PREMIUM_EMBEDDING_TOKEN="op://Shared/Metabase License Dev Tokens/Licenses/MB_ALL_FEATURES_TOKEN"
# Skip embedding SDK build for faster frontend compilation
# SKIP_EMBEDDING_SDK="true"
# ==============================================================================
# 3. E2E / CYPRESS TESTING
# ==============================================================================
#
# Configuration for running Cypress end-to-end tests locally.
#
# The whole environment is already orchestrated via deps.edn using :e2e alias.
# Treat it as a source of truth for JVM flags and ENVs whether you decide to run
# backend on your own, or using `yarn test-cypress` (local test runner).
#
# You don't _have to_ export any of these vars (except for the tokens below).
# Things will still work.
# 3.1. E2E Application Database (H2 required)
# ------------------------------------------------------------------------------
# Whether to run the enterprise or the open-source Metabase version
MB_EDITION="ee"
# Which file to use for the ephemeral testing application database?
# MB_DB_FILE="./e2e/tmp/cypress-test.db"
# Where does Cypress go to look for the application? (defaults: localhost:4000)
# MB_JETTY_HOST="localhost"
# MB_JETTY_PORT=4000
# 3.2 E2E Local Runner Setup
# ------------------------------------------------------------------------------
# Whether to run true e2e test suite, or SDK component tests (e2e | component)
CYPRESS_TESTING_TYPE="e2e"
# Whether to start Cypress in an interactive (open) mode with full GUI
CYPRESS_GUI="true"
# Whether to generate application database dumps (colloquially "snapshots")
# Keep this enabled unless you're experimenting, or know what you're doing.
GENERATE_SNAPSHOTS="true"
# E2E tests run the backend from source by default.
# To run tests against a JAR instead, set the JAR_PATH variable.
#
# Hint: build the JAR with ./bin/build.sh
# JAR_PATH="target/uberjar/metabase.jar"
# 3.3 E2E Tokens
# ------------------------------------------------------------------------------
#
# These make sense for Metabase core devs only
# op inject --in-file .env.example --out-file .env
CYPRESS_MB_ALL_FEATURES_TOKEN="op://Shared/Metabase License Dev Tokens/Licenses/MB_ALL_FEATURES_TOKEN"
CYPRESS_MB_STARTER_CLOUD_TOKEN="op://Shared/Metabase License Dev Tokens/Licenses/MB_STARTER_CLOUD_TOKEN"
CYPRESS_MB_PRO_CLOUD_TOKEN="op://Shared/Metabase License Dev Tokens/Licenses/MB_PRO_CLOUD_TOKEN"
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN="op://Shared/Metabase License Dev Tokens/Licenses/MB_PRO_SELF_HOSTED_TOKEN"
# 3.4 E2E Misc.
# ------------------------------------------------------------------------------
# To make Node.js match the instance tz
TZ="US/Pacific"
# Export this environment variable when running tests on Apple Silicon.
# DO NOT USE Docker Desktop. Use Orbstack instead. Metabase will fail to connect
# to the dockerized Mongo QA database otherwise.
EXPERIMENTAL_DOCKER_DESKTOP_FORCE_QEMU=1

View File

@@ -2,4 +2,5 @@ frontend/src/cljs
frontend/src/cljs_release
e2e/support/cypress_sample_database.js
e2e/support/cypress_sample_instance_data.js
frontend/src/metabase-types/openapi/types.gen.ts
e2e/embedding-sdk-host-apps

View File

@@ -180,6 +180,7 @@ module.exports = {
"no-unconditional-metabase-links-render": "error",
"no-color-literals": "error",
"no-literal-metabase-strings": "error",
"no-oss-reinitialize-import": "error",
"depend/ban-dependencies": [
"error",
{
@@ -240,6 +241,7 @@ module.exports = {
plugins: ["@typescript-eslint"],
rules: {
"prefer-rest-params": "off",
"react/prop-types": "off", // TypeScript handles prop validation
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-explicit-any": "off",
@@ -344,5 +346,11 @@ module.exports = {
"import/no-commonjs": "off",
},
},
{
files: ["**/*.stories.tsx", "**/preview.tsx"],
rules: {
"import/no-default-export": "off",
},
},
],
};

7
.gitattributes vendored Normal file
View File

@@ -0,0 +1,7 @@
# Custom merge driver for YAML migration files
# Treats each changeset as an atomic unit to avoid conflicts within changesets
# Execute this in your shell to enable custom merge driver:
# echo '\n[include]\npath=../.gitconfig' >> .git/config
#
# TODO (Bryan 12/12/25) -- reenable this when we can completely verify correctness
# resources/migrations/*.yaml merge=yaml-migrations

7
.gitconfig Normal file
View File

@@ -0,0 +1,7 @@
# execute this in your shell to enable custom merge driver:
# echo '\n[include]\npath=../.gitconfig' >> .git/config
#
# TODO (Bryan 12/12/25) -- reenable this when we can completely verify correctness
# [merge "yaml-migrations"]
# name = YAML migration changeset-aware merge
# driver = mage -merge-yaml-migrations %O %A %B %L %P

View File

@@ -1,23 +0,0 @@
---
name: Epic (Internal Use)
about: This issue is used to track a feature/project that may span several days
to weeks to implement. This is used by the core Metabase team to project plan
and manage work.
title: "[Epic] Title"
labels: ".Epic"
---
### Links
- [product doc](LINK_TO_PRODUCT_DOC)
- [technical design doc](LINK_TO_TECHNICAL_DESIGN_DOC)
- [testing plan](LINK_TO_TESTING_PLAN)
- feature branch: `BRANCH_NAME`
- issue links: _related issues, if any_
### Implementation Plan
```[tasklist]
#### Milestone 1
- [ ] _Add tasks here_
```

View File

@@ -7,16 +7,13 @@ assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**What problem will this feature request solve?**
**Describe the solution you'd like**
**Describe the solution you'd like.**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**How does this feature request impact you?**
For example, is it a minor inconvenience, or does it block important work?
**How important is this feature to you?**
**Additional context**
**Additional information**
Add any other context or screenshots about the feature request here.

View File

@@ -1,14 +0,0 @@
---
name: Task (Internal Use)
about: This issue is used to track a smaller feature/task that does not require
being broken down to milestones. This is used by the core Metabase team to
project plan and manage work.
labels: ".Task"
---
**Context**
- issue links: _related issues if any_

View File

@@ -25,3 +25,4 @@ _Upload a demo video or before/after screenshots if sensible or remove the secti
### Checklist
- [ ] Tests have been added/updated to cover changes in this PR
- [ ] If adding new Loki tests: they pass [stress testing](https://github.com/metabase/metabase/actions/workflows/loki-stress-test-flake-fix.yml)

View File

@@ -13,6 +13,9 @@ outputs:
eslint-cache-key:
description: "The cache key for Eslint cache"
value: ${{ steps.keys-factory.outputs.eslint-cache-key }}
cypress-cache-key:
description: "The cache key for Cypress cache"
value: ${{ steps.keys-factory.outputs.cypress-cache-key }}
runs:
using: "composite"
@@ -23,10 +26,12 @@ runs:
M2_CACHE_PREFIX='M2'
NODE_CACHE_PREFIX='node-modules'
ESLINT_CACHE_PREFIX='eslint'
CYPRESS_CACHE_PREFIX='cypress'
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
echo "eslint-cache-key=$ESLINT_CACHE_PREFIX-$CACHE_SUFFIX" >> $GITHUB_OUTPUT
echo "cypress-cache-key=$CYPRESS_CACHE_PREFIX-$CACHE_SUFFIX" >> $GITHUB_OUTPUT
shell: bash

View File

@@ -0,0 +1,19 @@
name: Maximize disk space
description: Removes unused stuff from GH runner
runs:
using: "composite"
steps:
- name: Maximize build space
shell: bash
run: |
echo "-- Dotnet"
sudo rm -rf /usr/share/dotnet
echo "-- Android"
sudo rm -rf /usr/local/lib/android
echo "-- Haskell"
sudo rm -rf /opt/ghc
echo "-- CodeQL"
sudo rm -rf /opt/hostedtoolcache/CodeQL
df -h

View File

@@ -25,11 +25,6 @@ runs:
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: Get M2 cache key
uses: ./.github/actions/get-cache-keys
id: get-cache-keys

View File

@@ -22,16 +22,16 @@ runs:
chrome-version: 1097615
id: setup-chrome
- name: Get current week of year
id: get-date
run: |
echo "week-of-year=$(/bin/date "+%G-%V")" >> $GITHUB_OUTPUT
shell: bash
- name: Get cache keys
uses: ./.github/actions/get-cache-keys
id: get-cache-keys
- name: Get Cypress cache
uses: actions/cache@v4
uses: actions/cache/restore@v4
with:
path: ~/.cache/Cypress
key: ${{ runner.os }}-Cypress-${{ steps.get-date.outputs.week-of-year }}
key: ${{ steps.get-cache-keys.outputs.cypress-cache-key }}
- name: Ensure that Cypress executable is ready
run: |
yarn cypress install

View File

@@ -1,4 +1,5 @@
name: Prepare front-end environment
description: "Prepare the front-end environment for the CI build"
inputs:
node-version:
description: "The version of Node.js to use, overriding .nvmrc"
@@ -6,7 +7,7 @@ inputs:
apply-patches:
description: "Whether to patch frontend dependencies with patch-package."
required: true
default: 'true'
default: "true"
runs:
using: "composite"
steps:
@@ -28,11 +29,21 @@ runs:
~/.gitlibs
key: ${{ steps.get-cache-keys.outputs.m2-cache-key }}
- name: Get yarn cache directory
id: yarn-cache-dir
run: |
YARN_CACHE_DIR=$(yarn cache dir)
echo "Yarn cache directory: $YARN_CACHE_DIR"
echo "dir=$YARN_CACHE_DIR" >> $GITHUB_OUTPUT
shell: bash
- name: Restore node_modules cache
uses: actions/cache/restore@v4
id: node-modules-cache
with:
path: node_modules
path: |
${{ steps.yarn-cache-dir.outputs.dir }}
node_modules
key: ${{ steps.get-cache-keys.outputs.node-cache-key }}
# postinstall lifecycle hook can be dangerous in CI so we only run it locally (see package.json)

View File

@@ -9,6 +9,9 @@ inputs:
build-static-viz:
required: true
default: false
logs-artifact-suffix:
required: false
description: Suffix to append to the test logs artifact name to avoid conflicts in matrix jobs
runs:
using: "composite"
@@ -16,12 +19,12 @@ runs:
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
if: ${{ inputs.build-static-viz == 'true' }}
uses: ./.github/actions/prepare-frontend
- name: Build static viz frontend
if: ${{ inputs.build-static-viz == 'true' }}
run: yarn build-static-viz
shell: bash
if: ${{ inputs.build-static-viz == 'true' }}
env:
MB_EDITION: ee
- name: Test database driver
@@ -37,7 +40,7 @@ runs:
# As per the documentation: https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#steps-context
# test.outcome gives us access to the result before `continue-on-error` overrides it and sets it to 'success'.
# We want test reports even if the test step gets cancelled (e.g. times out), hence we match anything that is not a 'success'.
if: steps.run-test.outcome != 'success'
if: ${{ steps.run-test.outcome != 'success' }}
with:
path: "target/junit/**/*_test.xml"
name: JUnit Test Report ${{ inputs.junit-name }}
@@ -49,7 +52,7 @@ runs:
if: always() && steps.run-test.outcome != 'success'
uses: actions/upload-artifact@v4
with:
name: test-logs-${{ github.job }}
name: ${{ format('test-logs-{0}{1}', github.job, (inputs.logs-artifact-suffix == '' || inputs.logs-artifact-suffix == null) && '' || format('-{0}', inputs.logs-artifact-suffix)) }}
path: logs/test-log.json
retention-days: 1
# Failing to upload the artifact should never affect the outcome of the whole test run.

View File

@@ -20,7 +20,7 @@ inputs:
required: true
variant:
required: false
default: ''
default: ""
runs:
using: "composite"
@@ -56,3 +56,4 @@ runs:
org-slug: metabase
dry-run: ${{ github.event_name == 'pull_request' && github.event.pull_request.draft == true }} # quarantine, but do not upload results
token: ${{ inputs.trunk-api-token }}
use-cache: true

View File

@@ -11,15 +11,19 @@ shared_specs: &shared_specs
- "test/**/*.cljc"
- "test/**/*.cljs"
frontend_ci: &frontend_ci
shared_ci: &shared_ci
- ".github/actions/prepare-frontend/**"
- ".github/actions/prepare-backend/**"
- ".github/workflows/frontend.yml"
- ".github/workflows/run-tests.yml"
frontend_embedding_sdk_ci: &frontend_embedding_sdk_ci
- ".github/actions/prepare-frontend/**"
- ".github/actions/prepare-backend/**"
- ".github/workflows/*embedding-sdk*.yml"
shared_e2e: &shared_e2e
- "e2e/runner/**"
- "e2e/snapshot-creators/**"
- "e2e/support/**"
frontend_ci: &frontend_ci
- *shared_ci
- ".github/workflows/frontend.yml"
frontend_configs: &frontend_configs
- "yarn.lock"
@@ -41,14 +45,12 @@ frontend_sources: &frontend_sources
- "enterprise/frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
- "frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
# Used only in .github/workflows/conventional-commit-pr-title-reminder.yml
frontend_embedding_sources:
- "enterprise/frontend/src/{embedding,embedding-*}/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
- "enterprise/frontend/src/metabase-enterprise/{embedding,embedding-*}**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
frontend_embedding_sdk_sources:
- *frontend_configs
- "enterprise/frontend/!(test)**/**/{!(*.spec),}.{js,jsx,ts,tsx,css}"
# Used only in .github/workflows/embedding-sdk-labels-reminder.yml
frontend_embedding_sdk_package_sources:
- "enterprise/frontend/src/embedding-sdk-package/**/!(*.spec).{js,jsx,ts,tsx,css}"
@@ -76,8 +78,7 @@ frontend_loki_ci: &frontend_loki_ci
- ".storybook/**"
backend_ci: &backend_ci
- ".github/actions/prepare-frontend/**"
- ".github/actions/prepare-backend/**"
- *shared_ci
- ".github/actions/test-driver/**"
- ".github/workflows/backend.yml"
- ".github/workflows/drivers.yml"
@@ -117,9 +118,9 @@ sources: &sources
- *backend_sources
e2e_ci: &e2e_ci
- ".github/actions/prepare-frontend/**"
- ".github/actions/prepare-backend/**"
- *shared_ci
- ".github/actions/prepare-uberjar-artifact/**"
- ".github/actions/fetch-artifact/action.yml"
- ".github/actions/e2e-prepare-containers/**"
- ".github/actions/prepare-cypress/**"
- ".github/workflows/e2e-*"
@@ -127,18 +128,27 @@ e2e_ci: &e2e_ci
e2e_specs: &e2e_specs
- e2e/!(test-host-app)**/*.cy.*.{js,ts}
e2e_embedding_sdk:
- *frontend_embedding_sdk_ci
- *sources
- "e2e/component/**/*.cy.*.{js,ts}"
embedding_sdk_ci: &embedding_sdk_ci
- *shared_ci
- ".github/actions/prepare-uberjar-artifact/**"
- ".github/actions/fetch-artifact/action.yml"
- ".github/actions/prepare-cypress/**"
- ".github/workflows/embedding-sdk*.yml"
e2e_embedding_sdk_compatibility:
embedding_sdk_components:
- *default
- *frontend_embedding_sdk_ci
- *embedding_sdk_ci
- *sources
- *shared_e2e
- "e2e/test-component/**/*.cy.*.{js,jsx,ts,tsx}"
embedding_sdk_host_sample_apps:
- *default
- *embedding_sdk_ci
- *frontend_sources
- *backend_sources
- *shared_e2e
- "e2e/embedding-sdk-host-apps/**"
- "e2e/runner/embedding-sdk/**"
- "e2e/test-host-app/**/*.cy.*.{js,ts}"
snowplow: &snowplow

40
.github/scripts/find-linear-issue.js vendored Normal file
View File

@@ -0,0 +1,40 @@
async function findLinearIssue({ githubIssueUrl, linearApiKey }) {
const response = await fetch("https://api.linear.app/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: linearApiKey,
},
body: JSON.stringify({
query: `
query {
attachmentsForURL(url: "${githubIssueUrl}") {
nodes {
issue { identifier }
}
}
}
`,
}),
});
const data = await response.json();
if (!response.ok) {
return { success: false, message: `Linear API error: ${response.status}` };
}
if (!data.data?.attachmentsForURL?.nodes?.length) {
return {
success: false,
message: `No Linear issue linked to ${githubIssueUrl}`,
};
}
return {
success: true,
issue: data.data.attachmentsForURL.nodes[0].issue.identifier,
};
}
module.exports = { findLinearIssue };

317
.github/scripts/generate-llms-txt.js vendored Normal file
View File

@@ -0,0 +1,317 @@
const fs = require("fs");
const path = require("path");
const REPO = "metabase/metabase";
const OUTPUT_FILE = "llms.txt";
// Sections to generate llms-<name>-full.txt for.
// Each section can define a preamble (introductory content before the main docs).
const LLMS_FULL_TO_GENERATE = [
{
section: "embedding",
getPreamble: (branch) =>
aboveVersion(branch, 57) ? getModularEmbeddingGotchaNotes() : "",
},
];
/**
* List directory recursively to get markdown files
*
* @param {string} docsPath - full path to docs directory
* @returns {Array} list of markdown file objects with fullPath and relativePath
*/
function getMarkdownFilesList(docsPath) {
if (!fs.existsSync(docsPath)) {
console.error(`Error: Docs directory '${docsPath}' does not exist`);
process.exit(1);
}
const entries = fs.readdirSync(docsPath, {
recursive: true,
withFileTypes: true,
});
return entries
.filter((entry) => {
return (
entry.isFile() &&
// Only markdown files
entry.name.endsWith(".md") &&
// Ignore README.md
entry.name !== "README.md" &&
// Ignore node_modules and hidden directories
!entry.parentPath
.split(path.sep)
.some((dir) => dir === "node_modules" || dir.startsWith("."))
);
})
.map((entry) => {
const fullPath = path
.join(entry.parentPath, entry.name)
.replace(/\\/g, "/");
const relativePath = path
.relative(docsPath, fullPath)
.replace(/\\/g, "/");
return { fullPath, relativePath };
});
}
/**
* Generate llms.txt file with links to all markdown files in docs/
*
* @param {string} branch - branch name (e.g. 'master' or 'release-x.58.x')
* @param {Array} files - list of all markdown file objects
* @param {Array<Object>} sectionsConfig - list of section config objects to generate complete references for
*/
function generateLlmsTxt(branch, files, sectionsConfig) {
const baseUrl = `https://raw.githubusercontent.com/${REPO}/refs/heads/${branch}`;
const filesToExtract = files
// Files in embedding/sdk/api/snippets does not exist in the repo.
.filter(
(file) => !file.relativePath.startsWith("embedding/sdk/api/snippets"),
);
const entries = filesToExtract.map((file) => {
const content = fs.readFileSync(file.fullPath, "utf8");
const title = extractTitle(content, file.relativePath);
const url = `${baseUrl}/docs/${file.relativePath}`;
return { title, url, path: file.relativePath };
});
// Generate table of contents entries
const tableOfContents = entries.map(
(entry) => `- [${entry.title}](${entry.url})`,
);
// Generate complete references entries
const completeReferences = sectionsConfig
.filter((config) =>
files.some((file) => file.relativePath.startsWith(`${config.section}/`)),
)
.map((config) => {
const capitalized =
config.section.charAt(0).toUpperCase() + config.section.slice(1);
return `- [${capitalized} - Complete Reference](${baseUrl}/llms-${config.section}-full.txt)`;
});
// Generate llms.txt content using template literal
const content = `# Metabase Documentation
Metabase - The simplest, fastest way to get business intelligence and analytics to everyone in your company.
## Table of Contents
${tableOfContents.join("\n")}
## Complete References
These files are very large and are around 90,000 tokens. Do not use by default unless the context window is huge or RAG is supported in your editor.
${completeReferences.join("\n")}
`;
fs.writeFileSync(OUTPUT_FILE, content, "utf8");
console.log(
`✅ Generated ${OUTPUT_FILE} with ${entries.length} markdown files`,
);
console.log(` Branch: ${branch}`);
console.log(` Base URL: ${baseUrl}`);
}
/**
* Generate llms-full.txt files for specified sections
*
* @param {string} branch - branch name (e.g., 'master', 'release-x.58.x')
* @param {Array} files - list of all markdown file objects
* @param {Array<Object>} sectionsConfig - list of section config objects to generate full files for
*/
function generateLlmsFullFiles(branch, files, sectionsConfig) {
const baseUrl = `https://raw.githubusercontent.com/${REPO}/refs/heads/${branch}`;
sectionsConfig.forEach((config) => {
generateLlmsFullTxt(branch, config, files, baseUrl);
});
}
/**
* LLMs are likely to pay attention to the very first lines.
*
* We add the most important context for LLMs to avoid
* confusion and pitfalls like out-of-date APIs in trained data.
*
* @returns {string} Markdown formatted gotcha notes
*/
function getModularEmbeddingGotchaNotes() {
return `> **Important Version Notes**
>
> Watch out for these deprecated props and gotchas for Metabase 57 onwards, for modular embedding:
>
> 1. \`config\` prop on MetabaseProvider no longer exist - it is replaced by \`authConfig\`.
> 2. \`authProviderUri\` field no longer exist.
> 3. \`jwtProviderUri\` optional field only exists in v58+. This is used to make JWT auth faster by skipping the \`GET /auth/sso\` discovery request. Not needed for initial implementation.
> 4. \`fetchRequestToken\` is not needed by default. This is only used to customize how the SDK fetches the request token.
> 5. Numeric IDs must be integers not strings, e.g. \`dashboardId={1}\`. When the ID is retrieved from the URL and it is numeric, convert it to an integer via \`parseInt\` before passing it to the SDK. IDs can also be strings for entity ids, so you should not parse all IDs as numbers if entity ids are also to be expected.
`;
}
/**
* Generate llms-full.txt file for a specific section
* @param {string} branch - The branch name
* @param {Object} config - Section config object with section name and optional getPreamble function
* @param {Array} files - Array of all markdown file objects
* @param {string} baseUrl - Base URL for raw GitHub links
*/
function generateLlmsFullTxt(branch, config, files, baseUrl) {
const { section, getPreamble } = config;
// Filter docs for this section
const sectionFiles = files.filter((file) =>
file.relativePath.startsWith(`${section}/`),
);
if (sectionFiles.length === 0) {
console.log(` Skipping llms-full.txt for ${section} (no files found)`);
return;
}
// Build content
const sectionCapitalized = section.charAt(0).toUpperCase() + section.slice(1);
const header = `# Metabase ${sectionCapitalized} - Complete Reference for AI agents
> Table of contents: ${baseUrl}/${OUTPUT_FILE}
`;
// Add preamble if provided (e.g., version-specific notes, warnings)
const preamble = getPreamble ? getPreamble(branch) : "";
// Concatenate all documents
const docs = sectionFiles
.map((file) => readAndCleanMarkdown(file.fullPath))
.join("\n");
// Write llms-full.txt file at repo root
const content = header + preamble + "\n" + docs;
const llmsFullPath = `llms-${section}-full.txt`;
fs.writeFileSync(llmsFullPath, content, "utf8");
console.log(
`✅ Generated ${llmsFullPath} with ${sectionFiles.length} documents`,
);
}
/**
* Extract title from markdown file frontmatter or filename.
*
* We try to extract the title in this order: 1) YAML frontmatter
* 2) first H1 heading, and 3) the Markdown file name.
*
* Example Markdown and frontmatter format:
* ```markdown
* ---
* title: "Getting Started"
* description: "A guide"
* ---
* # Getting Started
* ```
*
* @param {string} content - file content
* @param {string} filePath - relative file path
* @returns {string} title of content
*/
function extractTitle(content, filePath) {
// Try to extract title from YAML frontmatter
// First, match against the YAML frontmatter delimiter `---`
const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
if (frontmatterMatch) {
// Then, match against the title property
// Example: `title: "My Page"`
const frontmatter = frontmatterMatch[1];
const titleMatch = frontmatter.match(/^title:\s*(.+)$/m);
// Remove quotes if present
if (titleMatch) {
return titleMatch[1].trim().replace(/^["']|["']$/g, "");
}
}
// Try to extract title from first H1 heading
// Example: `# My Page`
const h1Match = content.match(/^#\s+(.+)$/m);
if (h1Match) {
return h1Match[1].trim();
}
// Fallback to filename, e.g. `my-page.md`
const filename = path.basename(filePath, ".md");
// Convert kebab-case or snake_case to Title Case
// `my-page.md` would become "My Page"
return filename
.split(/[-_]/)
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
}
/**
* Read and clean markdown file content
*
* @param {string} filePath - full path to the markdown file
* @returns {string} cleaned markdown content with separator
*/
function readAndCleanMarkdown(filePath) {
let content = fs.readFileSync(filePath, "utf8");
// Strip YAML frontmatter
content = content.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, "");
// Strip Jekyll/Liquid template syntax
content = content.replace(/\{%.*?%\}/g, "");
content = content.replace(/\{\{.*?\}\}/g, "");
return `${content.trim()}\n\n---\n`;
}
/**
* Check if branch version is above target version
* @param {string} branch - Branch name (e.g., 'master', 'release-x.58.x')
* @param {number} targetVersion - Target version number
* @returns {boolean}
*/
function aboveVersion(branch, targetVersion) {
if (branch === "master") {
return true;
}
// Parse version from release branch like "release-x.58.x" -> 58
const match = branch.match(/release-x\.(\d+)\.x/);
if (!match) {
return false;
}
const version = parseInt(match[1], 10);
return version >= targetVersion;
}
// Main execution
if (require.main === module) {
const args = process.argv.slice(2);
const docsPath = args[0] || "docs";
const branch = args[1] || "master";
const resolvedDocsPath = path.resolve(docsPath);
const markdownFiles = getMarkdownFilesList(resolvedDocsPath);
// Sort all files upfront for consistent ordering across all generated files
markdownFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
generateLlmsTxt(branch, markdownFiles, LLMS_FULL_TO_GENERATE);
generateLlmsFullFiles(branch, markdownFiles, LLMS_FULL_TO_GENERATE);
}

View File

@@ -19,11 +19,12 @@ while [[ $# -gt 0 ]]; do
done
echo "Cloning python-runner repository..."
git clone --depth 1 https://${METABASE_AUTOMATION_USER_TOKEN}@github.com/metabase/python-runner-container.git python-runner
git clone https://${METABASE_AUTOMATION_USER_TOKEN}@github.com/metabase/python-runner-container.git python-runner
if [ "$SKIP_START" = false ]; then
echo "Starting python-runner..."
cd python-runner
git checkout origin/memory_improvements_2
make run-ci 1> ../python-runner.out.log 2> ../python-runner.err.log
make logs 1>> ../python-runner.out.log 2>> ../python-runner.err.log &
cd ..

10
.github/team.json vendored
View File

@@ -50,7 +50,7 @@
"nemanjaglumac"
]
},
{
{
"name": "Metabot",
"label": ".Team/Metabot",
"members": [
@@ -92,7 +92,10 @@
"deniskaber",
"alxnddr",
"bpander",
"andsalves"
"andsalves",
"gantoreno",
"kevinkelleher12",
"undrfined"
]
},
{
@@ -106,7 +109,8 @@
"chodorowicz",
"kamilmielnik",
"stasgavrylov",
"uladzimirdev"
"uladzimirdev",
"egorgrushin"
]
}
]

View File

@@ -68,8 +68,8 @@ jobs:
(
github.event_name == 'push' &&
(
github.ref == 'master' ||
startsWith(github.ref, 'release-')
github.ref_name == 'master' ||
startsWith(github.ref_name, 'release-')
) &&
''
) ||
@@ -182,8 +182,8 @@ jobs:
(
github.event_name == 'push' &&
(
github.ref == 'master' ||
startsWith(github.ref, 'release-')
github.ref_name == 'master' ||
startsWith(github.ref_name, 'release-')
) &&
''
) ||
@@ -297,8 +297,8 @@ jobs:
(
github.event_name == 'push' &&
(
github.ref == 'master' ||
startsWith(github.ref, 'release-')
github.ref_name == 'master' ||
startsWith(github.ref_name, 'release-')
) &&
''
) ||

View File

@@ -48,13 +48,11 @@ jobs:
- name: Enterprise Tests
edition: ee
test-group-name: ee
build-static-viz: 'false'
test-args: >-
:only '"enterprise/backend/test"'
- name: EE App DB Tests (Part 1)
edition: ee
test-group-name: ee-app-db-1
build-static-viz: 'true'
test-args: >-
:only '["test" ".clj-kondo/test"]'
:partition/total 2
@@ -62,7 +60,6 @@ jobs:
- name: EE App DB Tests (Part 2)
edition: ee
test-group-name: ee-app-db-2
build-static-viz: 'true'
test-args: >-
:only '["test" ".clj-kondo/test"]'
:partition/total 2
@@ -70,7 +67,6 @@ jobs:
- name: OSS App DB Tests (Part 1)
edition: oss
test-group-name: oss-app-db-1
build-static-viz: 'true'
test-args: >-
:only '["test" ".clj-kondo/test"]'
:partition/total 2
@@ -78,7 +74,6 @@ jobs:
- name: OSS App DB Tests (Part 2)
edition: oss
test-group-name: oss-app-db-2
build-static-viz: 'true'
test-args: >-
:only '["test" ".clj-kondo/test"]'
:partition/total 2
@@ -93,8 +88,8 @@ jobs:
(
github.event_name == 'push' &&
(
github.ref == 'master' ||
startsWith(github.ref, 'release-')
github.ref_name == 'master' ||
startsWith(github.ref_name, 'release-')
) &&
''
) ||
@@ -103,25 +98,15 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Prepare front-end environment
if: ${{ matrix.job.build-static-viz == 'true' }}
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
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
- name: Build static-viz frontend
if: ${{ matrix.job.build-static-viz == 'true' && !inputs.skip }}
run: yarn build-static-viz
env:
MB_EDITION: ${{ matrix.job.edition }}
- name: Download Static Viz Bundle Artifact
if: ${{ matrix.job.build-static-viz == 'true' && !inputs.skip }}
uses: actions/download-artifact@v4
with:
name: static-viz-bundle-${{ github.sha }}
path: resources/frontend_client/app/dist
- name: "Test Java ${{ matrix.java-version }} ${{ matrix.job.name }}"
id: run-java-tests

View File

@@ -30,8 +30,8 @@ name: Cache Generator
on:
schedule:
- cron: '0 3 * * 1' # Mondays at 03:00 UTC
workflow_dispatch: # manually update the cache
- cron: "0 3 * * 1" # Mondays at 03:00 UTC
workflow_dispatch: # manually update the cache
concurrency:
group: cache-generator
@@ -49,21 +49,27 @@ jobs:
m2-cache-key: ${{ steps.get-cache-keys.outputs.m2-cache-key }}
node-cache-key: ${{ steps.get-cache-keys.outputs.node-cache-key }}
eslint-cache-key: ${{ steps.get-cache-keys.outputs.eslint-cache-key }}
cypress-cache-key: ${{ steps.get-cache-keys.outputs.cypress-cache-key }}
generate-m2-cache:
generate-caches:
runs-on: ubuntu-22.04
timeout-minutes: 15
timeout-minutes: 30
needs: get-cache-keys
env:
M2_CACHE_KEY: ${{ needs.get-cache-keys.outputs.m2-cache-key }}
NODE_CACHE_KEY: ${{ needs.get-cache-keys.outputs.node-cache-key }}
CYPRESS_CACHE_KEY: ${{ needs.get-cache-keys.outputs.cypress-cache-key }}
ESLINT_CACHE_KEY: ${{ needs.get-cache-keys.outputs.eslint-cache-key }}
steps:
- uses: actions/checkout@v4
# Backend preparation and cache
- 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
- name: Pre-resolve Clojure dependencies
run: clojure -A:build:dev:ee:ee-dev:drivers:drivers-dev:cljs -P
- name: Update M2 cache
@@ -74,15 +80,7 @@ jobs:
~/.gitlibs
key: ${{ env.M2_CACHE_KEY }}
generate-frontend-caches:
runs-on: ubuntu-22.04
timeout-minutes: 15
needs: get-cache-keys
env:
NODE_CACHE_KEY: ${{ needs.get-cache-keys.outputs.node-cache-key }}
ESLINT_CACHE_KEY: ${{ needs.get-cache-keys.outputs.eslint-cache-key }}
steps:
- uses: actions/checkout@v4
# Frontend preparation and caches
# `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:
@@ -92,16 +90,51 @@ jobs:
- name: Install front-end dependencies
uses: ./.github/actions/prepare-frontend
with:
apply-patches: 'false'
apply-patches: "false"
- name: Get yarn cache directory
id: yarn-cache-dir
run: |
YARN_CACHE_DIR=$(yarn cache dir)
echo "Yarn cache directory: $YARN_CACHE_DIR"
echo "dir=$YARN_CACHE_DIR" >> $GITHUB_OUTPUT
- name: Ensure that Cypress executable is ready
run: |
yarn cypress install
yarn cypress cache path
yarn cypress cache list
yarn cypress verify
shell: bash
# Run Prettier to populate its cache (stored in node_modules/.cache/prettier)
# so it gets saved as part of the node_modules cache below
- name: Run Prettier to populate cache
run: yarn lint-prettier-pure
- name: Update node_modules cache
uses: ./.github/actions/update-cache
with:
path: node_modules
path: |
${{ steps.yarn-cache-dir.outputs.dir }}
node_modules
key: ${{ env.NODE_CACHE_KEY }}
- name: Update Cypress cache
uses: ./.github/actions/update-cache
with:
path: ~/.cache/Cypress
key: ${{ env.CYPRESS_CACHE_KEY }}
# ESLint cache (requires both backend and frontend)
- name: Compile CLJS
run: yarn build-pure:cljs
- name: Run ESLint to populate cache
run: yarn lint-eslint-pure
- name: Update eslint cache
uses: ./.github/actions/update-cache
with:
path: .eslintcache
path: ${{ github.workspace}}/.eslintcache
key: ${{ env.ESLINT_CACHE_KEY }}

View File

@@ -70,6 +70,31 @@ jobs:
core.setFailed(error.message);
}
- name: Find linked Linear issue
id: find_linear
continue-on-error: true
uses: actions/github-script@v7
env:
LINEAR_API_KEY: ${{ secrets.LINEAR_API_KEY }}
ISSUE_NUMBER: ${{ steps.get_issue.outputs.issue_number }}
with:
script: |
const { findLinearIssue } = require('${{ github.workspace }}/.github/scripts/find-linear-issue.js');
const githubIssueUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/issues/${process.env.ISSUE_NUMBER}`;
const result = await findLinearIssue({
githubIssueUrl,
linearApiKey: process.env.LINEAR_API_KEY
});
if (result.success) {
console.log(`Found Linear issue: ${result.issue}`);
core.setOutput('linear_issue', result.issue);
} else {
console.log(`Could not find Linear issue: ${result.message}`);
}
- name: Set up git configuration
run: |
git config --global user.name "Claude Code[bot]"
@@ -159,15 +184,15 @@ jobs:
1. **Analyze the issue description and comments** - Understand what the issue is describing
a. Pay particular attention to reproduction steps and if there's an agreed upon fix.
2. **Search the codebase** - Use Grep and Glob tools to find relevant files
3. **Implement a fix** - Follow existing code patterns and conventions
4. **Test the fix** - Run appropriate tests using the commands in CLAUDE.md:
- JavaScript/TypeScript: `yarn test-unit path/to/file.unit.spec.js`
- Clojure: `clojure -X:dev:test :only namespace/test-name`
- Lint: `yarn lint-eslint-pure` for JS/TS, `./bin/mage kondo <file>` for Clojure
3. **Implement a fix** - Use the appropriate write skill based on the file types:
- Use clojure-write for Clojure/ClojureScript files
- Use typescript-write for TypeScript/JavaScript files
- Follow the coding standards and patterns in each skill
4. **Test the fix** - Run appropriate tests as specified in the skills
5. **Verify the fix** - Ensure tests pass and code follows conventions
## Important Guidelines
- Follow the development patterns in CLAUDE.md
- Use the appropriate write skill for the language you're working in
- Write failing tests first, then fix them
- Work in small, testable increments
- Don't commit changes - leave that for the workflow
@@ -259,6 +284,7 @@ jobs:
core.setOutput('reviewers', issueCreator);
- name: Create Pull Request
id: create_pr
if: steps.check_changes.outputs.has_changes == 'true'
uses: peter-evans/create-pull-request@v6
with:
@@ -279,6 +305,8 @@ jobs:
body: |
This PR automatically fixes the bug reported in #${{ env.ISSUE_NUMBER }}.
${{ steps.find_linear.outputs.linear_issue && format('Closes {0}', steps.find_linear.outputs.linear_issue) || '' }}
## Bug Report
**Original Issue:** #${{ env.ISSUE_NUMBER }}
**Reporter:** @${{ env.ISSUE_AUTHOR }}
@@ -299,7 +327,6 @@ jobs:
- If issues are found, either fix them or close this PR
---
Closes #${{ env.ISSUE_NUMBER }}
🤖 Generated with [Claude Code](https://claude.ai/code)
@@ -309,6 +336,7 @@ jobs:
automated-fix
ci skip
reviewers: ${{ steps.prepare_reviewers.outputs.reviewers }}
assignees: ${{ github.actor }}
- name: Log existing branch update
if: steps.check_changes.outputs.has_changes == 'true' && env.BRANCH_EXISTS == 'true'

View File

@@ -79,17 +79,14 @@ jobs:
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Review this pull request with a focus on:
Review this pull request for compliance with project coding standards and conventions.
- Compliance with project coding standards and conventions
- Code quality and best practices
- Clear and correct docstrings
- Clear and correct comments explaining what the code is doing
**Use the appropriate review skill based on the file types changed:**
- Use clojure-review for Clojure/ClojureScript files
- Use typescript-review for TypeScript/JavaScript files
- Follow the review guidelines and checklists in each skill
DO NOT post any comments confirming that something is correct or congratulating someone for following our
guidelines -- only post comments for style violations or concerns.
Follow additional guidelines in the "Code Review Guidelines" section of CLAUDE.md .
DO NOT post any comments confirming that something is correct - only post comments for style violations or concerns.
Note: The PR branch is already checked out in the current working directory.

103
.github/workflows/claude-docs-review.yml vendored Normal file
View File

@@ -0,0 +1,103 @@
name: "Claude Docs Review"
on:
pull_request:
types:
- opened
- synchronize
- reopened
paths:
- 'docs/**/*.md'
- 'docs/**/*.mdx'
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to review'
required: true
type: number
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}-claude-docs-review
cancel-in-progress: true
jobs:
review:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
# Make sure the value of GITHUB_TOKEN will not be persisted in repo's config
persist-credentials: false
- name: Generate GitHub App Token for Claude
uses: actions/create-github-app-token@v1
id: claude-app-token
with:
app-id: ${{ secrets.METABASE_BOT_APP_ID }}
private-key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
permission-contents: read # Required for reading repository files and PR diffs
permission-pull-requests: write # Required for creating inline comments and PR comments
- name: Delete old Claude docs review comments
env:
GH_TOKEN: ${{ steps.claude-app-token.outputs.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
shell: bash
run: |
# Delete pending reviews first (these can be deleted entirely)
pending_review_ids=$(gh api "/repos/$REPO/pulls/$PR_NUMBER/reviews" --jq '.[] | select(.user.login=="metabase-bot[bot]" and .state=="PENDING") | .id')
if [ -n "$pending_review_ids" ]; then
echo "Deleting pending reviews: $pending_review_ids"
for id in $pending_review_ids; do
gh api -X DELETE "/repos/$REPO/pulls/$PR_NUMBER/reviews/$id"
echo "Deleted pending review $id"
done
fi
# Delete individual inline comments from submitted reviews (can't delete the review itself)
old_line_comment_ids=$(gh api "/repos/$REPO/pulls/$PR_NUMBER/comments" --jq '.[] | select(.user.login=="metabase-bot[bot]") | .id')
if [ -n "$old_line_comment_ids" ]; then
echo "Deleting line comments: $old_line_comment_ids"
for id in $old_line_comment_ids; do
gh api -X DELETE "/repos/$REPO/pulls/comments/$id"
echo "Deleted line comment $id"
done
fi
# Delete top-level review comments
old_top_level_comment_ids=$(gh api "/repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.user.login=="metabase-bot[bot]") | .id')
if [ -n "$old_top_level_comment_ids" ]; then
echo "Deleting top-level comments: $old_top_level_comment_ids"
for id in $old_top_level_comment_ids; do
gh api -X DELETE "/repos/$REPO/issues/comments/$id"
echo "Deleted top-level comment $id"
done
fi
- uses: anthropics/claude-code-action@v1
timeout-minutes: 10
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ steps.claude-app-token.outputs.token }}
show_full_output: true
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
Review the documentation changes in this pull request.
Use the docs-review skill to review all changed documentation files for compliance with the Metabase writing style guide.
IMPORTANT: Only review markdown files (.md and .mdx). Skip any .txt files or other non-markdown files.
DO NOT post any comments confirming that something is correct - only post comments for style violations or concerns.
claude_args: |
--allowedTools "Skill,mcp__github__get_pull_request,mcp__github__get_pull_request_files,mcp__github__create_pending_pull_request_review,mcp__github__get_pull_request_diff,mcp__github__add_comment_to_pending_review,mcp__github__add_pull_request_review_comment_to_pending_review,mcp__github__delete_pending_pull_request_review,mcp__github__submit_pending_pull_request_review"

View File

@@ -1,33 +0,0 @@
name: Cleanup caches by a branch
on:
pull_request:
types:
- closed
jobs:
cleanup:
runs-on: ubuntu-22.04
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
REPO=${{ github.repository }}
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
echo "Fetching list of cache key"
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
echo "Done"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,19 +1,110 @@
name: Codespell
on:
push:
branches:
- 'master'
- 'release-**'
pull_request:
schedule:
# Run nightly at 4:00 AM UTC
- cron: "0 4 * * *"
workflow_dispatch:
jobs:
codespell:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v3
- uses: codespell-project/actions-codespell@v1
- uses: actions/checkout@v4
- name: Install codespell
run: pip install codespell
- name: Set up git configuration
run: |
git config --global user.name "Claude Code[bot]"
git config --global user.email "noreply@anthropic.com"
- name: Get current date
id: date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Run codespell check
id: codespell_check
continue-on-error: true
run: |
set -o pipefail
./bin/mage codespell 2>&1 | tee codespell_output.txt
- name: Generate GitHub App Token for Claude
if: steps.codespell_check.outcome == 'failure'
uses: actions/create-github-app-token@v1
id: claude-app-token
with:
# keep this list in sync with the list in `mage/src/mage/codespell.yml`
path: >-
docs
app-id: ${{ secrets.METABASE_BOT_APP_ID }}
private-key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
- name: Fix spelling errors with Claude Code
if: steps.codespell_check.outcome == 'failure'
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ steps.claude-app-token.outputs.token }}
prompt: |
You are tasked with fixing spelling errors detected by codespell in this repository.
## Codespell Output
The following spelling errors were detected:
```
$(cat codespell_output.txt)
```
## Instructions
1. **Review the codespell output and identify reported spelling errors** - The usual format codespell uses is `typo ==> correction`
2. **Fix every spelling error** - Use the Edit tool to fix each misspelling with the suggested correction
- If codespell suggests multiple corrections, choose the most appropriate one based on context
Human reviewers will verify the changes before merging, so fix all errors reported by codespell.
claude_args: |
--allowedTools "Write,Read,Glob,Grep,Edit,MultiEdit,Bash(cat*),Bash(ls*)"
--disallowedTools "Bash(git commit*),Bash(git push*),Bash(gh*)"
- name: Clean up temporary files
if: steps.codespell_check.outcome == 'failure'
run: rm -f codespell_output.txt
- name: Create Pull Request
if: steps.codespell_check.outcome == 'failure'
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: claude-fix/codespell-${{ steps.date.outputs.date }}
base: master
delete-branch: true
commit-message: |
Fix spelling errors detected by codespell (${{ steps.date.outputs.date }})
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
committer: "Claude Code[bot] <noreply@anthropic.com>"
author: "Claude Code[bot] <noreply@anthropic.com>"
title: "Fix spelling errors detected by codespell (${{ steps.date.outputs.date }})"
body: |
This PR automatically fixes spelling errors detected by the scheduled codespell check.
## Automated Fix
🤖 This fix was generated automatically by Claude Code based on codespell output.
**Please review carefully:**
- [ ] The spelling fixes are correct
- [ ] No code functionality was changed
- [ ] Technical terms were preserved correctly
---
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
labels: |
automated-fix
backport

View File

@@ -2,8 +2,6 @@ name: Check doc links
on:
pull_request:
paths:
- "docs/**"
workflow_dispatch:
jobs:
@@ -15,7 +13,7 @@ jobs:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
sparse-checkout: |
docs
@@ -29,7 +27,7 @@ jobs:
- name: Run link checker
id: link-check
uses: lycheeverse/lychee-action@v2
uses: lycheeverse/lychee-action@v2.3.0
with:
fail: true
args: docs --config ./.lychee/config.toml --offline

View File

@@ -8,7 +8,7 @@ on:
target_branch:
description: "Target branch for documentation update"
required: false
default: "release-x.56.x"
default: "release-x.58.x"
type: string
jobs:
@@ -16,6 +16,6 @@ jobs:
name: Call documentation update for release branch
uses: ./.github/workflows/docs-generate-base.yml
with:
target_branch: ${{ inputs.target_branch || 'release-x.56.x' }}
target_branch: ${{ inputs.target_branch || 'release-x.58.x' }}
secrets:
automation_token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}

View File

@@ -12,12 +12,52 @@ concurrency:
cancel-in-progress: true
jobs:
# This job will determine if the tier 3 driver tests should be skipped.
# It will always run first.
# This job determines which driver tests should run based on PR context.
# All decision logic is consolidated in mage driver-decisions.
determine-driver-skips:
runs-on: ubuntu-latest
outputs:
skip: ${{ steps.check-branch-and-files-changed.outputs.skip }}
# All driver run decisions (from mage driver-decisions)
h2-should-run: ${{ steps.driver-decisions.outputs.h2-should-run }}
athena-should-run: ${{ steps.driver-decisions.outputs.athena-should-run }}
bigquery-should-run: ${{ steps.driver-decisions.outputs.bigquery-should-run }}
clickhouse-should-run: ${{ steps.driver-decisions.outputs.clickhouse-should-run }}
databricks-should-run: ${{ steps.driver-decisions.outputs.databricks-should-run }}
druid-should-run: ${{ steps.driver-decisions.outputs.druid-should-run }}
druid-jdbc-should-run: ${{ steps.driver-decisions.outputs.druid-jdbc-should-run }}
mongo-should-run: ${{ steps.driver-decisions.outputs.mongo-should-run }}
mongo-ssl-should-run: ${{ steps.driver-decisions.outputs.mongo-ssl-should-run }}
mongo-sharded-cluster-should-run: ${{ steps.driver-decisions.outputs.mongo-sharded-cluster-should-run }}
mysql-mariadb-should-run: ${{ steps.driver-decisions.outputs.mysql-mariadb-should-run }}
oracle-should-run: ${{ steps.driver-decisions.outputs.oracle-should-run }}
postgres-should-run: ${{ steps.driver-decisions.outputs.postgres-should-run }}
presto-jdbc-should-run: ${{ steps.driver-decisions.outputs.presto-jdbc-should-run }}
redshift-should-run: ${{ steps.driver-decisions.outputs.redshift-should-run }}
snowflake-should-run: ${{ steps.driver-decisions.outputs.snowflake-should-run }}
sparksql-should-run: ${{ steps.driver-decisions.outputs.sparksql-should-run }}
sqlite-should-run: ${{ steps.driver-decisions.outputs.sqlite-should-run }}
sqlserver-should-run: ${{ steps.driver-decisions.outputs.sqlserver-should-run }}
vertica-should-run: ${{ steps.driver-decisions.outputs.vertica-should-run }}
# Per-driver quarantine conflict flags (set when driver is quarantined but has file changes)
athena-quarantine-conflict: ${{ steps.driver-decisions.outputs.athena-quarantine-conflict }}
bigquery-quarantine-conflict: ${{ steps.driver-decisions.outputs.bigquery-quarantine-conflict }}
clickhouse-quarantine-conflict: ${{ steps.driver-decisions.outputs.clickhouse-quarantine-conflict }}
databricks-quarantine-conflict: ${{ steps.driver-decisions.outputs.databricks-quarantine-conflict }}
druid-quarantine-conflict: ${{ steps.driver-decisions.outputs.druid-quarantine-conflict }}
druid-jdbc-quarantine-conflict: ${{ steps.driver-decisions.outputs.druid-jdbc-quarantine-conflict }}
mongo-quarantine-conflict: ${{ steps.driver-decisions.outputs.mongo-quarantine-conflict }}
mongo-ssl-quarantine-conflict: ${{ steps.driver-decisions.outputs.mongo-ssl-quarantine-conflict }}
mongo-sharded-cluster-quarantine-conflict: ${{ steps.driver-decisions.outputs.mongo-sharded-cluster-quarantine-conflict }}
mysql-mariadb-quarantine-conflict: ${{ steps.driver-decisions.outputs.mysql-mariadb-quarantine-conflict }}
oracle-quarantine-conflict: ${{ steps.driver-decisions.outputs.oracle-quarantine-conflict }}
postgres-quarantine-conflict: ${{ steps.driver-decisions.outputs.postgres-quarantine-conflict }}
presto-jdbc-quarantine-conflict: ${{ steps.driver-decisions.outputs.presto-jdbc-quarantine-conflict }}
redshift-quarantine-conflict: ${{ steps.driver-decisions.outputs.redshift-quarantine-conflict }}
snowflake-quarantine-conflict: ${{ steps.driver-decisions.outputs.snowflake-quarantine-conflict }}
sparksql-quarantine-conflict: ${{ steps.driver-decisions.outputs.sparksql-quarantine-conflict }}
sqlite-quarantine-conflict: ${{ steps.driver-decisions.outputs.sqlite-quarantine-conflict }}
sqlserver-quarantine-conflict: ${{ steps.driver-decisions.outputs.sqlserver-quarantine-conflict }}
vertica-quarantine-conflict: ${{ steps.driver-decisions.outputs.vertica-quarantine-conflict }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -26,44 +66,25 @@ jobs:
run: |
# Fetch the base branch to ensure its history is available for diffing
git fetch --depth=1 origin ${{ github.event.pull_request.base.ref }}:${{ github.event.pull_request.base.ref }}
# Only run this if it's a pull request and the base ref exists
- name: Get Date
id: get-date
shell: bash
- name: Determine which drivers should run
id: driver-decisions
run: |
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
- name: Restore Babashka cache
uses: actions/cache@v4
with:
path: |
~/.m2
~/.deps.clj
restore-keys: |
mage-drivers-
key: >-
mage-drivers-${{ steps.get-date.outputs.date }}
- name: Check if driver tests should run
id: check-branch-and-files-changed
run: |
IS_MASTER_OR_RELEASE="${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-') }}"
echo "Is master or release: ${IS_MASTER_OR_RELEASE}"
if [[ "${IS_MASTER_OR_RELEASE}" == "true" ]]; then
echo "skip=false" >> $GITHUB_OUTPUT
echo "Merging into master or a release branch. All driver tests will run."
else
echo "Checking for changes in relevant modules..."
if ./bin/mage can-skip-driver-tests "${{ github.event.pull_request.base.ref }}"; then
echo 'skip=true' >> $GITHUB_OUTPUT
else
echo 'skip=false' >> $GITHUB_OUTPUT
fi
fi
# All decision logic is in mage - it analyzes module dependencies,
# branch context, labels, and file changes to decide what runs.
MAGE_ARGS=(
--git-ref="${{ github.event.pull_request.base.ref || 'master' }}"
--is-master-or-release="${{ github.ref_name == 'master' || startsWith(github.ref_name, 'release-') }}"
--pr-labels="${{ join(github.event.pull_request.labels.*.name, ',') }}"
--skip="${{ inputs.skip }}"
)
# First call: show human-readable output for debugging
./bin/mage -driver-decisions "${MAGE_ARGS[@]}"
# Second call: output only key=value lines for GITHUB_OUTPUT
./bin/mage -driver-decisions "${MAGE_ARGS[@]}" --github-output-only >> $GITHUB_OUTPUT
shell: bash
be-tests-athena-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -80,8 +101,19 @@ jobs:
MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_SECRET_KEY: ${{ secrets.MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_SECRET_KEY }}
name: Athena
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.athena-quarantine-conflict == 'true' }}
run: |
echo "::error::Athena driver is quarantined but you changed files in modules/drivers/athena/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Athena tests, add the label: break-quarantine-athena"
echo ""
echo "If you merge without testing, you risk breaking the Athena driver!"
exit 1
- uses: actions/checkout@v4
- name: Test Athena driver
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-athena-ee'
@@ -102,7 +134,6 @@ jobs:
be-tests-bigquery-cloud-sdk-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
@@ -113,6 +144,7 @@ jobs:
test-args: >-
:only-tags [:mb/driver-tests]
:exclude-tags [:mb/transforms-python-test]
:fail-fast? true
# DS 2025-09-26 temporarily disabled while we diagnose flakes
# - name: Transforms Python Tests
# test-args: >-
@@ -130,6 +162,16 @@ jobs:
MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON_ROUTING: ${{ secrets.MB_BIGQUERY_CLOUD_SDK_TEST_SERVICE_ACCOUNT_JSON_ROUTING }}
name: BigQuery ${{ matrix.job.name }}
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.bigquery-quarantine-conflict == 'true' }}
run: |
echo "::error::BigQuery driver is quarantined but you changed files in modules/drivers/bigquery-cloud-sdk/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run BigQuery tests, add the label: break-quarantine-bigquery"
echo ""
echo "If you merge without testing, you risk breaking the BigQuery driver!"
exit 1
- uses: actions/checkout@v4
- name: Setup python-runner
if: ${{ matrix.job.needs-python-runner == true }}
@@ -142,6 +184,7 @@ jobs:
with:
junit-name: 'be-tests-bigquery-cloud-sdk-ee'
test-args: ${{ matrix.job.test-args }}
logs-artifact-suffix: ${{ matrix.job.name }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
@@ -162,7 +205,6 @@ jobs:
be-tests-clickhouse-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
@@ -186,6 +228,16 @@ jobs:
MB_CLICKHOUSE_TEST_NGINX_PORT: 8127
name: Clickhouse ${{ matrix.job.name }}
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.clickhouse-quarantine-conflict == 'true' }}
run: |
echo "::error::ClickHouse driver is quarantined but you changed files in modules/drivers/clickhouse/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run ClickHouse tests, add the label: break-quarantine-clickhouse"
echo ""
echo "If you merge without testing, you risk breaking the ClickHouse driver!"
exit 1
- uses: actions/checkout@v4
- name: Setup python-runner
if: ${{ matrix.job.needs-python-runner == true }}
@@ -213,6 +265,7 @@ jobs:
with:
junit-name: 'be-tests-clickhouse-ee'
test-args: ${{ matrix.job.test-args }}
logs-artifact-suffix: ${{ matrix.job.name }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
@@ -233,7 +286,6 @@ jobs:
be-tests-druid-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -248,8 +300,19 @@ jobs:
CLUSTER_SIZE: nano-quickstart
name: Druid (Legacy)
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.druid-quarantine-conflict == 'true' }}
run: |
echo "::error::Druid driver is quarantined but you changed files in modules/drivers/druid/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Druid tests, add the label: break-quarantine-druid"
echo ""
echo "If you merge without testing, you risk breaking the Druid driver!"
exit 1
- uses: actions/checkout@v4
- name: Test Druid driver
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-druid-ee'
@@ -270,7 +333,6 @@ jobs:
be-tests-druid-jdbc-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -285,8 +347,19 @@ jobs:
CLUSTER_SIZE: nano-quickstart
name: Druid (JDBC)
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.druid-jdbc-quarantine-conflict == 'true' }}
run: |
echo "::error::Druid JDBC driver is quarantined but you changed files in modules/drivers/druid-jdbc/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Druid JDBC tests, add the label: break-quarantine-druid-jdbc"
echo ""
echo "If you merge without testing, you risk breaking the Druid JDBC driver!"
exit 1
- uses: actions/checkout@v4
- name: Test Druid JDBC driver
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-druid-jdbc-ee'
@@ -307,7 +380,6 @@ jobs:
be-tests-databricks-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -322,8 +394,19 @@ jobs:
MB_DATABRICKS_TEST_OAUTH_SECRET: ${{ secrets.MB_DATABRICKS_JDBC_TEST_OAUTH_SECRET }}
name: Databricks
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.databricks-quarantine-conflict == 'true' }}
run: |
echo "::error::Databricks driver is quarantined but you changed files in modules/drivers/databricks/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Databricks tests, add the label: break-quarantine-databricks"
echo ""
echo "If you merge without testing, you risk breaking the Databricks driver!"
exit 1
- uses: actions/checkout@v4
- name: Test Databricks driver
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-databricks-ee'
@@ -344,7 +427,6 @@ jobs:
be-tests-databricks-multi-catalog-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -360,8 +442,19 @@ jobs:
MB_DATABRICKS_TEST_OAUTH_SECRET: ${{ secrets.MB_DATABRICKS_JDBC_TEST_OAUTH_SECRET }}
name: Databricks (Multi-Catalog)
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.databricks-quarantine-conflict == 'true' }}
run: |
echo "::error::Databricks driver is quarantined but you changed files in modules/drivers/databricks/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Databricks tests, add the label: break-quarantine-databricks"
echo ""
echo "If you merge without testing, you risk breaking the Databricks driver!"
exit 1
- uses: actions/checkout@v4
- name: Test Databricks driver with multi-catalog
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-databricks-multi-catalog-ee'
@@ -381,7 +474,7 @@ jobs:
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
be-tests-h2:
if: ${{ !inputs.skip }}
needs: determine-driver-skips
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -411,7 +504,6 @@ jobs:
be-tests-mysql-mariadb:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
@@ -469,8 +561,8 @@ jobs:
(
github.event_name == 'push' &&
(
github.ref == 'master' ||
startsWith(github.ref, 'release-')
github.ref_name == 'master' ||
startsWith(github.ref_name, 'release-')
) &&
''
) ||
@@ -523,6 +615,7 @@ jobs:
uses: ./.github/actions/test-driver
with:
junit-name: ${{ matrix.version.junit-name }}
logs-artifact-suffix: ${{ matrix.version.name }}
test-args: >-
${{ matrix.job.test-args }}
:exclude-tags '[ ${{ matrix.job.exclude-tag }} ${{ env.__ADDITIONAL_EXCLUDED_TAG__ }}]'
@@ -546,7 +639,6 @@ jobs:
be-tests-mongo:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
@@ -583,6 +675,16 @@ jobs:
MONGO_INITDB_ROOT_PASSWORD: metasample123
name: ${{ matrix.version.name }} ${{ matrix.job.name }}
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.mongo-quarantine-conflict == 'true' }}
run: |
echo "::error::MongoDB driver is quarantined but you changed files in modules/drivers/mongo/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run MongoDB tests, add the label: break-quarantine-mongo"
echo ""
echo "If you merge without testing, you risk breaking the MongoDB driver!"
exit 1
- uses: actions/checkout@v4
- name: Setup python-runner
if: ${{ matrix.job.needs-python-runner == true }}
@@ -595,6 +697,7 @@ jobs:
with:
junit-name: ${{ matrix.version.junit-name }}
test-args: ${{ matrix.job.test-args }}
logs-artifact-suffix: ${{ matrix.job.name }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
@@ -615,7 +718,6 @@ jobs:
be-tests-mongo-ssl:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
@@ -633,6 +735,16 @@ jobs:
MB_TEST_MONGO_REQUIRES_SSL: true
name: "${{ matrix.version.name }} (SSL)"
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.mongo-ssl-quarantine-conflict == 'true' }}
run: |
echo "::error::MongoDB SSL driver is quarantined but you changed files in modules/drivers/mongo/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run MongoDB SSL tests, add the label: break-quarantine-mongo-ssl"
echo ""
echo "If you merge without testing, you risk breaking the MongoDB SSL driver!"
exit 1
- uses: actions/checkout@v4
- name: Spin up Mongo docker container
run: >-
@@ -660,6 +772,7 @@ jobs:
curl https://raw.githubusercontent.com/metabase/metabase-qa/master/dbs/mongo/certificates/metaca.crt \
-o ./test_resources/ssl/mongo/metaca.crt
- name: Test ${{ matrix.version.name }}
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: ${{ matrix.version.junit-name }}
@@ -680,7 +793,7 @@ jobs:
be-tests-mongo-sharded-cluster-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -693,8 +806,19 @@ jobs:
- "27017:17017"
name: MongoDB Sharded Cluster
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.mongo-sharded-cluster-quarantine-conflict == 'true' }}
run: |
echo "::error::MongoDB Sharded Cluster driver is quarantined but you changed files in modules/drivers/mongo/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run MongoDB Sharded Cluster tests, add the label: break-quarantine-mongo-sharded-cluster"
echo ""
echo "If you merge without testing, you risk breaking the MongoDB Sharded Cluster driver!"
exit 1
- uses: actions/checkout@v4
- name: Test MongoDB driver (Sharded cluster)
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-mongo-sharded-cluster-ee'
@@ -714,7 +838,6 @@ jobs:
be-tests-oracle:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
@@ -765,11 +888,23 @@ jobs:
- "1521:${{ matrix.version.port }}"
name: ${{ matrix.version.name }}
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.oracle-quarantine-conflict == 'true' }}
run: |
echo "::error::Oracle driver is quarantined but you changed files in modules/drivers/oracle/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Oracle tests, add the label: break-quarantine-oracle"
echo ""
echo "If you merge without testing, you risk breaking the Oracle driver!"
exit 1
- uses: actions/checkout@v4
- name: Test ${{ matrix.version.name }}
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: ${{ matrix.version.junit-name }}
logs-artifact-suffix: ${{ matrix.version.name }}
test-args: >-
:only-tags [:mb/driver-tests]
:exclude-tags [:mb/transforms-python-test]
@@ -787,7 +922,6 @@ jobs:
be-tests-postgres:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
@@ -825,8 +959,8 @@ jobs:
(
github.event_name == 'push' &&
(
github.ref == 'master' ||
startsWith(github.ref, 'release-')
github.ref_name == 'master' ||
startsWith(github.ref_name, 'release-')
) &&
''
) ||
@@ -896,7 +1030,6 @@ jobs:
be-tests-presto-jdbc-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -919,6 +1052,16 @@ jobs:
env:
JAVA_TOOL_OPTIONS: "-Xmx2g"
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.presto-jdbc-quarantine-conflict == 'true' }}
run: |
echo "::error::Presto JDBC driver is quarantined but you changed files in modules/drivers/presto-jdbc/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Presto JDBC tests, add the label: break-quarantine-presto-jdbc"
echo ""
echo "If you merge without testing, you risk breaking the Presto JDBC driver!"
exit 1
- uses: actions/checkout@v4
- uses: ./.github/actions/await-port
with:
@@ -946,6 +1089,7 @@ jobs:
-file /tmp/presto-ssl-ca.der
-trustcacerts
- name: Test Presto JDBC driver
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-presto-jdbc-ee'
@@ -966,7 +1110,6 @@ jobs:
be-tests-redshift-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
@@ -978,12 +1121,22 @@ jobs:
test-args: >-
:only-tags [:mb/upload-tests]
:fail-fast? true
- name: Redshift (Excluding Upload Tests)
- name: Redshift (Excluding Upload Tests) Part 1
skip: false
test-args: >-
:only-tags [:mb/driver-tests]
:exclude-tags '[:mb/upload-tests :mb/transforms-python-test]'
:fail-fast? true
:partition/total 2
:partition/index 0
- name: Redshift (Excluding Upload Tests) Part 2
skip: false
test-args: >-
:only-tags [:mb/driver-tests]
:exclude-tags '[:mb/upload-tests :mb/transforms-python-test]'
:fail-fast? true
:partition/total 2
:partition/index 1
- name: Redshift Transforms Python Tests
skip: false
test-args: >-
@@ -1001,6 +1154,16 @@ jobs:
MB_REDSHIFT_TEST_PASSWORD: ${{ secrets.MB_REDSHIFT_TEST_PASSWORD }}
name: ${{ matrix.job.name }}
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.redshift-quarantine-conflict == 'true' }}
run: |
echo "::error::Redshift driver is quarantined but you changed files in modules/drivers/redshift/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Redshift tests, add the label: break-quarantine-redshift"
echo ""
echo "If you merge without testing, you risk breaking the Redshift driver!"
exit 1
- uses: actions/checkout@v4
- name: Setup python-runner
if: ${{ matrix.job.needs-python-runner == true }}
@@ -1015,6 +1178,7 @@ jobs:
junit-name: 'be-tests-redshift-ee'
test-args: >-
${{ matrix.job.test-args }}
logs-artifact-suffix: ${{ matrix.job.name }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: ${{ !matrix.job.skip && !cancelled() }}
@@ -1034,7 +1198,7 @@ jobs:
logs-artifact-suffix: ${{ matrix.job.name }} ${{ matrix.version.name }}
be-tests-snowflake-ee:
if: ${{ !inputs.skip }}
needs: determine-driver-skips
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
@@ -1045,6 +1209,7 @@ jobs:
test-args: >-
:only-tags [:mb/driver-tests]
:exclude-tags [:mb/transforms-python-test]
:fail-fast? true
# DS 2025-09-26 temporarily disabled while we diagnose flakes
# - name: Transforms Python Tests
@@ -1072,6 +1237,16 @@ jobs:
MB_SNOWFLAKE_TEST_RSA_ROLE_TEST_DB: RSA_ROLE_TEST_DB
name: Snowflake ${{ matrix.job.name }}
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.snowflake-quarantine-conflict == 'true' }}
run: |
echo "::error::Snowflake driver is quarantined but you changed files in modules/drivers/snowflake/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Snowflake tests, add the label: break-quarantine-snowflake"
echo ""
echo "If you merge without testing, you risk breaking the Snowflake driver!"
exit 1
- uses: actions/checkout@v4
- name: Setup python-runner
if: ${{ matrix.job.needs-python-runner == true }}
@@ -1084,6 +1259,7 @@ jobs:
with:
junit-name: 'be-tests-snowflake-ee'
test-args: ${{ matrix.job.test-args }}
logs-artifact-suffix: ${{ matrix.job.name }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
@@ -1104,7 +1280,6 @@ jobs:
be-tests-sparksql-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -1117,8 +1292,19 @@ jobs:
- "10000:10000"
name: Spark SQL
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.sparksql-quarantine-conflict == 'true' }}
run: |
echo "::error::SparkSQL driver is quarantined but you changed files in modules/drivers/sparksql/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run SparkSQL tests, add the label: break-quarantine-sparksql"
echo ""
echo "If you merge without testing, you risk breaking the SparkSQL driver!"
exit 1
- uses: actions/checkout@v4
- name: Test Spark driver
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-sparksql-ee'
@@ -1139,7 +1325,6 @@ jobs:
be-tests-sqlite-ee:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -1147,8 +1332,19 @@ jobs:
DRIVERS: sqlite
name: SQLite
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.sqlite-quarantine-conflict == 'true' }}
run: |
echo "::error::SQLite driver is quarantined but you changed files in modules/drivers/sqlite/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run SQLite tests, add the label: break-quarantine-sqlite"
echo ""
echo "If you merge without testing, you risk breaking the SQLite driver!"
exit 1
- uses: actions/checkout@v4
- name: Test SQLite driver
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-sqlite-ee'
@@ -1169,7 +1365,6 @@ jobs:
be-tests-sqlserver:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
@@ -1208,6 +1403,16 @@ jobs:
MSSQL_MEMORY_LIMIT_MB: 1024
name: ${{ matrix.version.name }} ${{ matrix.job.name }}
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.sqlserver-quarantine-conflict == 'true' }}
run: |
echo "::error::SQL Server driver is quarantined but you changed files in modules/drivers/sqlserver/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run SQL Server tests, add the label: break-quarantine-sqlserver"
echo ""
echo "If you merge without testing, you risk breaking the SQL Server driver!"
exit 1
- uses: actions/checkout@v4
- name: Setup python-runner
if: ${{ matrix.job.needs-python-runner == true }}
@@ -1220,6 +1425,7 @@ jobs:
with:
junit-name: ${{ matrix.version.junit-name }}
test-args: ${{ matrix.job.test-args }}
logs-artifact-suffix: ${{ matrix.version.name }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
@@ -1279,7 +1485,6 @@ jobs:
login-to-ecr:
needs: determine-driver-skips
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
@@ -1309,7 +1514,6 @@ jobs:
be-tests-vertica-ee:
needs: [determine-driver-skips, login-to-ecr]
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
@@ -1325,10 +1529,21 @@ jobs:
password: ${{ needs.login-to-ecr.outputs.docker_password }}
name: Vertica
steps:
- name: Fail on quarantine conflict
if: ${{ needs.determine-driver-skips.outputs.vertica-quarantine-conflict == 'true' }}
run: |
echo "::error::Vertica driver is quarantined but you changed files in modules/drivers/vertica/"
echo ""
echo "Your changes will NOT be tested because the driver is currently quarantined."
echo "To run Vertica tests, add the label: break-quarantine-vertica"
echo ""
echo "If you merge without testing, you risk breaking the Vertica driver!"
exit 1
- uses: actions/checkout@v4
- name: Make plugins directory
run: mkdir plugins
- name: Test Vertica driver
id: test-driver
uses: ./.github/actions/test-driver
with:
junit-name: 'be-tests-vertica-ee'

View File

@@ -1,185 +0,0 @@
# This workflow does the backward compatibility tests
# between the Embedding SDK package of version N and Embedding SDK Bundle of version N - 1
# N - 1 is a target of a PR
name: Embedding SDK backward-compatibility E2E Component Tests
on:
workflow_call:
inputs:
cached-embedding-sdk-dist-artifact-name:
required: true
type: string
jobs:
files-changed:
name: "SDK backward-compatibility E2E > Check which files changed"
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
e2e_embedding_sdk: ${{ steps.changes.outputs.e2e_embedding_sdk }}
steps:
- uses: actions/checkout@v4
- name: Test which files changed
uses: dorny/paths-filter@v3.0.0
id: changes
with:
token: ${{ github.token }}
filters: .github/file-paths.yaml
decide-target-ref:
runs-on: ubuntu-latest
outputs:
target-ref: ${{ steps.get-target-ref.outputs.value }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Decide ref to checkout
id: get-target-ref
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "value=${{ github.base_ref }}" >> "$GITHUB_OUTPUT"
else
echo "value=$(git rev-parse HEAD^1)" >> "$GITHUB_OUTPUT"
fi
# if this is a test on a release branch, we need to check the build requirements
get-build-requirements:
name: "SDK backward-compatibility E2E > [Backport only] Get build requirements"
needs: [decide-target-ref]
if: |
!cancelled() &&
contains(github.base_ref || github.ref, 'release-x')
runs-on: ubuntu-22.04
timeout-minutes: 10
outputs:
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
node_version: ${{ fromJson(steps.dependencies.outputs.result).node_version }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.decide-target-ref.outputs.target-ref }}
sparse-checkout: release
- name: Prepare build scripts
run: cd ${{ github.workspace }}/release && yarn && yarn build
- name: Get build dependencies
uses: actions/github-script@v7
id: dependencies
with:
script: | # js
const {
getBuildRequirements,
getVersionFromReleaseBranch,
} = require('${{ github.workspace }}/release/dist/index.cjs');
const targetBranchName = '${{ github.base_ref || github.ref }}';
const version = getVersionFromReleaseBranch(targetBranchName);
const requirements = getBuildRequirements(version);
return {
java_version: requirements.java,
node_version: requirements.node,
};
e2e-tests:
name: "SDK backward-compatibility E2E > Run e2e tests"
needs: [files-changed, decide-target-ref, get-build-requirements]
if: |
!cancelled() &&
needs.files-changed.outputs.e2e_embedding_sdk == 'true'
runs-on: ubuntu-22.04
timeout-minutes: 45
env:
MB_EDITION: ee
DISPLAY: ""
MB_RUN_MODE: "e2e"
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.STAGING_MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.STAGING_MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.STAGING_MB_PRO_SELF_HOSTED_TOKEN }}
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.decide-target-ref.outputs.target-ref }}
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
with:
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
- name: Build uberjar with ./bin/build.sh
run: ./bin/build.sh
- name: Retrieve Embedding SDK dist artifact
uses: actions/download-artifact@v4
with:
name: ${{ inputs.cached-embedding-sdk-dist-artifact-name }}
path: ${{ github.workspace }}/resources/embedding-sdk
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start
- name: Make app db snapshot
run: node e2e/runner/run_cypress_ci.js snapshot --browser ${{ steps.cypress-prep.outputs.chrome-path }}
- name: Run component tests for Embedding SDK
run: |
node e2e/runner/run_cypress_ci.js component \
--browser ${{ steps.cypress-prep.outputs.chrome-path }} \
--env grepTags="-@skip-backward-compatibility",grepOmitFiltered=true
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit
output-name: e2e-embedding-sdk
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: Upload Cypress Artifacts upon failure
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-recording-embedding-sdk-cross-version
path: |
./cypress
./logs/test.log
if-no-files-found: ignore
- name: Publish Summary
if: failure()
uses: actions/github-script@v7
with:
script: | #js
const {
generateReport,
parseReport,
formatSummary
} = require("./.github/scripts/handle-mochawesome-report.js");
const report = await generateReport();
const results = parseReport(report);
const summary = formatSummary(results);
await core.summary.addRaw(summary).write();

View File

@@ -1,203 +0,0 @@
name: E2E Component Tests for Embedding SDK
on:
workflow_call:
inputs:
cached-embedding-sdk-dist-artifact-name:
required: true
type: string
jobs:
files-changed:
name: "SDK e2e > Check which files changed"
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
e2e_embedding_sdk: ${{ steps.changes.outputs.e2e_embedding_sdk }}
steps:
- uses: actions/checkout@v4
- name: Test which files changed
uses: dorny/paths-filter@v3.0.0
id: changes
with:
token: ${{ github.token }}
filters: .github/file-paths.yaml
# if this is a test on a release branch, we need to check the build requirements
get-build-requirements:
name: "SDK e2e > [Backport only] Get build requirements"
if: |
!cancelled() &&
contains(github.base_ref || github.ref, 'release-x')
runs-on: ubuntu-22.04
timeout-minutes: 10
outputs:
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
node_version: ${{ fromJson(steps.dependencies.outputs.result).node_version }}
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: release
- name: Prepare build scripts
run: cd ${{ github.workspace }}/release && yarn && yarn build
- name: Get build dependencies
uses: actions/github-script@v7
id: dependencies
with:
script: | # js
const {
getBuildRequirements,
getVersionFromReleaseBranch,
} = require('${{ github.workspace }}/release/dist/index.cjs');
const targetBranchName = '${{ github.base_ref || github.ref }}';
const version = getVersionFromReleaseBranch(targetBranchName);
const requirements = getBuildRequirements(version);
return {
java_version: requirements.java,
node_version: requirements.node,
};
build-uberjar:
name: "SDK e2e > Build uberjar"
needs: [files-changed, get-build-requirements]
if: |
!cancelled() &&
needs.files-changed.outputs.e2e_embedding_sdk == 'true'
runs-on: ubuntu-22.04
timeout-minutes: 25
env:
MB_EDITION: ee
INTERACTIVE: false
# make sure that builds on release branches get licenses, because we use them for releases
SKIP_LICENSES: ${{ github.event_name == 'pull_request' }}
steps:
- uses: actions/checkout@v4
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
with:
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
- name: Build uberjar with ./bin/build.sh
run: ./bin/build.sh
- name: Prepare uberjar artifact
uses: ./.github/actions/prepare-uberjar-artifact
with:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar-sdk-tests
e2e-tests:
name: "SDK e2e > Run e2e tests (React ${{ matrix.react-version }})"
needs: [get-build-requirements, build-uberjar]
if: |
!cancelled() &&
needs.build-uberjar.result == 'success'
runs-on: ubuntu-22.04
timeout-minutes: 45
strategy:
matrix:
react-version: [18, 19]
fail-fast: false
env:
MB_EDITION: ee
DISPLAY: ""
MB_RUN_MODE: "e2e"
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.STAGING_MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.STAGING_MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.STAGING_MB_PRO_SELF_HOSTED_TOKEN }}
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
steps:
- uses: actions/checkout@v4
- name: Retrieve uberjar artifact for ee
uses: actions/download-artifact@v4
with:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar-sdk-tests
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare JDK ${{ needs.get-build-requirements.outputs.java_version || 21 }}
uses: actions/setup-java@v4
with:
java-version: ${{ needs.get-build-requirements.outputs.java_version || 21 }}
distribution: "temurin"
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Retrieve Embedding SDK dist artifact
uses: actions/download-artifact@v4
with:
name: ${{ inputs.cached-embedding-sdk-dist-artifact-name }}
path: ${{ github.workspace }}/resources/embedding-sdk
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start
- name: Make app db snapshot
run: node e2e/runner/run_cypress_ci.js snapshot --browser ${{ steps.cypress-prep.outputs.chrome-path }}
# Has to be run after the app db snapshot is made, as it is not compatible with React 19
- name: Change React version to ${{ matrix.react-version }}
run: ./bin/embedding-sdk/change-react-version.bash ${{ matrix.react-version }}
- name: Run component tests for Embedding SDK
run: node e2e/runner/run_cypress_ci.js component --browser ${{ steps.cypress-prep.outputs.chrome-path }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit
output-name: e2e-embedding-sdk-react-${{ matrix.react-version }}
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: "SDK e2e > Upload Cypress Artifacts upon failure"
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-recording-embedding-sdk-react-${{ matrix.react-version }}
path: |
./cypress
./logs/test.log
if-no-files-found: ignore
- name: "SDK e2e > Publish Summary"
if: failure()
uses: actions/github-script@v7
with:
script: | #js
const {
generateReport,
parseReport,
formatSummary
} = require("./.github/scripts/handle-mochawesome-report.js");
const report = await generateReport();
const results = parseReport(report);
const summary = formatSummary(results);
await core.summary.addRaw(summary).write();

View File

@@ -22,14 +22,10 @@ on:
required: false
default: "ee"
qa_db:
description: "Select the type of Database you want to run your tests with"
type: choice
description: "Whether to set up and include external QA databases"
type: boolean
required: true
default: "none"
options:
- none
- sql
- mongo
default: false
enable_network_throttling:
description: "Enable network throttling simulation (4g slow like in chrome dev tools)"
type: boolean
@@ -37,26 +33,26 @@ on:
default: true
jobs:
determine-suite:
name: Determine test suite
determine-test-type:
name: Determine test type
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
suite: ${{ steps.detect.outputs.suite }}
type: ${{ steps.detect.outputs.type }}
steps:
- name: Detect suite from spec path
- name: Detect test type from spec path
id: detect
run: |
SPEC='${{ inputs.spec }}'
if [[ "$SPEC" == e2e/test-component/scenarios/embedding-sdk/* ]]; then
echo "suite=component" >> $GITHUB_OUTPUT
echo "type=component" >> $GITHUB_OUTPUT
else
echo "suite=e2e" >> $GITHUB_OUTPUT
echo "type=e2e" >> $GITHUB_OUTPUT
fi
workflow-summary:
name: Stress test inputs
needs: [determine-suite]
needs: [determine-test-type]
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
@@ -66,7 +62,7 @@ jobs:
echo '' >> $GITHUB_STEP_SUMMARY
echo '- `branch`: ${{ github.ref_name }}' >> $GITHUB_STEP_SUMMARY
echo '- `spec`: ${{ inputs.spec }}' >> $GITHUB_STEP_SUMMARY
echo '- `test_suite` (inferred): ${{ needs.determine-suite.outputs.suite }}' >> $GITHUB_STEP_SUMMARY
echo '- `test_type` (inferred): ${{ needs.determine-test-type.outputs.type }}' >> $GITHUB_STEP_SUMMARY
echo '- `burn_in`: ${{ inputs.burn_in }}' >> $GITHUB_STEP_SUMMARY
echo '- `grep`: "${{ inputs.grep }}"' >> $GITHUB_STEP_SUMMARY
echo '- `qa_db`: "${{ inputs.qa_db }}"' >> $GITHUB_STEP_SUMMARY
@@ -75,26 +71,20 @@ jobs:
echo 'triggered by: @${{ github.event.sender.login }}' >> $GITHUB_STEP_SUMMARY
stress-test-flake-fix:
needs: [determine-suite]
needs: [determine-test-type]
runs-on: ubuntu-22.04
timeout-minutes: 60
name: Stress test E2E flake fix
env:
DISPLAY: ""
QA_DB_ENABLED: ${{ contains(fromJSON('["sql", "mongo"]'), inputs.qa_db) }}
CYPRESS_QA_DB_MONGO: ${{ inputs.qa_db == 'mongo' }}
MB_RUN_MODE: e2e
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
DISPLAY: "" # https://github.com/cypress-io/cypress/issues/4034
TERM: xterm
TZ: US/Pacific # to make Node match the instance tz
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.STAGING_MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.STAGING_MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.STAGING_MB_PRO_SELF_HOSTED_TOKEN }}
MB_SNOWPLOW_AVAILABLE: true
MB_SNOWPLOW_URL: "http://localhost:9090" # Snowplow micro
MB_EDITION: ${{ inputs.mb_edition }}
CYPRESS_ENABLE_NETWORK_THROTTLING: ${{ inputs.enable_network_throttling }}
TERM: xterm
TZ: US/Pacific # to make node match the instance tz
steps:
- uses: actions/checkout@v4
with:
@@ -109,9 +99,9 @@ jobs:
maildev: true
openldap: true
snowplow: true
postgres: ${{ inputs.qa_db == 'sql' }}
mysql: ${{ inputs.qa_db == 'sql' }}
mongo: ${{ inputs.qa_db == 'mongo' }}
postgres: ${{ inputs.qa_db }}
mysql: ${{ inputs.qa_db }}
mongo: ${{ inputs.qa_db }}
- name: Download Metabase ${{ matrix.edition }} uberjar
uses: ./.github/actions/e2e-download-uberjar
@@ -120,40 +110,45 @@ jobs:
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
if: ${{ needs.determine-suite.outputs.suite == 'component' }}
uses: ./.github/actions/prepare-backend
with:
m2-cache-key: "cljs"
- name: Build Embedding SDK package
if: ${{ needs.determine-suite.outputs.suite == 'component' }}
if: ${{ needs.determine-test-type.outputs.type == 'component' }}
run: yarn build-embedding-sdk-package
- name: Prepare JDK 21
uses: actions/setup-java@v4
with:
java-version: 21
distribution: "temurin"
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
- name: Compile CLJS
run: yarn build-pure:cljs
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start
- name: Generate database snapshots
run: node e2e/runner/run_cypress_ci.js snapshot
- name: Generate default database snapshot
if: inputs.qa_db == false # true boolean, do not use string here!
run: |
node e2e/runner/run_cypress_ci.js snapshot \
--spec "e2e/snapshot-creators/default.cy.snap.js"
- name: Generate all database snapshots
if: inputs.qa_db
run: |
node e2e/runner/run_cypress_ci.js snapshot
# For all options and fine-grained control, take a look at the documentation
# https://github.com/cypress-io/cypress/tree/develop/npm/grep
- name: Stress-test ${{ github.event.inputs.spec }} ${{ github.event.inputs.burn_in }} times
env:
GREP: ${{ github.event.inputs.grep }}
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
run: |
node e2e/runner/run_cypress_ci.js ${{ needs.determine-suite.outputs.suite }} \
node e2e/runner/run_cypress_ci.js ${{ needs.determine-test-type.outputs.type }} \
--spec '${{ github.event.inputs.spec }}' \
--env burn=${{ github.event.inputs.burn_in }} \
--config-file e2e/support/cypress-stress-test.config.js \
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
--config-file e2e/support/cypress-stress-test.config.js
- name: Upload Cypress Artifacts upon failure
uses: actions/upload-artifact@v4

View File

@@ -29,6 +29,15 @@ on:
required: false
type: number
env:
DISPLAY: "" # https://github.com/cypress-io/cypress/issues/4034
TERM: xterm
TZ: US/Pacific # to make Node match the instance tz
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
JOB_NAME: ${{ inputs.name }}
jobs:
e2e-tests:
runs-on: ${{ inputs.runner }}
@@ -36,29 +45,12 @@ jobs:
name: e2e-tests-${{ inputs.name }}-${{ inputs.edition }}
env:
MB_EDITION: ${{ inputs.edition }}
DISPLAY: ""
QA_DB_ENABLED: true
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
JOB_NAME: ${{ inputs.name }}
MB_RUN_MODE: "e2e"
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.STAGING_MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.STAGING_MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.STAGING_MB_PRO_SELF_HOSTED_TOKEN }}
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
MB_EXPERIMENTAL_SEARCH_BLOCK_ON_QUEUE: true
MB_SEARCH_ENGINE: appdb
MB_SNOWPLOW_AVAILABLE: true
MB_SNOWPLOW_URL: "http://localhost:9090" # Snowplow micro
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
CYPRESS_QA_DB_MONGO: ${{ inputs.name == 'mongo' }}
steps:
- uses: actions/checkout@v4
with:
@@ -80,9 +72,9 @@ jobs:
openldap: true
webhook: true
snowplow: true
postgres: ${{ inputs.name != 'mongo' }}
mysql: ${{ inputs.name != 'mongo' }}
mongo: ${{ inputs.name == 'mongo' }}
postgres: true
mysql: true
mongo: true
- name: Retrieve uberjar artifact for ${{ inputs.edition }}
uses: ./.github/actions/fetch-artifact
@@ -93,12 +85,8 @@ jobs:
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare JDK 21
uses: actions/setup-java@v4
with:
java-version: 21
distribution: "temurin"
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Prepare Cypress environment
id: cypress-prep
@@ -116,13 +104,19 @@ jobs:
if: github.run_attempt != '1'
run: echo "specs=$(cat failed-specs)" >> $GITHUB_ENV
- name: Compile CLJS
run: yarn build-pure:cljs
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start
- name: Generate database snapshots
env:
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
run: node e2e/runner/run_cypress_ci.js snapshot
- name: Run auto-split Cypress tests on ${{ inputs.name }}
id: split-e2e
if: ${{ !inputs.specs }}
env:
SPLIT: ${{ inputs.total_chunks }}
@@ -133,29 +127,30 @@ jobs:
# do not write cypress-split summary to github
SPLIT_SUMMARY: false
SPEC_PATH: ${{ env.specs || inputs.specs }}
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
shell: bash
run: |
echo "Running tests with specs: $SPEC_PATH"
node e2e/runner/run_cypress_ci.js e2e \
--env grepTags="-@mongo+-@python+-@OSS+-@skip",grepOmitFiltered=true \
--spec "$SPEC_PATH" \
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
--env grepTags="-@mongo+-@python+-@OSS+-@skip" \
--spec "$SPEC_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.
continue-on-error: true
- name: Run Tagged EE Cypress tests on ${{ inputs.name }}
id: tagged-e2e
if: ${{ inputs.specs }}
shell: bash
env:
SPEC_PATH: ${{ env.specs || inputs.specs }}
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
run: |
echo "Running tests with specs: $SPEC_PATH"
node e2e/runner/run_cypress_ci.js e2e \
--env grepTags="${{inputs.tags && format('{0}+-@skip', inputs.tags) || '-@skip'}}",grepOmitFiltered=true \
--spec "$SPEC_PATH" \
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
--env grepTags="${{inputs.tags && format('{0}+-@skip', inputs.tags) || '-@skip'}}" \
--spec "$SPEC_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.
@@ -178,7 +173,8 @@ jobs:
- name: Upload Cypress Artifacts upon failure
uses: actions/upload-artifact@v4
if: failure()
if: |
!cancelled() && (steps.split-e2e.outcome == 'failure' || steps.tagged-e2e.outcome == 'failure')
with:
name: cypress-recording-${{ inputs.name }}-${{ inputs.edition }}
path: |
@@ -188,10 +184,12 @@ jobs:
- name: Upload Failed Tests
uses: actions/upload-artifact@v4
if: failure()
if: |
!cancelled() && (steps.split-e2e.outcome == 'failure' || steps.tagged-e2e.outcome == 'failure')
with:
name: failed-tests-${{ inputs.name }}-${{ inputs.edition }}
path: ./cypress/test-results
if-no-files-found: ignore
- name: Extract chunk-specific changed timings
id: extract-timings

View File

@@ -0,0 +1,274 @@
name: Embedding SDK Component Tests
on:
workflow_call:
env:
DISPLAY: "" # https://github.com/cypress-io/cypress/issues/4034
TERM: xterm
TZ: US/Pacific # to make Node match the instance tz
MB_EDITION: "ee"
jobs:
sdk-component-tests:
name: "SDK component tests (React ${{ matrix.react-version }})"
runs-on: ubuntu-22.04
timeout-minutes: 45
strategy:
matrix:
react-version: [18, 19]
fail-fast: false
env:
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.STAGING_MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.STAGING_MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.STAGING_MB_PRO_SELF_HOSTED_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Prepare Docker containers
uses: ./.github/actions/e2e-prepare-containers
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
maildev: true
openldap: false
webhook: false
snowplow: false
postgres: false
mysql: false
mongo: false
- name: Retrieve uberjar artifact for ee
uses: ./.github/actions/fetch-artifact
with:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
extract-path: "target/uberjar"
output-name: "metabase.jar"
- name: Retrieve Embedding SDK dist artifact
uses: actions/download-artifact@v4
with:
name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
path: ${{ github.workspace }}/resources/embedding-sdk
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start
- name: Make app db snapshot
env:
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
# Component tests only need the default snapshot
run: |
node e2e/runner/run_cypress_ci.js snapshot \
--spec "e2e/snapshot-creators/default.cy.snap.js"
# Has to be run after the app db snapshot is made, as it is not compatible with React 19
- name: Change React version to ${{ matrix.react-version }}
run: ./bin/embedding-sdk/change-react-version.bash ${{ matrix.react-version }}
- name: Run component tests for Embedding SDK
env:
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
run: node e2e/runner/run_cypress_ci.js component
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit
output-name: e2e-embedding-sdk-react-${{ matrix.react-version }}
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: "SDK component tests > Upload Cypress Artifacts upon failure"
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-recording-embedding-sdk-react-${{ matrix.react-version }}
path: |
./cypress
./logs/test.log
if-no-files-found: ignore
- name: "SDK component tests > Publish Summary"
if: failure()
uses: actions/github-script@v7
with:
script: | #js
const {
generateReport,
parseReport,
formatSummary
} = require("./.github/scripts/handle-mochawesome-report.js");
const report = await generateReport();
const results = parseReport(report);
const summary = formatSummary(results);
await core.summary.addRaw(summary).write();
decide-target-ref:
runs-on: ubuntu-latest
outputs:
target-ref: ${{ steps.get-target-ref.outputs.value }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Decide ref to checkout
id: get-target-ref
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "value=${{ github.base_ref }}" >> "$GITHUB_OUTPUT"
else
echo "value=$(git rev-parse HEAD^1)" >> "$GITHUB_OUTPUT"
fi
# This job ensures that the Embedding SDK package from the current commit (N) works with the
# Embedding SDK Bundle (Metabase JAR) from the previous commit (N-1).
# N - 1 is a target of a pull request, or a literal previous commit when this job is run on push in a branch.
sdk-component-tests-backward-compatibility:
name: "SDK component tests (Backward compatibility)"
needs: [decide-target-ref]
runs-on: ubuntu-22.04
timeout-minutes: 45
env:
MB_RUN_MODE: "e2e"
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.STAGING_MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.STAGING_MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.STAGING_MB_PRO_SELF_HOSTED_TOKEN }}
steps:
- name: Check out the code from the previous commit
uses: actions/checkout@v4
with:
ref: ${{ needs.decide-target-ref.outputs.target-ref }}
- name: Prepare Docker containers
uses: ./.github/actions/e2e-prepare-containers
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
maildev: true
openldap: false
webhook: false
snowplow: false
postgres: false
mysql: false
mongo: false
- name: Get the actual commit SHA from the checked out branch
id: get-commit-sha
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Attempt to retrieve the ee uberjar artifact from the previous commit
id: download-uberjar
uses: ./.github/actions/fetch-artifact
with:
name: metabase-ee-${{ steps.get-commit-sha.outputs.sha }}-uberjar
extract-path: "target/uberjar"
output-name: "metabase.jar"
continue-on-error: true # do not break the whole job if this step doesn't succeed
# Build the uberjar from the previous commit only if we couldn't fetch it.
# `step.foo.OUTCOME` is important because it looks at the step status *before* continue-on-error is applied.
# Do not confuse it with the `step.foo.conclusion`.
- name: Build MB uberjar from the commit N-1
if: steps.download-uberjar.outcome != 'success'
run: ./bin/build.sh
- name: Retrieve Embedding SDK dist artifact built from the current commit N
uses: actions/download-artifact@v4
with:
name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
path: ${{ github.workspace }}/resources/embedding-sdk
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start
- name: Make app db snapshot
env:
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
# Component tests only need the default snapshot
run: |
node e2e/runner/run_cypress_ci.js snapshot \
--spec "e2e/snapshot-creators/default.cy.snap.js"
- name: Run component tests for Embedding SDK
env:
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
run: |
node e2e/runner/run_cypress_ci.js component \
--env grepTags="-@skip-backward-compatibility"
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit
output-name: e2e-embedding-sdk
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: Upload Cypress Artifacts upon failure
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-recording-embedding-sdk-cross-version
path: |
./cypress
./logs/test.log
if-no-files-found: ignore
- name: Publish Summary
if: failure()
uses: actions/github-script@v7
with:
script: | #js
const {
generateReport,
parseReport,
formatSummary
} = require("./.github/scripts/handle-mochawesome-report.js");
const report = await generateReport();
const results = parseReport(report);
const summary = formatSummary(results);
await core.summary.addRaw(summary).write();

View File

@@ -1,78 +1,22 @@
name: "[NOT REQUIRED] SDK Compatibility tests"
on:
push:
branches:
- "master"
- "release-**"
pull_request:
types: [opened, synchronize, reopened]
branches:
- "master"
- "release-**"
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
cancel-in-progress: true
workflow_call:
env:
DISPLAY: "" # https://github.com/cypress-io/cypress/issues/4034
TERM: xterm
TZ: US/Pacific # to make Node match the instance tz
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
MB_EDITION: ee
jobs:
files-changed:
name: Check which files changed
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
e2e_embedding_sdk_compatibility: ${{ steps.changes.outputs.e2e_embedding_sdk_compatibility }}
steps:
- uses: actions/checkout@v4
- name: Test which files changed
uses: dorny/paths-filter@v3.0.0
id: changes
with:
token: ${{ github.token }}
filters: .github/file-paths.yaml
# if this is a test on a release branch, we need to check the build requirements
get-build-requirements:
if: |
!cancelled() &&
contains(github.base_ref || github.ref, 'release-x')
runs-on: ubuntu-22.04
timeout-minutes: 10
outputs:
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
node_version: ${{ fromJson(steps.dependencies.outputs.result).node_version }}
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: release
- name: Prepare build scripts
run: cd ${{ github.workspace }}/release && yarn && yarn build
- name: Get build dependencies
uses: actions/github-script@v7
id: dependencies
with:
script: | # js
const {
getBuildRequirements,
getVersionFromReleaseBranch,
} = require('${{ github.workspace }}/release/dist/index.cjs');
const targetBranchName = '${{ github.base_ref || github.ref }}';
const version = getVersionFromReleaseBranch(targetBranchName);
const requirements = getBuildRequirements(version);
return {
java_version: requirements.java,
node_version: requirements.node,
};
get-sample-apps-data:
if: |
!cancelled()
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
# we must support last two stable releases
# we must support the last two stable releases
SUPPORTED_RELEASES_COUNT: 2
TEST_SUITES: |
[
@@ -145,51 +89,6 @@ jobs:
matrix: []
};
build:
needs: [files-changed, get-build-requirements, get-sample-apps-data]
if: |
!cancelled() &&
needs.files-changed.outputs.e2e_embedding_sdk_compatibility == 'true' &&
fromJSON(needs.get-sample-apps-data.outputs.matrix)[0] != null
runs-on: ubuntu-22.04
timeout-minutes: 25
env:
MB_EDITION: ee
INTERACTIVE: false
# make sure that builds on release branches get licenses, because we use them for releases
SKIP_LICENSES: ${{ github.event_name == 'pull_request' }}
steps:
- uses: actions/checkout@v4
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
with:
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
with:
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
- name: Build uberjar with ./bin/build.sh
run: ./bin/build.sh
- name: Prepare uberjar artifact
uses: ./.github/actions/prepare-uberjar-artifact
with:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
- name: 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:
name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
path: resources/embedding-sdk
# In order to check compatibility between Sample Apps and Embedding SDK, the job for each sample app:
# - pulls a Sample App
# - starts it
@@ -197,27 +96,21 @@ jobs:
# The job is not required, though if it's failing better to be sure that it's not caused by a breaking change.
# For more details see `Sample Apps compatibility with Embedding SDK tests` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
e2e-sample-apps-tests:
needs: [get-build-requirements, get-sample-apps-data, build]
needs: [get-sample-apps-data]
strategy:
matrix:
test_suite: ${{ fromJSON(needs.get-sample-apps-data.outputs.matrix) }}
environment: ["production", "development"]
if: |
!cancelled() && needs.build.result == 'success'
!cancelled() && needs.get-sample-apps-data.result == 'success'
runs-on: ubuntu-22.04
timeout-minutes: 45
name: e2e-sample-app-${{ matrix.test_suite }}-tests-${{ matrix.environment }}-bundle
env:
MB_EDITION: ee
DISPLAY: ""
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
MB_RUN_MODE: e2e
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
SAMPLE_APP_BRANCH_NAME: ${{ needs.get-sample-apps-data.outputs.branch_name }}
SAMPLE_APP_ENVIRONMENT: ${{ matrix.environment }}
permissions:
@@ -226,6 +119,8 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/maximize-disk-space
# We have to use the latest version that does not have this issue https://github.com/docker/compose/pull/12752
- name: Set up Docker Compose
uses: docker/setup-compose-action@v1
@@ -240,9 +135,11 @@ jobs:
echo "sample_app_name=${test_suite%-e2e}" >> "$GITHUB_OUTPUT"
- name: Retrieve uberjar artifact for ee
uses: actions/download-artifact@v4
uses: ./.github/actions/fetch-artifact
with:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
extract-path: "target/uberjar"
output-name: "metabase.jar"
- name: Retrieve Embedding SDK dist artifact
uses: actions/download-artifact@v4
@@ -294,11 +191,19 @@ jobs:
if: ${{ steps.check-sample-app-branch.outputs.sample_app_branch_exists == 'true' && matrix.test_suite != 'shoppy-e2e' }}
run: npx tsx ./e2e/runner/embedding-sdk/sample-apps/start-ci.ts ${{ matrix.test_suite }}
- name: Prune build cache
run: docker builder prune -af
- name: Log free disk space
run: df -h /
- name: Run e2e tests for Sample App
id: run-e2e-tests
if: ${{ steps.check-sample-app-branch.outputs.sample_app_branch_exists == 'true' }}
continue-on-error: true
run: node e2e/runner/run_cypress_ci.js ${{ matrix.test_suite }} --browser ${{ steps.cypress-prep.outputs.chrome-path }}
env:
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
run: node e2e/runner/run_cypress_ci.js ${{ matrix.test_suite }}
- name: Upload Cypress Artifacts upon failure
uses: actions/upload-artifact@v4
@@ -322,7 +227,6 @@ jobs:
# The job is not required, though if it's failing better to be sure that it's not caused by a breaking change.
# For more details see `Embedding SDK integration tests with Host Apps` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
e2e-host-apps-tests:
needs: [get-build-requirements, build]
strategy:
matrix:
test_suite:
@@ -333,22 +237,11 @@ jobs:
"angular-20-host-app-e2e",
]
environment: ["production", "development"]
if: |
!cancelled() && needs.build.result == 'success'
runs-on: ubuntu-22.04
timeout-minutes: 45
name: e2e-host-app-${{ matrix.test_suite }}-tests-${{ matrix.environment }}-bundle
env:
MB_EDITION: ee
DISPLAY: ""
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
MB_RUN_MODE: e2e
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
HOST_APP_ENVIRONMENT: ${{ matrix.environment }}
permissions:
id-token: write
@@ -357,9 +250,11 @@ jobs:
- uses: actions/checkout@v4
- name: Retrieve uberjar artifact for ee
uses: actions/download-artifact@v4
uses: ./.github/actions/fetch-artifact
with:
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
extract-path: "target/uberjar"
output-name: "metabase.jar"
- name: Retrieve Embedding SDK dist artifact
uses: actions/download-artifact@v4
@@ -369,22 +264,20 @@ jobs:
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
- name: Prepare JDK 21
uses: actions/setup-java@v4
with:
java-version: 21
distribution: "temurin"
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start
- name: Generate database snapshots
run: node e2e/runner/run_cypress_ci.js snapshot
run: |
node e2e/runner/run_cypress_ci.js snapshot \
--spec "e2e/snapshot-creators/default.cy.snap.js"
- name: Prepare and launch Host App
run: npx tsx ./e2e/runner/embedding-sdk/host-apps/start-ci.ts ${{ matrix.test_suite }}
@@ -392,7 +285,9 @@ jobs:
- name: Run e2e tests for Host App
id: run-e2e-tests
continue-on-error: true
run: node e2e/runner/run_cypress_ci.js ${{ matrix.test_suite }} --browser ${{ steps.cypress-prep.outputs.chrome-path }}
env:
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
run: node e2e/runner/run_cypress_ci.js ${{ matrix.test_suite }}
- name: Upload Cypress Artifacts upon failure
uses: actions/upload-artifact@v4

View File

@@ -0,0 +1,31 @@
name: Embedding SDK Package Build
on:
workflow_call:
workflow_dispatch:
concurrency:
group: embedding-sdk-package-${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
cancel-in-progress: true
jobs:
build-sdk-package:
runs-on: ubuntu-22.04
timeout-minutes: 25
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
- name: 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:
name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
path: resources/embedding-sdk

View File

@@ -2,61 +2,39 @@ name: SDK
on:
workflow_call:
inputs:
cli-snippets-type-check:
description: "Whether to run cli snippets type check."
required: true
type: boolean
docs-snippets-type-check:
description: "Whether to run docs snippets type check."
required: true
type: boolean
documentation-validation:
description: "Whether to run documentation generation validation check."
required: true
type: boolean
component-tests:
description: "Whether to run component tests."
required: true
type: boolean
host-sample-apps-tests:
description: "Whether to run host and sample apps compatibility tests."
required: true
type: boolean
skip:
description: Whether to skip running tests due to one of the artifacts failing to build.
required: true
type: boolean
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
cancel-in-progress: true
jobs:
files-changed:
name: Check which files changed
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
e2e_embedding_sdk: ${{ steps.changes.outputs.e2e_embedding_sdk }}
frontend_embedding_sdk_sources: ${{ steps.changes.outputs.frontend_embedding_sdk_sources }}
embedding_documentation: ${{ steps.changes.outputs.embedding_documentation }}
steps:
- uses: actions/checkout@v4
- name: Test which files changed
uses: dorny/paths-filter@v3.0.0
id: changes
with:
token: ${{ github.token }}
filters: .github/file-paths.yaml
build:
needs: [files-changed]
if: |
!cancelled() &&
(needs.files-changed.outputs.e2e_embedding_sdk == 'true' ||
needs.files-changed.outputs.frontend_embedding_sdk_sources == 'true' ||
needs.files-changed.outputs.embedding_documentation == 'true')
runs-on: ubuntu-22.04
timeout-minutes: 25
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
- name: 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:
name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
path: resources/embedding-sdk
embedding-sdk-cli-snippets-type-check:
needs: [files-changed, build]
if: |
needs.files-changed.outputs.frontend_embedding_sdk_sources == 'true' &&
needs.build.result == 'success'
if: inputs.cli-snippets-type-check && !inputs.skip
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
@@ -72,10 +50,7 @@ jobs:
run: yarn run embedding-sdk:cli-snippets:type-check
embedding-sdk-docs-snippets-type-check:
needs: [files-changed, build]
if: |
needs.files-changed.outputs.embedding_documentation == 'true' &&
needs.build.result == 'success'
if: inputs.docs-snippets-type-check && !inputs.skip
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
@@ -91,10 +66,7 @@ jobs:
run: yarn run embedding-sdk:docs-snippets:type-check
embedding-sdk-api-documentation-generation-validation:
needs: [files-changed, build]
if: |
needs.files-changed.outputs.frontend_embedding_sdk_sources == 'true' &&
needs.build.result == 'success'
if: inputs.documentation-validation && !inputs.skip
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
@@ -140,29 +112,24 @@ jobs:
run: exit 1
# See `Component e2e tests` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
sdk-e2e-tests:
name: "SDK e2e tests"
uses: ./.github/workflows/e2e-component-tests-embedding-sdk.yml
needs: [build]
embedding-sdk-component-tests:
name: "SDK component tests"
if: inputs.component-tests && !inputs.skip
uses: ./.github/workflows/embedding-sdk-component-tests.yml
secrets: inherit
with:
cached-embedding-sdk-dist-artifact-name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
e2e-component-tests-embedding-sdk-backward-compatibility:
name: "SDK e2e backward compatibility tests"
uses: ./.github/workflows/e2e-component-tests-embedding-sdk-backward-compatibility.yml
needs: [build]
not-required-embedding-sdk-apps-compatibility-tests:
name: "SDK e2e tests for compatibility with (host/sample) apps"
if: inputs.host-sample-apps-tests && !inputs.skip
uses: ./.github/workflows/embedding-sdk-host-sample-apps-tests.yml
secrets: inherit
with:
cached-embedding-sdk-dist-artifact-name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
embedding-sdk-tests-result:
needs:
- embedding-sdk-cli-snippets-type-check
- embedding-sdk-docs-snippets-type-check
- embedding-sdk-api-documentation-generation-validation
- sdk-e2e-tests
- e2e-component-tests-embedding-sdk-backward-compatibility
- embedding-sdk-component-tests
if: always() && !cancelled()
runs-on: ubuntu-latest
timeout-minutes: 5

View File

@@ -42,7 +42,7 @@ jobs:
- name: Restore ESLint cache
uses: actions/cache/restore@v4
with:
path: .eslintcache
path: ${{ github.workspace}}/.eslintcache
key: ${{ steps.get-cache-keys.outputs.eslint-cache-key }}
- name: Compile CLJS

View File

@@ -16,7 +16,7 @@ on:
description: 'Seconds (Number of seconds after which next iteration will not start)'
test:
description: 'Test or namespace to run'
default: metabase.query-processor-test.generative-test/execution-with-cards-test
default: metabase.query-processor.generative-test/execution-with-cards-test
ref:
description: 'Ref to run generative tests on'
default: qgen-ms2

198
.github/workflows/llms-txt-generate.yml vendored Normal file
View File

@@ -0,0 +1,198 @@
name: Generate llms.txt file
on:
workflow_call:
inputs:
version:
description: 'Metabase version (e.g. v0.57.0)'
type: string
required: true
branch:
description: 'Target branch (e.g. release-x.57.x)'
type: string
required: true
workflow_dispatch:
inputs:
version:
description: 'Metabase version (e.g. v0.57.0)'
type: string
required: true
branch:
description: 'Target branch (e.g. release-x.57.x)'
type: string
required: true
permissions:
contents: write
pull-requests: write
jobs:
check-version:
name: Check if minor or major release
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
should_generate: ${{ steps.check.outputs.should_generate }}
target_branch: ${{ steps.check.outputs.target_branch }}
version: ${{ steps.check.outputs.version }}
steps:
- name: Check version
id: check
run: |
VERSION="${{ inputs.version }}"
BRANCH="${{ inputs.branch }}"
# Extract version number (e.g., v0.57.0 -> 0.57.0)
VERSION_NUM="${VERSION#v}"
# Count dots to determine version type
# Metabase format: v0.MAJOR.MINOR (3 segments) or v0.MAJOR.MINOR.PATCH (4 segments)
DOT_COUNT=$(echo "$VERSION_NUM" | tr -cd '.' | wc -c | tr -d ' ')
# Only proceed if this is a minor or major release (3 segments)
# Examples of minor/major releases: v0.57.8, v0.59.0
# Skip for patch releases (4 segments): v0.57.8.1
# Note: This is a safety check even though the workflow should only be called
# for minor/major releases, just in case the workflow is dispatched manually.
if [ "$DOT_COUNT" -eq 3 ]; then
echo "⏭️ This is a patch release ($VERSION). Skipping llms.txt generation."
echo "should_generate=false" >> $GITHUB_OUTPUT
else
echo "✅ This is a minor or major release ($VERSION). Proceeding with llms.txt generation for branch: $BRANCH"
echo "should_generate=true" >> $GITHUB_OUTPUT
fi
echo "target_branch=$BRANCH" >> $GITHUB_OUTPUT
echo "version=$VERSION" >> $GITHUB_OUTPUT
generate-llms-txt:
name: Generate llms.txt
needs: check-version
if: needs.check-version.outputs.should_generate == 'true'
runs-on: ubuntu-22.04
timeout-minutes: 15
steps:
- name: Get the generate-llms-txt.js node script via sparse checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
ref: ${{ github.ref }}
sparse-checkout: |
.github/scripts
path: workflow-scripts
- name: Checkout target branch for docs
uses: actions/checkout@v4
with:
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
ref: ${{ needs.check-version.outputs.target_branch }}
path: metabase
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- name: Generate llms.txt
id: generate
run: |
node workflow-scripts/.github/scripts/generate-llms-txt.js metabase/docs ${{ needs.check-version.outputs.target_branch }}
- name: Sanity check generated files
run: |
if [ ! -f "llms.txt" ]; then
echo "❌ Error: llms.txt was not generated"
exit 1
fi
if [ ! -f "llms-embedding-full.txt" ]; then
echo "❌ Error: llms-embedding-full.txt was not generated"
exit 1
fi
# Check that llms.txt contains URLs with the expected GitHub raw URL prefix
URL_COUNT=$(grep -o "https://raw.githubusercontent.com/metabase/metabase/refs/heads/${{ needs.check-version.outputs.target_branch }}/docs" llms.txt | wc -l)
if [ "$URL_COUNT" -lt 10 ]; then
echo "❌ Error: llms.txt appears to be malformed. Found only $URL_COUNT URLs (expected at least 10)"
exit 1
fi
echo "✅ Both llms.txt and llms-embedding-full.txt were generated successfully"
echo "✅ llms.txt contains $URL_COUNT documentation URLs"
- name: Set up git configuration
working-directory: metabase
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
BRANCH_NAME="llms-txt/auto-update-${{ needs.check-version.outputs.target_branch }}-$(date +%Y%m%d-%H%M%S)"
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
echo "Branch name will be: $BRANCH_NAME"
- name: Copy generated files to metabase repo
run: |
cp llms.txt metabase/
cp llms-embedding-full.txt metabase/
- name: Create Pull Request
id: create_pr
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
path: metabase
branch: ${{ env.BRANCH_NAME }}
base: ${{ needs.check-version.outputs.target_branch }}
commit-message: |
Update llms.txt and llms-full.txt (${{ needs.check-version.outputs.target_branch }})
Regenerated llms.txt to include all markdown files from the docs/ directory.
Also generated llms-full.txt files for the embedding section.
🤖 Generated automatically by llms-txt-generate workflow
Co-Authored-By: GitHub Actions <actions@github.com>
committer: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"
author: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"
title: "[chore] Update llms.txt for ${{ needs.check-version.outputs.target_branch }}"
body: |
## Summary
This PR contains automatically generated updates to `llms.txt` and `llms-embedding-full.txt` files, triggered by a minor or major release.
## Changes
- The `llms.txt` file has been regenerated to include all markdown files from the `docs/` directory.
- The `llms-embedding-full.txt` file has been generated for the embedding section (concatenated documentation for RAG).
## Generation
These files were generated using:
- Script: `.github/scripts/generate-llms-txt.js`
- Branch: `${{ needs.check-version.outputs.target_branch }}`
- Base URL: `https://raw.githubusercontent.com/metabase/metabase/refs/heads/${{ needs.check-version.outputs.target_branch }}`
Please review the changes and merge if they look correct.
🤖 Generated automatically by the `llms-txt-generate` workflow.
Co-Authored-By: GitHub Actions <actions@github.com>
labels: |
Type:Documentation
no-backport
add-paths: |
llms.txt
llms-embedding-full.txt
- name: Auto approve PR
if: steps.create_pr.outputs.pull-request-number != ''
working-directory: metabase
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr review "${{ steps.create_pr.outputs.pull-request-number }}" --approve --body "Auto-approved by llms-txt-generate workflow"
- name: Auto merge PR
if: steps.create_pr.outputs.pull-request-number != ''
working-directory: metabase
env:
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
run: |
gh pr merge "${{ steps.create_pr.outputs.pull-request-number }}" --auto --squash

View File

@@ -0,0 +1,114 @@
name: Loki Visual Stress Test Flake Fix
on:
workflow_dispatch:
inputs:
stories_filter:
description: "Regex pattern to filter stories (e.g. 'DataGrid' or 'static-viz|viz')"
type: string
required: true
burn_in:
description: "Number of times to run the test (e.g. 50)"
type: string
required: true
default: "50"
jobs:
workflow-summary:
name: Stress test inputs
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- name: Generate workflow summary
run: |
echo '**Inputs:**' >> $GITHUB_STEP_SUMMARY
echo '' >> $GITHUB_STEP_SUMMARY
echo '- `branch`: ${{ github.ref_name }}' >> $GITHUB_STEP_SUMMARY
echo '- `stories_filter`: ${{ inputs.stories_filter }}' >> $GITHUB_STEP_SUMMARY
echo '- `burn_in`: ${{ inputs.burn_in }}' >> $GITHUB_STEP_SUMMARY
echo '' >> $GITHUB_STEP_SUMMARY
echo 'triggered by: @${{ github.event.sender.login }}' >> $GITHUB_STEP_SUMMARY
stress-test-loki:
runs-on: ubuntu-latest
timeout-minutes: 60
name: Stress test Loki visual tests
services:
docker:
image: docker:19.03.12
options: --privileged
ports:
- 2376:2376
env:
DOCKER_TLS_CERTDIR: /certs
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /tmp/docker-certs:/certs/client
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Prepare frontend environment
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Compile CLJS
run: NODE_ENV=development yarn build-pure:cljs
- name: Build Storybook (once)
run: yarn build-storybook
- name: Stress-test Loki "${{ inputs.stories_filter }}" ${{ inputs.burn_in }} times
run: |
BURN_IN=${{ inputs.burn_in }}
STORIES_FILTER='${{ inputs.stories_filter }}'
echo "Running Loki visual tests $BURN_IN times for stories matching: $STORIES_FILTER"
echo ""
FAILED=0
for i in $(seq 1 $BURN_IN); do
echo "=========================================="
echo "Run $i of $BURN_IN"
echo "=========================================="
if yarn test-visual:loki \
--reactUri file:./storybook-static \
--verboseRenderer \
--storiesFilter "$STORIES_FILTER"; then
echo "✅ Run $i passed"
else
echo "❌ Run $i FAILED"
FAILED=$((FAILED + 1))
mkdir -p .loki/failures/run-$i
cp -r .loki/difference/* .loki/failures/run-$i/ 2>/dev/null || true
fi
echo ""
done
echo "=========================================="
echo "Summary: $((BURN_IN - FAILED))/$BURN_IN passed, $FAILED failed"
echo "=========================================="
if [ $FAILED -gt 0 ]; then
echo "::error::$FAILED out of $BURN_IN runs failed"
exit 1
fi
- name: Generate Visual Report on Failure
if: failure()
run: yarn test-visual:loki-report
- name: Upload Artifact
id: artifact-upload-step
if: failure()
uses: actions/upload-artifact@v4
with:
name: loki-stress-test-report
include-hidden-files: true
path: .loki/
if-no-files-found: ignore

View File

@@ -2,7 +2,9 @@ name: Mage Tests
on:
pull_request:
paths: ["mage/**"]
paths:
- "mage/**"
- "bb.edn"
jobs:
# run mage tests even if the rest of be isnt needed
@@ -13,13 +15,7 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Setup Babashka
uses: turtlequeue/setup-babashka@v1.7.0
with:
babashka-version: 1.12.197
- name: Check bb runs
run: bb --version
- name: bb task list
run: bb tasks
- name: Check mage runs
run: ./bin/mage -h
- name: Run mage tests
run: bb ./mage/test/mage/runtests.clj
run: ./bin/mage -test

227
.github/workflows/minimal-tests.yml vendored Normal file
View File

@@ -0,0 +1,227 @@
name: Minimal Tests
on:
pull_request:
types: [opened, synchronize, reopened, labeled]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
cancel-in-progress: true
jobs:
# Only run if the PR has the minimal-tests label
check-label:
runs-on: ubuntu-latest
timeout-minutes: 1
outputs:
should-run: ${{ steps.check.outputs.result }}
steps:
- name: Check for minimal-tests label
id: check
run: |
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'minimal-tests') }}" == "true" ]]; then
echo "result=true" >> $GITHUB_OUTPUT
else
echo "result=false" >> $GITHUB_OUTPUT
fi
# Postgres app-db tests - single version, single job
postgres-app-db-test:
needs: check-label
if: needs.check-label.outputs.should-run == 'true'
runs-on: ubuntu-22.04
timeout-minutes: 60
env:
CI: 'true'
DRIVERS: postgres
MB_DB_TYPE: postgres
MB_DB_PORT: 5432
MB_DB_HOST: localhost
MB_DB_DBNAME: mb_test
MB_DB_USER: mb_test
MB_POSTGRESQL_TEST_USER: mb_test
services:
postgres:
image: postgres:latest
ports:
- "5432:5432"
env:
POSTGRES_USER: mb_test
POSTGRES_DB: mb_test
POSTGRES_HOST_AUTH_METHOD: trust
name: Postgres Latest EE App DB Tests (Part 1)
steps:
- uses: actions/checkout@v4
- name: Test Postgres App DB
uses: ./.github/actions/test-driver
with:
build-static-viz: true
junit-name: 'minimal-be-tests-postgres-ee'
test-args: >-
:only '["test" "enterprise/backend/test"]'
:exclude-tags '[:mb/driver-tests :mb/transforms-python-test]'
:partition/total 2
:partition/index 0
- 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 }}
# Postgres driver tests
postgres-driver-test:
needs: check-label
if: needs.check-label.outputs.should-run == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
env:
CI: 'true'
DRIVERS: postgres
MB_DB_TYPE: postgres
MB_DB_PORT: 5432
MB_DB_HOST: localhost
MB_DB_DBNAME: mb_test
MB_DB_USER: mb_test
MB_POSTGRESQL_TEST_USER: mb_test
services:
postgres:
image: postgres:latest
ports:
- "5432:5432"
env:
POSTGRES_USER: mb_test
POSTGRES_DB: mb_test
POSTGRES_HOST_AUTH_METHOD: trust
name: Postgres Latest Driver Tests
steps:
- uses: actions/checkout@v4
- name: Test Postgres Driver
uses: ./.github/actions/test-driver
with:
junit-name: 'minimal-be-tests-postgres-driver-ee'
test-args: >-
:only-tags [:mb/driver-tests]
:exclude-tags [:mb/transforms-python-test]
- 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 }}
# Frontend unit tests
frontend-unit-tests:
needs: check-label
if: needs.check-label.outputs.should-run == 'true'
runs-on: ubuntu-22.04
timeout-minutes: 30
env:
JEST_JUNIT_OUTPUT_DIR: ./target/junit
JEST_JUNIT_OUTPUT_NAME: test-report-frontend-unit.xml
name: Frontend Unit Tests
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
- name: Run frontend unit tests
run: yarn run test-unit --silent
continue-on-error: true
- name: Upload Test Results
uses: ./.github/actions/upload-test-results
if: always()
with:
input-path: ./target/junit
output-name: frontend-unit
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 }}
# Summary job
minimal-tests-result:
needs:
- postgres-app-db-test
- postgres-driver-test
- frontend-unit-tests
runs-on: ubuntu-latest
timeout-minutes: 5
name: minimal-tests-result
if: always() && !cancelled()
steps:
- name: Check job status
uses: actions/github-script@v7
env:
needs: ${{ toJson(needs) }}
with:
script: | # js
const needs = JSON.parse(process.env.needs);
const jobs = Object.entries(needs).map(
([jobName, jobValues]) => ({
name: jobName,
result: jobValues.result
}));
// Check if all jobs either succeeded or were skipped
// Skipped jobs are acceptable (they were intentionally skipped when the label is absent)
const allPassedOrSkipped = jobs.every(job =>
job.result === 'success' || job.result === 'skipped'
);
// Check if any jobs actually failed (not skipped, not cancelled)
const anyFailed = jobs.some(job =>
job.result === 'failure'
);
if (allPassedOrSkipped && !anyFailed) {
console.log("");
console.log(" _------. ");
console.log(" / , \_ ");
console.log(" / / /{}\ |o\_ ");
console.log(" / \ `--' /-' \ ");
console.log(" | \ \ | ");
console.log(" | |`-, | ");
console.log(" / /__/)/ ");
console.log(" | | ");
console.log("");
console.log("All minimal tests have passed. Fast feedback achieved!");
process.exit(0);
}
// otherwise, something failed
console.log("");
console.log(" .::::::::::. .::::::::::. ");
console.log(" .::::''''''::::. .::::''''''::::. ");
console.log(" .:::' `::::.... ....::::' `:::. ");
console.log(" .::' `:::::::| |:::::::' `::. ");
console.log(" .::| |::::::|_ ___ __|::::::| |::. ");
console.log(" `--' |::::::|_()__()_|::::::| `--' ");
console.log(" ::: |::-o::| |::o-::| ::: ");
console.log(" `::. .|::::::| |::::::|. .::' ");
console.log(" `:::. .::\-----' `-----/::. .:::' ");
console.log(" `::::......::::' `::::......::::' ");
console.log(" `::::::::::' `::::::::::' ");
console.log("");
console.log("Minimal tests have failed.");
jobs.forEach((job) => {
if (job.result !== 'success' && job.result !== 'skipped') {
console.log(`${job.name} - ${job.result}`);
}
});
process.exit(1);

44
.github/workflows/openapi-check.yml vendored Normal file
View File

@@ -0,0 +1,44 @@
name: OpenAPI Check
on:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
check-openapi-specs:
runs-on: ubuntu-22.04
timeout-minutes: 5
if: contains(github.event.pull_request.labels.*.name, 'openapi-self-healing')
steps:
- uses: actions/checkout@v4
with:
# we're intentionally using METABASE_AUTOMATION_USER_TOKEN to trigger the whole CI pipeline again
# after the self-healing commit is created
# if we used GITHUB_TOKEN, the self-healing commit would not trigger the CI pipeline again
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
# fetch full git history to allow fetching the latest base branch commit and comparing changes
fetch-depth: 0
- name: Setup Node.js 22
uses: actions/setup-node@v4
with:
node-version: 22.x
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Generate version.properties
run: ./bin/build.sh :steps [:version]
- name: Get latest base branch commit
run: |
git fetch origin ${{ github.event.pull_request.base.ref }}
echo "LATEST_BASE_SHA=$(git rev-parse origin/${{ github.event.pull_request.base.ref }})" >> $GITHUB_ENV
- name: Check OpenAPI specs are up to date
env:
AUTO_COMMIT: "true"
PR_BRANCH: ${{ github.event.pull_request.head.ref }}
BASE_SHA: ${{ env.LATEST_BASE_SHA }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
GITHUB_SHA: ${{ github.sha }}
run: ./bin/openapi-check.sh

View File

@@ -10,7 +10,7 @@ concurrency:
jobs:
pr-env:
if: ${{ (github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'PR-Env') && !contains(github.event.pull_request.labels.*.name, 'PR-Env-self-hosting')) || github.event.label.name == 'PR-Env' }}
if: ${{ (github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'PR-Env') && !contains(github.event.pull_request.labels.*.name, 'PR-Env-self-hosting') && !contains(github.event.pull_request.labels.*.name, 'PR-Env-analytics-dev')) || github.event.label.name == 'PR-Env' }}
uses: ./.github/workflows/pr-env-destroy.yml
secrets: inherit
with:
@@ -22,3 +22,10 @@ jobs:
secrets: inherit
with:
self_hosting: true
pr-env-analytics-dev:
if: ${{ (github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'PR-Env-analytics-dev')) || github.event.label.name == 'PR-Env-analytics-dev' }}
uses: ./.github/workflows/pr-env-destroy.yml
secrets: inherit
with:
self_hosting: false

View File

@@ -10,7 +10,7 @@ concurrency:
jobs:
uberjar:
if: ${{ github.event.label.name == 'PR-Env' || github.event.label.name == 'PR-Env-self-hosting' }}
if: ${{ github.event.label.name == 'PR-Env' || github.event.label.name == 'PR-Env-self-hosting' || github.event.label.name == 'PR-Env-analytics-dev' }}
uses: ./.github/workflows/uberjar.yml
secrets: inherit
@@ -21,6 +21,7 @@ jobs:
secrets: inherit
with:
self_hosting: false
analytics_dev_mode: false
pr-env-self-hosting:
needs: [uberjar]
@@ -29,3 +30,13 @@ jobs:
secrets: inherit
with:
self_hosting: true
analytics_dev_mode: false
pr-env-analytics-dev:
needs: [uberjar]
if: ${{ github.event.label.name == 'PR-Env-analytics-dev' }}
uses: ./.github/workflows/pr-env.yml
secrets: inherit
with:
self_hosting: false
analytics_dev_mode: true

View File

@@ -9,6 +9,11 @@ on:
required: false
type: boolean
default: false
analytics_dev_mode:
description: 'Enable analytics development mode'
required: false
type: boolean
default: false
jobs:
build:
runs-on: ubuntu-latest
@@ -132,6 +137,7 @@ jobs:
PR_NUMBER: ${{ github.event.number }}
MB_PREMIUM_EMBEDDING_TOKEN: ${{ secrets.PR_ENV_MB_PREMIUM_EMBEDDING_TOKEN }}
SHA: ${{ github.event.pull_request.head.sha || github.sha }}
MB_ANALYTICS_DEV_MODE: ${{ inputs.analytics_dev_mode && 'true' || 'false' }}
- name: Deploy PR Review ENV
if: ${{ !inputs.self_hosting }}
run: |
@@ -157,6 +163,7 @@ jobs:
DB_USERNAME: ${{ secrets.PR_ENV_DB_USER }}
DB_PASSWORD: ${{ secrets.PR_ENV_DB_PASSWORD }}
CONFIG: ${{ secrets.PR_ENV_CONFIG }}
MB_ANALYTICS_DEV_MODE: ${{ inputs.analytics_dev_mode && 'true' || 'false' }}
- name: Setup Helm
if: ${{ inputs.self_hosting }}
@@ -191,4 +198,4 @@ jobs:
✅ Preview:
https://pr${{ github.event.number }}.coredev.metabase.com
🗒️ [login instructions](https://www.notion.so/metabase/Ephemeral-PR-Environments-c74a3710c87a460dbf4fc0007a001458)
📦 Deployment type: ${{ inputs.self_hosting && 'PR-Env-self-hosting' || 'PR-Env' }}
📦 Deployment type: ${{ inputs.self_hosting && 'PR-Env-self-hosting' || (inputs.analytics_dev_mode && 'PR-Env-analytics-dev' || 'PR-Env') }}

View File

@@ -166,11 +166,8 @@ jobs:
snowplow: true
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Prepare JDK 21
uses: actions/setup-java@v4
with:
java-version: 21
distribution: "temurin"
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
@@ -189,24 +186,32 @@ jobs:
- name: Run Metabase
run: node e2e/runner/run_cypress_ci.js start
# For now we only need the default snapshots for pre-release checks.
# If we decide to include tests that rely on the external QA databases, we should:
# 1. remove the --spec ... line
# 2. add postgres, mysql, and mongo to the prepare-containers step
- name: Make app db snapshot
run: node e2e/runner/run_cypress_ci.js snapshot
run: |
node e2e/runner/run_cypress_ci.js snapshot \
--spec "e2e/snapshot-creators/default.cy.snap.js"
- name: Run a few important OSS Cypress tests as sanity check
if: ${{ matrix.edition == 'oss' }}
env:
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
run: |
node e2e/runner/run_cypress_ci.js e2e \
--env grepTags="@smoke+-@EE",grepOmitFiltered=true \
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
--env grepTags="@smoke+-@EE" \
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)'
- name: Run a few important EE Cypress tests as sanity check
if: ${{ matrix.edition == 'ee' }}
env:
CYPRESS_BROWSER: ${{ steps.cypress-prep.outputs.chrome-path }}
run: |
node e2e/runner/run_cypress_ci.js e2e \
--env grepTags="@smoke+-@OSS",grepOmitFiltered=true \
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
--env grepTags="@smoke+-@OSS" \
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)'
- name: Upload Cypress Artifacts upon failure
uses: actions/upload-artifact@v4

View File

@@ -0,0 +1,44 @@
name: Querying On-call PagerDuty Alert
on:
issues:
types:
- labeled
jobs:
notify-querying-on-call:
runs-on: ubuntu-22.04
timeout-minutes: 5
if: |
(github.event.label.name == 'Priority:P0' || github.event.label.name == 'Priority:P1' || github.event.label.name == '.Escalation') &&
contains(github.event.issue.labels.*.name, '.Team/Querying')
steps:
- name: Setting title
uses: actions/github-script@v7
id: vars
with:
script: |
core.setOutput('issue_title', ${{ toJson(github.event.issue.title) }}.replaceAll(/"/g, '\\"'));
- name: Trigger PagerDuty Incident
run: |
curl -X POST https://events.pagerduty.com/v2/enqueue \
-H 'Content-Type: application/json' \
-d '{
"routing_key": "${{ secrets.QUERYING_PAGERDUTY_INTEGRATION_KEY }}",
"event_action": "trigger",
"dedup_key": "github-issue-${{ github.event.issue.number }}",
"payload": {
"summary": "[${{ github.event.label.name }}] ${{ steps.vars.outputs.issue_title }}",
"source": "GitHub Issues - ${{ github.repository }}",
"severity": "critical",
"custom_details": {
"Labels": "${{ join(github.event.issue.labels.*.name, ', ') }}"
}
},
"links": [
{
"href": "${{ github.event.issue.html_url }}",
"text": "View GitHub Issue"
}
]
}'

View File

@@ -383,28 +383,16 @@ jobs:
run: |
echo //registry.npmjs.org/:_authToken=${{ secrets.NPM_RELEASE_TOKEN }} > .npmrc
TAG=$(jq -r --null-input \
--arg branch "${{ inputs.branch }}" \
--arg masterTag "${{ steps.compute-tag.outputs.masterTag }}" '
{
"master": $masterTag,
"release-x.51.x": "51-stable",
"release-x.52.x": "52-stable",
"release-x.53.x": "53-stable",
"release-x.54.x": "54-stable",
"release-x.55.x": "55-stable",
"release-x.56.x": "56-stable"
}[$branch]'
)
TAG="${{ steps.compute-tag.outputs.masterTag }}"
echo "Resolved npm tag: $TAG"
npm publish --tag "$TAG"
- name: Add `latest` tag to the latest release branch (`release-x.55.x`) deployment
if: ${{ inputs.branch == 'release-x.56.x' }}
working-directory: sdk
run: |
npm dist-tag add @metabase/embedding-sdk-react@${{ env.sdk_version }} latest
# ⚠️ This step should only be executed on the latest stable (gold) release branch.
# Only uncomment this when the new release branch becomes stable (gold).
# - name: Add `latest` tag to the latest release branch (`release-x.55.x`) deployment
# working-directory: sdk
# run: |
# npm dist-tag add @metabase/embedding-sdk-react@${{ env.sdk_version }} latest
git-tag:
needs: [publish-npm, determine-sdk-version]

View File

@@ -424,6 +424,19 @@ jobs:
}
});
# updates the llms.txt asynchronously.
# release does not need to wait for this PR to be merged,
# because the llms.txt is in the main git repo.
trigger-update-llms-txt:
# do not trigger llms.txt update on automatic patch releases
if: ${{ !inputs.auto }}
needs: add-extra-tags
uses: ./.github/workflows/llms-txt-generate.yml
secrets: inherit
with:
version: ${{ inputs.version }}
branch: ${{ github.ref_name }}
draft-release-notes:
if: ${{ !inputs.auto }}
needs: add-extra-tags

View File

@@ -12,7 +12,7 @@ on:
jobs:
files-changed:
if: ${{ !contains(github.event.pull_request.labels.*.name,'ci skip') }}
if: ${{ !contains(github.event.pull_request.labels.*.name,'ci skip') && !contains(github.event.pull_request.labels.*.name,'minimal-tests') }}
name: Check which files changed
runs-on: ubuntu-22.04
timeout-minutes: 5
@@ -25,6 +25,10 @@ jobs:
frontend_all: ${{ steps.changes.outputs.frontend_all }}
frontend_sources: ${{ steps.changes.outputs.frontend_sources }}
documentation: ${{ steps.changes.outputs.documentation }}
embedding_documentation: ${{ steps.changes.outputs.embedding_documentation }}
embedding_sdk_components: ${{ steps.changes.outputs.embedding_sdk_components }}
embedding_sdk_host_sample_apps: ${{ steps.changes.outputs.embedding_sdk_host_sample_apps }}
embedding_sdk_ci: ${{ steps.changes.outputs.embedding_sdk_ci }}
steps:
- uses: actions/checkout@v4
- name: Test which files changed
@@ -36,49 +40,19 @@ jobs:
list-files: csv
filters: .github/file-paths.yaml
static-viz-files-changed:
name: Check whether static-viz files changed
if: ${{ !contains(github.event.pull_request.labels.*.name,'ci skip') }}
runs-on: ubuntu-22.04
timeout-minutes: 10
outputs:
static_viz: ${{ steps.static_viz.outputs.static_viz }}
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
- name: Build static-viz frontend
run: yarn build-static-viz
env:
MB_EDITION: ee
- name: Upload Static Viz Bundle Artifact
uses: actions/upload-artifact@v4
with:
name: static-viz-bundle-${{ github.sha }}
path: resources/frontend_client/app/dist
- name: Check for static viz changes
uses: dorny/paths-filter@v3.0.0
id: static_viz
with:
token: ${{ github.token }}
filters: .github/static-viz-sources.yaml
uberjar:
needs: [files-changed, static-viz-files-changed]
needs: [files-changed]
if: ${{ !cancelled() && !(needs.files-changed.outputs.documentation == 'true' && needs.files-changed.outputs.backend_all == 'false' && needs.files-changed.outputs.frontend_all == 'false' && needs.files-changed.outputs.e2e_all == 'false') }}
uses: ./.github/workflows/uberjar.yml
secrets: inherit
backend-tests:
if: ${{ !cancelled() && needs.files-changed.result == 'success' }}
needs: [files-changed, static-viz-files-changed]
needs: [files-changed]
uses: ./.github/workflows/backend.yml
secrets: inherit
with:
skip: ${{ needs.files-changed.outputs.backend_all != 'true' && needs.static-viz-files-changed.outputs.static_viz != 'true' }}
skip: ${{ needs.files-changed.outputs.backend_all != 'true' }}
semantic-search-tests:
needs: files-changed
@@ -122,21 +96,42 @@ jobs:
# list of changed specs files, then only specs are changed and we can run only those specs
specs: ${{ needs.files-changed.outputs.e2e_all_files == needs.files-changed.outputs.e2e_specs_files && needs.files-changed.outputs.e2e_specs_files || '' }}
embedding-sdk-package:
needs: [files-changed]
if: |
!cancelled() &&
(needs.files-changed.outputs.embedding_sdk_components == 'true' ||
needs.files-changed.outputs.frontend_sources == 'true' ||
needs.files-changed.outputs.embedding_documentation == 'true' ||
needs.files-changed.outputs.embedding_sdk_ci == 'true')
uses: ./.github/workflows/embedding-sdk-package-build.yml
secrets: inherit
sdk-tests:
needs: files-changed
needs: [uberjar, embedding-sdk-package, files-changed]
if: always()
uses: ./.github/workflows/embedding-sdk.yml
secrets: inherit
with:
cli-snippets-type-check: ${{ needs.files-changed.outputs.frontend_sources == 'true' }}
docs-snippets-type-check: ${{ needs.files-changed.outputs.embedding_documentation == 'true' }}
documentation-validation: ${{ needs.files-changed.outputs.frontend_sources == 'true' }}
component-tests: ${{ needs.files-changed.outputs.embedding_sdk_components == 'true' }}
host-sample-apps-tests: ${{ needs.files-changed.outputs.embedding_sdk_host_sample_apps == 'true' }}
skip: ${{ needs.embedding-sdk-package.result != 'success' || needs.uberjar.result != 'success' }}
pr-env:
needs: [uberjar]
if: |
!cancelled() &&
contains(github.event.pull_request.labels.*.name, 'PR-Env') &&
!contains(github.event.pull_request.labels.*.name, 'PR-Env-self-hosting')
!contains(github.event.pull_request.labels.*.name, 'PR-Env-self-hosting') &&
!contains(github.event.pull_request.labels.*.name, 'PR-Env-analytics-dev')
uses: ./.github/workflows/pr-env.yml
secrets: inherit
with:
self_hosting: false
analytics_dev_mode: false
pr-env-self-hosting:
needs: [uberjar]
@@ -147,6 +142,18 @@ jobs:
secrets: inherit
with:
self_hosting: true
analytics_dev_mode: false
pr-env-analytics-dev:
needs: [uberjar]
if: |
!cancelled() &&
contains(github.event.pull_request.labels.*.name, 'PR-Env-analytics-dev')
uses: ./.github/workflows/pr-env.yml
secrets: inherit
with:
self_hosting: false
analytics_dev_mode: true
containerize:
needs: [uberjar]

View File

@@ -27,7 +27,7 @@ jobs:
- name: Semantic Search Tests
build-static-viz: false
test-args: >-
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
:only '["enterprise/backend/test/metabase_enterprise/semantic_search" "enterprise/backend/test/metabase_enterprise/metabot_v3/tools/semantic_search_test.clj"]'
exclude-tag: ':mb/driver-tests'
services:
@@ -85,7 +85,7 @@ jobs:
- name: Semantic Search Tests
build-static-viz: false
test-args: >-
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
:only '["enterprise/backend/test/metabase_enterprise/semantic_search" "enterprise/backend/test/metabase_enterprise/metabot_v3/tools/semantic_search_test.clj"]'
exclude-tag: ':mb/driver-tests'
services:
@@ -157,7 +157,7 @@ jobs:
- name: Semantic Search Tests
build-static-viz: false
test-args: >-
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
:only '["enterprise/backend/test/metabase_enterprise/semantic_search" "enterprise/backend/test/metabase_enterprise/metabot_v3/tools/semantic_search_test.clj"]'
exclude-tag: ':mb/driver-tests'
services:
@@ -229,7 +229,7 @@ jobs:
- name: Semantic Search Tests
build-static-viz: false
test-args: >-
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
:only '["enterprise/backend/test/metabase_enterprise/semantic_search" "enterprise/backend/test/metabase_enterprise/metabot_v3/tools/semantic_search_test.clj"]'
exclude-tag: ':mb/driver-tests'
services:

View File

@@ -3,15 +3,15 @@ name: "Snyk"
on:
push:
branches:
- 'master'
- 'release-**'
- "master"
- "release-**"
paths:
- '**/deps.edn'
- '**/package.json'
- '.github/workflows/snyk.yml'
- '.github/scripts/write-poms.sh'
- "**/deps.edn"
- "**/package.json"
- ".github/workflows/snyk.yml"
- ".github/scripts/write-poms.sh"
schedule:
- cron: '0 5 * * *'
- cron: "0 5 * * *"
jobs:
# Generate pom.xml files for all Maven projects
@@ -45,26 +45,6 @@ jobs:
file: yarn.lock
package-manager: yarn
category: main-frontend-yarn
- name: Embedding SDK Template
file: bin/embedding-sdk/templates/yarn.lock
package-manager: yarn
category: embedding-sdk-template
- name: E2E Angular 20 Host App
file: e2e/embedding-sdk-host-apps/angular-20-host-app/package-lock.json
package-manager: npm
category: e2e-angular-host
- name: E2E Next 15 App Router
file: e2e/embedding-sdk-host-apps/next-15-app-router-host-app/package-lock.json
package-manager: npm
category: e2e-next-app-router
- name: E2E Next 15 Pages Router
file: e2e/embedding-sdk-host-apps/next-15-pages-router-host-app/package-lock.json
package-manager: npm
category: e2e-next-pages-router
- name: E2E Vite 6 Host App
file: e2e/embedding-sdk-host-apps/vite-6-host-app/package-lock.json
package-manager: npm
category: e2e-vite-host
- name: Release Helper
file: release/yarn.lock
package-manager: yarn

View File

@@ -15,8 +15,8 @@ jobs:
BRANCH_NAME: update-translations-${{ github.run_id }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ github.token }}
GITHUB_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
@@ -107,7 +107,7 @@ jobs:
- name: Auto approve PR
uses: juliangruber/approve-pull-request-action@v1
with:
github-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
github-token: ${{ github.token }}
number: ${{ steps.create_pr.outputs.pr_number }}
- name: Enable Pull Request Automerge

View File

@@ -146,7 +146,13 @@ jobs:
runs-on: ubuntu-22.04
name: Is ${{ matrix.edition }} (java ${{ matrix.java-version }}) healthy?
needs: [build, check-existing-artifacts]
if: always() && !cancelled() && (needs.build.result == 'success' || (needs.check-existing-artifacts.outputs.should_build == 'false' && needs.check-existing-artifacts.outputs.ee_exists == 'true' && needs.check-existing-artifacts.outputs.oss_exists == 'true'))
# We only care about the explicit JAR health check on push to `master` and the `release-` branches.
# JARs created in random branches on PRs are 99% of the time treated as ephemeral, and used only in e2e tests.
# E2E tests already have a step where they wait for the instance health check.
if: |
always() && !cancelled() &&
(github.ref_name == 'master' || startsWith(github.ref_name, 'release-')) &&
(needs.build.result == 'success' || (needs.check-existing-artifacts.outputs.should_build == 'false' && needs.check-existing-artifacts.outputs.ee_exists == 'true' && needs.check-existing-artifacts.outputs.oss_exists == 'true'))
timeout-minutes: 10
strategy:
matrix:

View File

@@ -16,5 +16,5 @@ jobs:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- run: clojure -T:whitespace-linter lint
- run: clojure -T:whitespace-linter lint :whitespace-linter/progress-bar false
name: Run Whitespace Linter

6
.gitignore vendored
View File

@@ -21,7 +21,8 @@
/*.mv.db
/*.trace.db
/.babel_cache
/.env
/.env*
!/.env.example
/.envrc
/.lein-env
/.lein-failures
@@ -104,6 +105,7 @@ dev/serialization_deltas/
*.tsbuildinfo
/trace-output/
/temp-types/
/frontend/src/metabase-types/openapi
**/cypress_sample_database.json
**/cypress_sample_instance_data.json
@@ -111,6 +113,7 @@ dev/serialization_deltas/
/frontend/src/cljs_release
.shadow-cljs
.clerk
mise.local.toml
# lsp: ignore all but the config file
.lsp/*
@@ -163,3 +166,4 @@ CLAUDE.local.md
/logs
/.clojure-mcp

View File

@@ -1,6 +1,3 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn precommit
# Run the formatter
@@ -9,4 +6,4 @@ yarn precommit
# ATM, you can manually run ./bin/cljfmt_staged.sh if you want to format locally staged files and inspect after.
# ./bin/cljfmt_staged.sh
./hooks/pre-commit.nocommit
./hooks/pre-commit.nocommit

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

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