Compare commits

...

196 Commits

Author SHA1 Message Date
Jeff Bruemmer
d585a8b779 update copy for remote sync settings 2025-11-05 17:01:41 -05:00
github-automation-metabase
f6582c78d1 Bump org.clojure/clojure from 1.12.2 to 1.12.3 (#64158)
Inspect dependency changes here: https://github.com/clojure/clojure/blob/clojure-1.12.3/changes.md

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-05 21:46:55 +00:00
Nick Fitzpatrick
10deae2a03 removing new badge for move questions into their dashboards (#65485) 2025-11-05 17:39:06 -04:00
Braden Shepherdson
b910dc5566 chore: removing a stub CLJC file that got included accidentally (#65437) 2025-11-05 21:05:39 +00:00
Cam Saul
65a4a7c9e8 Fix kondo failure in master (#65496) 2025-11-05 13:04:47 -08:00
Alex Yarosh
8ab634d497 docs : clarify subscription settings (#65179)
* Update wording for subscriptions and alerts section

* Update docs/permissions/application.md

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

---------

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2025-11-05 19:08:06 +00:00
github-automation-metabase
9431038a75 Update generated docs (master) (#65453)
Co-authored-by: github-actions <github-actions@github.com>
2025-11-05 14:01:21 -05:00
github-automation-metabase
cccb11b0d2 Bump org.eclipse.jetty/jetty-server from 12.0.24 to 12.1.3 (#65034)
* Bump org.eclipse.jetty/jetty-server from 12.0.24 to 12.1.3

Inspect dependency changes here:

* Add other Jetty deps bumps

---------

Co-authored-by: Cam Saul <github@camsaul.com>
2025-11-05 18:19:16 +00:00
github-automation-metabase
53a2da3c62 Bump org.graalvm.polyglot/polyglot from 24.2.2 to 25.0.1 (#65038)
* Bump org.graalvm.polyglot/polyglot from 24.2.2 to 25.0.1

Inspect dependency changes here: https://github.com/oracle/graal/compare/graal-24.2.2...graal-25.0.1

* Consolidate deps bumps

---------

Co-authored-by: Cam Saul <github@camsaul.com>
2025-11-05 18:18:37 +00:00
github-automation-metabase
8be450aa19 Bump io.netty/netty-common from 4.1.124.Final to 4.2.7.Final (#64827)
* Bump io.netty/netty-common from 4.1.124.Final to 4.2.7.Final

Inspect dependency changes here:

* Consolidate deps bumps

---------

Co-authored-by: Cam Saul <github@camsaul.com>
2025-11-05 17:55:34 +00:00
Oleksandr Yakushev
22929ac32b [mage] Use Babashka to run cljfmt on staged files in git pre-commit hook (#65026) 2025-11-05 19:23:53 +02:00
Oleksandr Yakushev
b2b5720843 [flake] Increase test timeout in metabase.app-db.liquibase-test (#64814) 2025-11-05 19:04:08 +02:00
Oleksandr Yakushev
8abb1420e0 [qp] Reuse oridinarily compiled query as inline if it doesn't have params (#64651) 2025-11-05 18:59:22 +02:00
Ryan Laurie
23287f9f28 Toggle dark mode from command palette (#65359)
* toggle dark mode from command palette

* I'm sorry I built this in a dumb way Ryan

---------

Co-authored-by: Nick Fitzpatrick <nickfitz.582@gmail.com>
2025-11-05 16:32:46 +00:00
Noah Moss
06e016fe4e Surface collection descriptions to metabot in search (#65442)
* Surface collection descriptions to metabot in search

* Fetch descriptions as a post-processing step as they're not indexed
2025-11-05 11:15:24 -05:00
Jakub Chodorowicz
be8686b577 feat: make metabot logo follow the bran colors (#65358)
# Conflicts:
#	frontend/src/metabase/common/components/MetabotLogo/MetabotLogo.stories.tsx

# Conflicts:
#	loki.config.js
2025-11-05 16:51:58 +01:00
Aleksandr Lesnenko
71eb726eb5 upgrade to echarts v6 (#64139)
* upgrade to echarts v6

* Update Loki Snapshots

* Fix BE test

* update gridlines helper function

* adjust test

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
Co-authored-by: Nick Fitzpatrick <nickfitz.582@gmail.com>
2025-11-05 11:45:47 -04:00
Anderson
60c65add21 Make sure /dirty is called when moving an entity out of the library (#65259)
* Make sure /dirty is called when moving an entity out of the library

* Untouch embedding code / Clean up / Add some tests

* Check cache from both entities and RTK / Undo unnecessary changes

* Make sure getCollectionFromCollectionsTree gets collection from latest query
2025-11-05 11:22:47 -03:00
Stas Gavrylov
e65f73716c GDGT-1185: Columns appear twice in model list view until action taken (#65412)
* List View: Fix incorrect bg color initialization

* GDGT-1185: Fix columns list initiation in ListView configuration screen

* GDGT-1185: Update e2e test

* GDGT-1185: Fix lint

* GDGT-1185: Fix unit tests

* GDGT-1185: Address PR comments

* GDGT-1185: Minor refactoring
2025-11-05 16:14:56 +02:00
Ngoc Khuat
be8790142c Proxy apis for store to get plan and addons (#65423) 2025-11-05 13:02:39 +00:00
Uladzimir Havenchyk
d04a2452f4 chore: ignore e2e embedding host apps from linting (#65467) 2025-11-05 15:58:27 +03:00
Oleksandr Solovyov
6ff47bfe22 metabot: handle (and propagate) request cancellation (#65461) 2025-11-05 14:37:27 +02:00
Timofey Kachalov
2df9e2645f Fix getNextSdkVersion helper (#65466) 2025-11-05 16:26:48 +04:00
Nicolò Pretto
1e997d6d5c ci: allow running stress tests on sdk tests (#64759)
* ci: allow running stress tests on sdk tests

* type choice

* yeah this should work 🤞

* ok we should also build the sdk

* maybe this time

* do we need to setup the BE?

* Revert "do we need to setup the BE?"

This reverts commit 7e9092e2c3.

* trying the auto infer thing out

* refactor and move the logic up to dedup it

* rename output

* move up env?

* Revert "move up env?"

This reverts commit f78f72e396.

* increase timeout to make stress test with throttling pass

* increase the timeout even more :shrugs:
2025-11-05 10:31:41 +01:00
Timofey Kachalov
381d156ca6 Use stableStringify for PublicOrEmbedDashboardView story + add StrictUnion type (#65411) 2025-11-05 12:51:48 +04:00
Nemanja Glumac
43301c49ad Stabilize and deduplicate eslint cache (#65410) 2025-11-05 09:31:47 +01:00
Nathan Voxland
a133b31fc4 Renamed Library to Synced Collection (#65447)
Renamed Library to Synced Collection
2025-11-04 23:32:13 -06:00
github-automation-metabase
d632109808 Bump cider/piggieback from 0.6.0 to 0.6.1 (#63218)
Inspect dependency changes here:

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-05 00:49:45 +00:00
github-automation-metabase
a316b1d9d3 Bump com.metabase/athena-jdbc from 3.5.0 to 3.6.0 (#64166)
Inspect dependency changes here:

Co-authored-by: Cam Saul <1455846+camsaul@users.noreply.github.com>
2025-11-05 00:41:06 +00:00
github-automation-metabase
d7a97b5704 Bump com.google.cloud/google-cloud-bigquery from 2.54.2 to 2.55.3 (#65041)
Inspect dependency changes here: https://github.com/googleapis/java-bigquery/blob/v2.55.3/CHANGELOG.md
2025-11-05 00:28:05 +00:00
github-automation-metabase
53fdb817c4 Bump io.github.clojure/tools.build from 0.10.10 to 0.10.11 (#65334)
Inspect dependency changes here: https://github.com/clojure/tools.build/blob/v0.10.11/CHANGELOG.md
2025-11-05 00:21:57 +00:00
github-automation-metabase
ead22c46a3 Bump ch.qos.logback/logback-classic from 1.5.18 to 1.5.20 (#64819)
Inspect dependency changes here:
2025-11-05 00:13:30 +00:00
github-automation-metabase
1615c60cbf Bump org.apache.sshd/sshd-core from 2.16.0 to 3.0.0-M2 (#65031)
Inspect dependency changes here:
2025-11-05 00:08:47 +00:00
github-automation-metabase
b3fa75c941 Bump dk.ative/docjure from 1.21.0 to 1.22.0 (#64821)
Inspect dependency changes here: https://github.com/mjul/docjure/blob/v1.22.0/CHANGELOG.md
2025-11-04 16:05:24 -08:00
github-automation-metabase
2821954e9b Bump software.amazon.awssdk/s3 from 2.33.0 to 2.36.2 (#65039)
* Bump software.amazon.awssdk/s3 from 2.33.0 to 2.36.2

Inspect dependency changes here:

* Consolidate deps bumps

---------

Co-authored-by: Cam Saul <github@camsaul.com>
2025-11-05 00:02:22 +00:00
github-automation-metabase
d4acb644ee Bump com.microsoft.sqlserver/mssql-jdbc from 13.2.0.jre11 to 13.2.1.jre11 (#64831)
Inspect dependency changes here:
2025-11-04 23:58:12 +00:00
github-automation-metabase
1236a70059 Bump nrepl/nrepl from 1.4.0 to 1.5.1 (#64823)
Inspect dependency changes here: https://github.com/nrepl/nrepl/blob/v1.5.1/CHANGELOG.md
2025-11-04 15:53:52 -08:00
github-automation-metabase
ab8fcd54b0 Bump com.facebook.presto/presto-jdbc from 0.294 to 0.295 (#64829)
Inspect dependency changes here:
2025-11-04 15:49:09 -08:00
github-automation-metabase
6dbe6594a7 Bump com.databricks/databricks-jdbc from 2.7.3 to 3.0.1 (#64828)
Inspect dependency changes here:
2025-11-04 15:37:15 -08:00
github-automation-metabase
f83b585668 Bump com.amazonaws/aws-java-sdk-core from 1.12.788 to 1.12.792 (#64403)
Inspect dependency changes here:
2025-11-04 15:19:09 -08:00
github-automation-metabase
53d01c5274 Bump cider/cider-nrepl from 0.57.0 to 0.58.0 (#64820)
Inspect dependency changes here: https://github.com/clojure-emacs/cider-nrepl/blob/v0.58.0/CHANGELOG.md
2025-11-04 15:07:32 -08:00
Timofey Kachalov
8137d490b3 Adjust parameter_mappings for a text dashcard when its variable is removed (#64463) 2025-11-05 02:53:44 +04:00
metamben
e39c2119d2 Add creator_id for transform (#65388)
* Add creator_id for transform

Closes QUE-2715
2025-11-05 01:46:34 +03:00
Nathan Voxland
c471c5640d Improve tracking for new objects that get deleted before sync (#65433) 2025-11-04 16:36:55 -06:00
Fraser
2f49744ee1 Remove parsing from file download e2e tests (#65081)
* Make e2e download tests more lightweight

* Fix helper to handle redirects
2025-11-05 10:18:43 +13:00
Nick Fitzpatrick
283eae65b6 Adding collection name to recent documents (#65376)
* Adding collection name to recent documents

* re-arranging e2e test
2025-11-04 17:07:36 -04:00
Braden Shepherdson
1217fca9a4 [perf] Add lib.computed, optimize wide tables and deep user queries (#65364)
Part of #64774.

Hopefully this is sufficient to unblock users seeing the high CPU times
like in #64774. I discovered other, less significant performance issues
during this investigation that I'll be addressing in follow-up PRs.

### Investigation Notes

The problem query and relevant table metadata from a helpful customer
was taking 950ms to preprocess and compile on my 2022 M1 Max, running
Metabase in dev mode but with Malli schema enforcement disabled.

The query is pretty big! It uses 3 tables with 200-300 columns each,
has several stages including some from a joined card, and ends up with
several stages doing two levels of aggregation. It also includes
several *huge* `:case` expressions.

The optimizations below have reduce the time required from 950ms to 310ms
on my machine. A 3x improvement, but I think there's more to be gained in
the follow-up PRs I mentioned.

### Optimizations

Main optimizations:

- `lib.util/find-stage-index-and-clause-by-uuid` pre-computed and cached
  on each stage, saved 120ms on the above query.
- `lib.metadata.cached-provider/fields` attempts to pre-load the cache
  of individual `lib.metadata/field` calls, having just fetched them
  all, but it used the wrong key and they were all misses instead!
- `expression-metadata` and `aggregation-metadata` are recomputed over
  and over again by their stage and later stages; cache them by value
- `returned-columns` was cached at the top level and frequently missed
  because of dumb details like explicit stage 1 vs. -1 for last stage.
  - Switched it to caching on individual `returned-columns-method`s
    with more precise cache keys.

#### New Caching Approach

Both of the latter two are using a new caching approach: a weak map
using queries as keys. Since CLJ(S) maps are immutable, any change to
the query means a new pointer.

That's still far more eviction than optimal! Most edits to a query
don't actually invalidate most of the cached values! But it's a lot
better than what we had before, and because the map's keys are weak
references, the queries and their cached data are not retained any
longer than the query itself.

### New Benchmarking Tools

I also added a `qp.perf-test` namespace with some metadata providers
with 10-, 100-, 1000- and 10,000-column tables for testing.

So far the tests it performs are quite basic, though. I'll be adapting
the user-provided query into a test case in the future, since it's an
excellent real-world example of a complex but not pathological query.
2025-11-04 20:49:25 +00:00
Jeff Bruemmer
5884bfe547 docs - various edits (#65422)
* various edits

* edits
2025-11-04 14:39:26 -05:00
Aleksandr Lesnenko
9d1d534e51 remote sync analytics (#65129) 2025-11-04 18:38:23 +00:00
Nick Fitzpatrick
2fb4793c24 fix large command palette subtext elements, add loki testing (#65369)
* fix large command palette subtext elements, add loki testing

* how did I miss this?

* updating Overlay demo
2025-11-04 13:23:12 -04:00
Nathan Voxland
954857c036 Clean up remote sync source vs. snapshot APIs (#65122) 2025-11-04 11:00:45 -06:00
Oleksandr Yakushev
6d1d618fff [util] Explicitly test for BigDecimals in real-number? (#65202) 2025-11-04 18:24:45 +02:00
Aleksandr Lesnenko
785c418578 allow disabling remote sync (#65175) 2025-11-04 15:45:41 +00:00
Ryan Laurie
9d1c3c0ab4 Release Log Upgrades (#65186)
* support tag refs in version log

* release log upgrades

* use html url

* no thanks

* update tests

* ok review bot, you win
2025-11-04 08:33:21 -07:00
Brad Anderson
57daa4d5dc Fix #50044 - Updates dashcard loading state so it shows the correct title while it's loading (#65363) 2025-11-04 10:19:19 -05:00
Chris Truter
805badeb79 Flake protection 🥐 (#65415) 2025-11-04 12:27:56 +00:00
Nemanja Glumac
5ea9541981 Fix the auto-patch workflow (#65417) 2025-11-04 13:12:53 +01:00
Abed Habli
72a7ebec91 V57 docs: updating Alerts + Model view (#65353)
* update screenshot

* Updating model list view

* updating screenshots to Model view

* Optimized 4 images, saved 406.0 KB (50.9% smaller)

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-11-04 12:16:11 +01:00
Nemanja Glumac
cdb6640ea4 Resolve a missing pre-release output (#65413)
[ci skip]
2025-11-04 12:07:38 +01:00
Chris Truter
8b90ffd906 Exclude other users collections in metabot search (#65348)
Closes BOT-496
2025-11-04 11:54:34 +02:00
Timofey Kachalov
3758d88539 Add embedding_type field for card/dashboard (#65209) 2025-11-04 12:45:57 +04:00
Aleksandr Lesnenko
d6397e205e skip flaky UpsellBigCard loki specs (#65404)
* skip flaky UpsellBigCard loki specs

* Update Loki Snapshots

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-11-04 08:21:26 +03:00
Noah Moss
01f7eeb023 Recreate model index quartz triggers on job initialization when needed (#65394)
* Recreate model index quartz triggers on job initialization when needed

* whitespace

* rename var + add comment
2025-11-03 19:32:49 -05:00
Nathan Voxland
8f3730dd45 Improving git management for remote sync (#65249) 2025-11-03 16:19:31 -06:00
dpsutton
5e92088c7d remove useless log (#65390)
```
Updating table metadata for Table 5465 ''properati_ar.properties_rent_201607'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5465 ''properati_ar.properties_rent_201607'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5485 ''properati_ar.properties_sell_201706'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5485 ''properati_ar.properties_sell_201706'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5468 ''properati_ar.properties_rent_201602'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5468 ''properati_ar.properties_rent_201602'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5511 ''properati_ar.properties_rent_201612'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5511 ''properati_ar.properties_rent_201612'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5431 ''properati_ar.properties_sell_201802'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5431 ''properati_ar.properties_sell_201802'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5441 ''properati_ar.properties_sell_201707'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5441 ''properati_ar.properties_sell_201707'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5467 ''personal_bq_repro.events_20230519'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5467 ''personal_bq_repro.events_20230519'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5484 ''properati_ar.properties_sell_201708'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5484 ''properati_ar.properties_sell_201708'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5434 ''properati_ar.resultados_apto_credito'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5434 ''properati_ar.resultados_apto_credito'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5501 ''properati_ar.properties_sell_201704'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5501 ''properati_ar.properties_sell_201704'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5433 ''properati_ar.properties_rent_201604'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5433 ''properati_ar.properties_rent_201604'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5478 ''properati_ar.properties_sell_201702'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5478 ''properati_ar.properties_sell_201702'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5498 ''properati_ar.properties_sell_201512'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5498 ''properati_ar.properties_sell_201512'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5447 ''properati_ar.properties_rent_201709'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5447 ''properati_ar.properties_rent_201709'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5463 ''properati_ar.properties_rent_201609'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5463 ''properati_ar.properties_rent_201609'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
Updating table metadata for Table 5448 ''properati_ar.properties_rent_201509'' {mb-quartz-job-type=SyncAndAnalyzeDatabase}
:is_writable of Table 5448 ''properati_ar.properties_rent_201509'' changed from null to null {mb-quartz-job-type=SyncAndAnalyzeDatabase}
```

We unconditionally say we are updating table metadata, but then when we
actually change anything we of course include the table name.

Note here there is some kind of bug that we are changing the
table (which property??) from null to null.
2025-11-03 16:02:18 -06:00
Jeff Bruemmer
2da5fb8aa8 token data (#65396) 2025-11-03 21:43:00 +00:00
Uladzimir Havenchyk
a94a70fe46 chore: cleanup warnings from postcss (#64954)
* chore: cleanup warnings from postcss

* Update frontend/src/metabase/common/components/EmojiPicker/EmojiPicker.module.css

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

---------

Co-authored-by: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>
2025-11-04 00:08:22 +03:00
Oleksandr Yakushev
5880342225 Remove unused metabase.util.formatting.numbers and metabase.util.formatting.time (#63791) 2025-11-03 22:37:47 +02:00
Jeff Bruemmer
89adf23ef7 update api docs (#65382) 2025-11-03 14:30:57 -05:00
Denis Berezin
7c7241d350 UXW-2182 fix codemirror editor suggestions styles in light mode (#65367) 2025-11-03 22:03:53 +03:00
Jeff Bruemmer
9638db8b02 json from data-url (#65374) 2025-11-03 18:47:47 +00:00
AlessioLaiso
bace3da926 Updates 6 illustrations for dark mode (#65375) 2025-11-03 14:31:13 -04:00
Ryan Laurie
898c82ad4c add v57 to version-helpers (#65227) 2025-11-03 18:29:18 +00:00
Ryan Laurie
c9792f6604 Restore calendar hover styles (#65361)
* restore calendar hover styles

* fix calendar picker hover states

* remove unnecessary rule
2025-11-03 11:28:02 -07:00
Noah Moss
ec0bc5e081 Comment out BackfillTransformSourceType migration (#65147) 2025-11-03 13:20:13 -05:00
Nathan Voxland
9b4c474e11 Remote sync should ignore system git settings (#65293) 2025-11-03 11:38:47 -06:00
metamben
8f10457e32 Add archived flag to graph endpoints (#65366)
Fixes QUE-2708
2025-11-03 16:43:27 +00:00
AlessioLaiso
20b3834269 Updates 35 SVG illustrations (#65232)
* Updates 35 SVG illustrations

The same asset now works well for both light and dark mode.

* branding OnboardingIllustration, adding cloug and bug metabot to metabot logo

* PR Feedback

---------

Co-authored-by: Nick Fitzpatrick <nickfitz.582@gmail.com>
2025-11-03 12:24:40 -04:00
Denis Berezin
0150dcfe07 UXW-2170 cleanup chart brush (#65313) 2025-11-03 18:49:40 +03:00
Riley Thompson
2b2a22b86d filter for active fields (#65245) 2025-11-03 15:11:08 +00:00
Noah Moss
d3e976ed53 Annotate draft transforms in user_is_viewing context with source type when possible (#65283)
* Annotate draft transforms in user_is_viewing context with source type when possible

* add unit tests

* Move transform-source-type helper to transform utils; some refactor

* switch to use lib/native-only-query; change default transform query in tests to use mbql5

* switch batch to using lib.query/native?

* switch back to native-only-query?

* clean ns
2025-11-03 09:56:29 -05:00
lbrdnk
c950dad7eb Fix suggested prompts schema and add test (#65299) 2025-11-03 15:33:50 +01:00
lbrdnk
2693173e7f Compute param values from card results (#64318)
* Compute param values from card results

seq for bool

Tests, multi-stage queries

Compute values also for params on nested stages

whitespace

Unused ns

Last stage check first

Docstring

Drop base query's last stage clauses

Address review remarks

Apply suggestions from code review

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

Remove redundant ops

Adjust for test

Search for col also in aggregated result columns

Look for breakoutable column only if source-uuid is present

* symb

* Rebase fix

* fix rebase, remove unused module

* post rebase, fix getting database id

* kondo

* Revamp

* limit

* Adjust the solution for impl joins

* Fix e2e

* Comment

* Cleanup

* Cleanup

* comment

* comment

* Update src/metabase/parameters/dashboard.clj

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

* indent

---------

Co-authored-by: metamben <103100869+metamben@users.noreply.github.com>
2025-11-03 15:33:39 +01:00
Denis Berezin
3ca4c5a2ee UXW-175 Fix visualization mode switch for pivot table (#65252) 2025-11-03 17:18:36 +03:00
Denis Berezin
9c0910f652 UXW-2172 UXW-2174 remove Document cards click actions (#65191)
* UXW-2172 UXW-2174 remove Document cards click actions

* Fix e2e

* UXW-2172 fix broken click actions for Document cards

* Restore e2e

* Fix typecheck

* review fixes
2025-11-03 17:18:21 +03:00
Mahatthana (Kelvin) Nomsawadi
cbf7579c4c Correct interactive embed query execution count (#65336)
* Simplify the FE API code

* Exclude static embed preview from being counted in analytics

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

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

* Clarify comments

* Add tests

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-03 13:11:10 +00:00
Nemanja Glumac
5ec5c9a9d3 Fix and revive the backend cloverage workflow (#65341) 2025-11-03 11:22:02 +01:00
github-automation-metabase
9ee26d70fd Bump com.ibm.icu/icu4j from 77.1 to 78.1 (#65332)
Inspect dependency changes here:
2025-11-03 09:30:00 +00:00
github-automation-metabase
73aab1d129 Bump djblue/portal from 0.61.0 to 0.62.0 (#65333)
Inspect dependency changes here: https://github.com/djblue/portal/blob/0.62.0/CHANGELOG.md
2025-11-03 09:29:14 +00:00
Oleksandr Yakushev
6375368c92 [kondo] Encourage more m.util.performance functions in perf-sensitive namespaces (#65331) 2025-11-03 11:09:43 +02:00
Nemanja Glumac
ee3cfb7e68 Disable CodeQL trap caching (#65275) 2025-11-03 09:52:34 +01:00
metamben
e62903b72a Add test case missing from #65240 (#65327)
The PR #65240 got merged without this test.
2025-11-02 02:58:31 +02:00
metamben
652f725d41 Make transforms available in search for admins only (#65240)
* Make transforms available in search for admins only

Fixes QUE-2710

* Fix test
2025-11-01 02:42:23 +03:00
Dan Stone
2c49eb977d Add missing .result to script output lookup in pre-release (#65298) 2025-10-31 23:02:21 +00:00
Brad Anderson
b70e091fe8 Fix #64685 - Update brand colors in UI without needing refresh (#65292)
* UXW-1991 Fixes various issues both new and old with the Branding page like the colors not updating until refresh and swatches not updating when setting colors back to their defaults

* UXW-1991 Uses hex format for brand colors placeholders

* UXW-1991 Fix persistence issues with setting/unsetting accent colors
2025-10-31 18:39:08 -04:00
Brad Anderson
dff2d77981 UXW-2183 Remove fullscreen dashboard night mode toggle (#65312) 2025-10-31 18:16:07 -04:00
Robert Kosara
60ec838229 Remove mention of "night mode" and image (#65318)
* Remove mention of "night mode" and image

Removed mention of 'Night mode' from fullscreen dashboard instructions.

* Delete dark mode/night mode image
2025-10-31 21:44:44 +00:00
dpsutton
830a6d5c83 Don't count app-db not setup errors in circuit breaker (#65295)
we want to not hammer the network when things are down. But during
startup we don't need to circuit break these errors that we throw before
the app-db is read
2025-10-31 16:33:27 -05:00
github-actions[bot]
e0ebddd4f2 Update translations 2025-10-30 (#65213)
* Update translation sources 2025-10-30

* Update translations

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-10-31 20:45:47 +00:00
metamben
79b350eca6 Make sure enough info about transforms is selected (#65291)
Fixes QUE-2731
2025-10-31 23:41:25 +03:00
Riley Thompson
af1be91a28 Implement connection impersonation for starburst (#64972)
* implemenet impersonation driver methods

* replace starburst impersonation

* use user as default role

* clean up

* enable starburst tests

* mount files to container

* add config files

* fix rules.json

* add starburst impersonation tests

* try fix

* remove old tests

* debug

* Debug'

* add volumes original way

* try again

* revert

* try docker run

* remove services

* add back accessc control

* enable impersonation

* exclude starburst tests again
2025-10-31 18:29:05 +00:00
Robert Kosara
6322ffc3b3 Small edits to v57 docs about Glossary, dark mode, and progress bars (#65253)
* Enhance glossary section with context for definitions

This is a smaller change than I expected, since glossary terms don't show up in searches yet. Might just cut this if it doesn't add anything useful. I also wasn't sure if we should mention Metabot here.

* Add dark mode options

Adds the available options and explains that you don't have to reload the page

* Add a little clarification to the computed goal example

This confused me, so I'm adding this little clarification

* Jeff's suggested change

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

* Remove the bit about LLMs again

---------

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2025-10-31 18:17:36 +00:00
Edward Paget
e657e83c3e fix: allow stacktraces to be suppressed in API (#65215)
* fix: allow stacktraces to be suppressed in API

Allows administrators to configure their metabase instance using
MB_HIDE_STACKTRACES to prevent stacktraces from appearing in API
response. For standard responses it replaces unhandled exceptiosn with a
generic message and 500 response. For streaming responses it leaves the
error message and strips out the trace/via keys to prevent exception
info from leaking.

* fixup! dissoc traces from map errors
2025-10-31 09:12:45 -05:00
Nemanja Glumac
4b3c293f04 Remove superfluous python setup from H2 driver test (#65272) 2025-10-31 15:09:48 +01:00
Brad Anderson
1447fa0e95 Fix: UXW-2171 Prevents "Edit Query" from clearing name on chart (#65224) 2025-10-31 09:38:55 -04:00
Edward Paget
cb2510a55d fix: pivoting json values (#65183)
* fix: pivoting json values

* fixup! kondos in test

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

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

---------

Co-authored-by: Ryan Laurie <30528226+iethree@users.noreply.github.com>
2025-10-31 08:35:55 -05:00
Nemanja Glumac
90f2e42b19 Sunset e2e cross-version tests (#65269)
Context: https://metaboat.slack.com/archives/C0669P4AF9N/p1761905881175819

The requirements for new and updated attempt at solving this problem are documented in:
https://linear.app/metabase/issue/DEV-1042/design-reliable-cross-version-upgradedowngrade-test-strategy
2025-10-31 14:34:09 +01:00
Mahatthana (Kelvin) Nomsawadi
cbcb70a438 Fix deleted documents were editable (#65136)
* Prevent trashed documents from being edited

* Add test

* Soften the test name tone

* Disallow even updating document when archived via API

* Add BE test

* Fix Cypress test issue reference

* Update tests after merging master

* Only check for archived when not unarchiving

* Don't check archived documents when archiving or unarchiving them

* Add missing condition from merging
2025-10-31 19:15:46 +07:00
lbrdnk
e47e51c229 Metabot glossary integration (#65223)
* Return glossary with user info

* Test glossary in response
2025-10-31 12:25:34 +01:00
Jeff Bruemmer
e6a3974c9a Fix env var doc gen (#65230)
* fix issue with env var gen and some cleanup

* cleanup
2025-10-31 07:00:20 -04:00
Dan Stone
247db60bb7 Increase sync timeout in execution test (#65205)
Redshift sync of even one table can take a really long time (sometimes
over 5 seconds).

Increased to 10 seconds for now.
2025-10-31 10:40:35 +00:00
Jeff Bruemmer
619d9350cc remove registry (#65242) 2025-10-31 03:14:57 +00:00
Nemanja Glumac
9b53db936e Fix logs upload for drivers (#65257)
* Fix logs upload for drivers

When we introduced `continue-on-error` to the "test" step, we had to
update the conditionals for the test report steps as well. I've
introduced a bug by checking for a failure, instead of saying - upload
test reports whenever the job is not successful.

Hint: test.outcome means "step status BEFORE continue-on-error overrides
the exit code"
2025-10-31 02:33:06 +01:00
Nemanja Glumac
024d197e3e Upgrade CodeQL action version (#65250) 2025-10-31 14:04:55 +13:00
metamben
7937c6888c Optimize graph API endpoints (#65172) 2025-10-30 19:41:16 -04:00
github-actions[bot]
3369bf7d15 Update E2E test timings with averaged data (#65024)
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>
2025-10-30 22:58:27 +00:00
Uladzimir Havenchyk
c7fb07c387 deps: drop react-beautiful-dnd (#64713)
Co-authored-by: Fraser <fraser@metabase.com>
2025-10-31 11:24:41 +13:00
Noah Moss
525dec7eb0 Metabot /debug mode to show tool calls (#64811)
* add debug message type for tool calls

* rename toolCalls -> activeToolCalls

* Basic debug mode slash command to hide/show tool calls

* ToolCallDetailsModal + better formatting

* Fix type

* Fix types, some simplification

* Address minor bot comments

* small changes

* move AgentToolCallMessage into its own file and add copy buttons + tool call id to modal

* fix copied value

* add unit tests

* move failure case further downstream to mitigate any possible customer issue

* ci fixes

---------

Co-authored-by: Sloan Sparger <sloansparger@gmail.com>
2025-10-30 17:20:39 -05:00
Ryan Laurie
f4dde2f744 fix comma in pre-release workflow (#65248) 2025-10-30 20:51:46 +00:00
Nemanja Glumac
c81e28e240 Support releases with different token testing strategies (#65203) 2025-10-30 21:29:02 +01:00
Alexander Polyankin
b859cbfd59 Extract QueryEditor from transforms (#65160) 2025-10-30 20:03:01 +00:00
Nick Fitzpatrick
99a736360b update document title compare to determine dirty state (#65229) 2025-10-30 19:50:30 +00:00
Alexander Polyankin
93d099427e Enable dependency graph UI (#65210) 2025-10-30 19:38:58 +00:00
Nick Fitzpatrick
6fafafe082 fix falsey check when removing card embed from document (#65222) 2025-10-30 16:36:25 -03:00
Nick Fitzpatrick
1a2035d5a4 update hover colors in UserListElement (#65174)
* update hover colors in UserListElement

* adjusting colors

* updating comment
2025-10-30 16:35:27 -03:00
Phoomparin Mano
186df5d802 fix(sdk): non-editable dashboard should not have "add a chart" button and title should be read-only (#65102) 2025-10-31 02:24:32 +07:00
Sloan Sparger
27d13486ac [Metabot] Copy change for suggested prompts setting description (#65163)
* update copy

* adjust copy for embedded metabot

* oops

* remove randomly

* fix test

* feedback
2025-10-30 13:53:33 -05:00
Edward Paget
41ba6ce845 Fix renamed test helper in documents (#65233) 2025-10-30 18:51:32 +00:00
Riley Thompson
1eb96fc1ec return false instead of throw (#65225) 2025-10-30 18:45:40 +00:00
Edward Paget
bbc81e20b3 test a document creation in personal collection (#65118)
* test a document creation in personal collection

* fixup! ws
2025-10-30 12:33:41 -05:00
Stas Gavrylov
fafc53e645 GDGT-1083: Improve visual design for new List view in Stats before v57 (#64957)
* GDGT-1083: Add new icons

* Remove subtitle column. Restyle inputs. Extend icon selection

* GDGT-1083: Fix minor tags input styling issues

* GDGT-1083: Replace semantic colors with accent colors

* GDGT-1083: Add image column selection option

* GDGT-1083: Add placeholder for image column icon. Fix bug with selected icon

* GDGT-1083: Update formatted column values rendering rules

* GDGT-1083: Fix incorrect entity icon initialization

* GDGT-1083: Add range viz rendering for quantity/score columns

* GDGT-1083: Fix drag from ListViewColumnsSidebar

* GDGT-1083: Fix list header grid

* GDGT-1083: Fix State column styling

* GDGT-1083: Fix incorrect rendering for boolean columns

* GDGT-1083: Fix incorrect column rendering for empty cells

* GDGT-1083: Address design review comments

* GDGT-1083: Fix TS error

* GDGT-1083: Fix image column rendering

* GDGT-1083: Minor refactoring

* GDGT-1083: Update e2e est

* GDGT-1083: Add unit test for ListViewItem component

* GDGT-1083: Fix linter

* Fix eslint

* GDGT-1083: Resolve metabot comments

* GDGT-1083: Get rid of split_currency setting

* wip

* GDGT-1083: Address PR comments

* GDGT-1083: Address PR comments

* GDGT-1083: Replace switch logic with fns. Fix header layout bug

* GDGT-1083: Fix badges cursor in list view

* GDGT-1083: Fix cursor styling when dragging over full tags input

* GDGT-1083: Remove max-width

* GDGT-1083: Fix linter

* GDGT-1083: Fix lint

* GDGT-1083: Fix incorrect imgURL/avatarURL column rendering after refactoring

* Fix incorrect icon background color

* Fix incorrect category columns rendering

* Update Loki Snapshots

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2025-10-30 16:58:37 +00:00
Nathan Voxland
d0f5d01eea Create appdb tables in its own connection (#65171) 2025-10-30 10:33:35 -05:00
Nicolò Pretto
a04b79857f remove border from dashboard header where header=false and no tabs (#65161)
* remove border from dashboard header where header=false and no tabs

* move css code up to keep no border in fullscreen
2025-10-30 16:00:07 +01:00
Denis Berezin
9f0f6eb78c UXW-2091 user without collection access to Our Analytics can't save documents (#65159)
* UXW-2091 user without collection access to Our Analytics can't save documents

* fix typecheck

* Fix types

* Add e2e tests
2025-10-30 17:56:02 +03:00
Edward Paget
7ea1d83a67 fix: skip join in stats handler test (#64639) 2025-10-30 09:27:17 -05:00
Edward Paget
9aa6611557 fix: improve collections graph performance (#65098)
* fix: improve collections graph performance

Fixes performance generating and updating a collection graph by avoiding
the cross join of all negative permissions (blocks) between groups and
collections. Instead it builds sparse graph where missing entries for
group/collection paris can be assumed to be :none permissions.

In practice this drops a collection permission update on a graph of 5K
groups and 5K collections from a greater than 10min operation on my
local machine against MySQL to a .5s operation.

* fixup! explicilty disj :root in other places

* fixup! improve some docs

* fixup! improve more docs

* fixup! seq checks

* fixup! blank lines

* fixup! convert raw sql concat into honeysql

* fixup! e2e test
2025-10-30 09:26:26 -05:00
Edward Paget
a7b420eeba Update error message for remote sync dep checking (#65148)
* Update error message for remote sync dep checking

Try to make these error messages less jargony because they are presented
by the user interface when dependency checking content fails.

Closes UXW-2142 and UXW-1879.

* Update some missed tests
2025-10-30 09:25:33 -05:00
dpsutton
7b8edfbad4 Token grace period (#64938)
* Add a grace period to token checks

There's more work on this namespace to be done i think, but this is a
first cut at it. There's a lot of control flow by exceptions which is
how we jump around in here. Fundamentally this should be far
simpler. Will take a crack at that shortly. I also don't love that this
just hammers the `fetch-token-status` function and then memoizes inside
of that. Would prefer simpler layout of `token-features` function and
that can be aware of population issues.

Adds a simple protocol: GracePeriod, which has two functions: save! and
retrieve. On successful token check, we `save!` the response. On errors,
we `retrieve` previous responses. This obviously can be nil in the case
we have never had a successful response, and will become nil once the
grace period's internal notion of time expires.

This implementation is based on guava's cache which has a nifty
expireafterwrite functionality.

```
 (*token-features*) ;; call this function to simulate the check of features
Checking with the MetaStore to see whether token 'f325...d01a' is valid...
Reporting Metabase stats: {... user counts etc}
 -> #{"features come back"}
 ;; meanwhile clear cache to simulate elapsing of 12 hours

 (*token-features*) ;; call function again to simulate check of features
2025-10-22 21:30:26,620 INFO premium-features.token-check :: Checking with the MetaStore to see whether token 'f325...d01a' is valid...
2025-10-22 21:30:26,622 ERROR premium-features.token-check :: Error fetching token status from https://token-check.metabase.com:
clojure.lang.ExceptionInfo: network issues ;; hit network issue

2025-10-22 21:30:26,632 INFO premium-features.token-check :: Using token from grace period
->> #{graceperiod network features}
...

;; here after 5 seconds (in real life will be 36 hours)
2025-10-22 21:31:00,064 WARN premium-features.token-check :: Removing token: f325...d01a from grace period cache {mb-quartz-job-type=Cache}
```

* tests that updating value populates grace period cache

* couple changes

protect against storing nil value. guava cache doesn't like it so gone
it is.

added some tests:

```clojure
(testing "Setting a new value populates the grace period cache"
    (let [new-token (tu/random-token)]
      (binding [http/request (fn [& _] {:status 200
                                        :body "{\"valid\":true,\"status\":\"fake\",\"features\":[\"fake\",\"features\"]}"})]
        (mt/discard-setting-changes [premium-embedding-token]
          (premium-features.settings/premium-embedding-token! new-token)
          (is (= #{"fake" "features"} (token-check/*token-features*)))
          (is (= {:valid true :status "fake" :features ["fake" "features"]}
                 (token-check/retrieve token-check/grace-period new-token)))))))
```

But this ended up leaving a setting table value for this value. i don't
feel like looking into discard setting changes so i'm gonna just remove it

* attempt to simplify the api a bit

the thee important functions are now `token-information`, `harness` and
`decode-token`.

Everyone should use token-information. Harness hooks up the grace period
and retry strategies, and `decode-token` only cares about decoding a
token. It should return the token-status map {:valid true ...} or throw.

* fixup test

* clean up tests and rename a bit

* remove comment block

* remove commented out grace period

* bit of cleanup

* fix with-random-premium-token! macro

* function composes them instead of caller

rather than a caller needing to know all of the layers, i thread them
for you and let you provide all arugments in one function call.

dynamic var for needing to customize layers in tests. largely for
removing the circuit-breaker which is stateful and hard to restart if
you want to simulate errors in tests

* rename test
2025-10-30 08:51:56 -05:00
Damien Chambe
07172f56f7 Update DB2 driver and IBM i driver (#65190)
IBM i has a separate driver , different from DB2 LUW ( linux/unix/windows )
2025-10-30 08:56:12 -04:00
Ngoc Khuat
9f93683518 Usage analytics update v57 (#65055)
* Add documents to content view

* add document to audit_log

* added comment events to the audit log, publish events

* wip: transform events

* glossary

* reversion the content migrations

* include transforms in content

* remote sync audit events

* wip: action v2 event

* kondo

* fix action tests

* transform run event

* add tests for new events

* bump

* tests

* task data

* let's not change the old migration in case we might break the hashsum

* typo

* more typos

* fix bugs in h2/mysql

* add :previous-object

* fix tests

* move branch into details

* fix test

* fix: run tests only on ee

---------

Co-authored-by: Nicola Mometto <nicola.mometto@metabase.com>
2025-10-30 10:43:48 +00:00
Sébastien
23574a80d5 Closes UXW-1993 tooltip columns in visualizer (#65042) 2025-10-30 07:05:27 +01:00
appleby
74113f603b Add :order-by to metabase-enterprise.transforms.api/get-transforms (#65162)
To ensure transforms are returned in a consistent order to and reduce test flakes.

https://metaboat.slack.com/archives/C5XHN8GLW/p1761753664842279
2025-10-30 01:11:13 +00:00
Cam Saul
622125d9d9 Disable Claude code review bot by default (#65184) 2025-10-29 21:04:51 -04:00
Sébastien Corbin
f6b1864d91 Add color-scheme meta tag for light and dark modes (#64324) 2025-10-29 18:20:16 -06:00
metamben
6b098da5de Normalize parameter type category/= to category (#65158)
* Normalize parameter type category/= to category

Stats had exactly one dashboard with one such parameter and that dashboard was immutable because the
before-update hook failed before any update could happen.
2025-10-29 23:42:40 +00:00
Ryan Laurie
6b09c0476c dont break scheduled patches (#65165) 2025-10-29 16:30:18 -06:00
Nathan Voxland
a94c284625 Remote-sync error handling improvements (#65072)
* - Improve remote-sync error messages
- Do a fetch when checking git settings to ensure the current version can be read and is being checked

* Validate git url

* Validate branch name in production mode

* Validate branch name in production mode

* Removed unneeded assoc

* Fixed formatting

* Code improvements

* Code improvements

* Allow direct path URLs

* Allow direct path URLs

* E2e Fixes

* E2e Fixes

* Allow empty branch to be passed
2025-10-29 14:15:33 -07:00
Nick Fitzpatrick
fdac82dba2 show a warning message when removing items from the library (#65169) 2025-10-29 14:00:31 -07:00
Denis Berezin
46b8b2791d UXW-1872 Fix some tooltips text color in dark theme (#65182) 2025-10-29 23:52:59 +03:00
Cam Saul
fd476e892b Fix slow metabase.core.modules-test/modules-config-up-to-date-test (#65168)
* Fix slow `metabase.core.modules-test/modules-config-up-to-date-test`

* Fix docstring location

* The bot caught something else
2025-10-29 12:30:22 -07:00
Timofey Kachalov
63f85c3706 feat(embed-js): Convert EmbedJS wizard into a modal (#65113) 2025-10-29 23:03:34 +04:00
Nick Fitzpatrick
9c6e1d1b7d Dark mode day 5 patch (#65099)
* Dark Mode Dashboard PDFS, bad solution for google login

* various fixes

* handfull of fixes

* PR Feedback

* stupid linter
2025-10-29 11:33:22 -07:00
Cam Saul
7d879a9a86 Legacy MBQL normalization overhaul: 3x faster and bug fixes (#65018)
* Legacy MBQL normalization overhaul

* Kondo + test fixes 🔧

* Cleanup and test fixes 🔧

* Code cleanup

* Test fixes 🔧

* Extra test 🔧

* Some test fixes 🔧

* Test fixes 🔧

* Test fixes 🔧

* Test fixes 🔧

* Fix SerDes test failure

* cljfmt

* Code cleanup

* Fix normalizing :datetime with bytes modes

* Fix legacy MBQL normalization of :datetime

* Handle broken case clauses

* Set Card metadata to nil when invalid

* Fixx

* Fix Kondo
2025-10-29 11:18:28 -07:00
Marcos
80ac5931a0 Fix x axis range calculation when undefined values are present (#65125)
* fix x axis range calculation when null values are present

* only remove undefined values

* rename variable instead of mutating function param
2025-10-29 15:11:14 -03:00
Jeff Bruemmer
fabb975482 docs - public documents and downloads (#65155)
* document public links and downloads

* edits

* link fixes

* Update docs/embedding/public-links.md
2025-10-29 17:57:05 +00:00
Timofey Kachalov
d1c40b6c81 Restore sdk backward compat tests (#65154) 2025-10-29 19:20:08 +04:00
Nemanja Glumac
95fa314e44 Delete superfluous test (#65153)
This is already covered in LicenseAndBillingSettings.unit.spec.tsx
2025-10-29 14:51:55 +00:00
Nick Fitzpatrick
5ded6d9623 Remote sync e2e followup (#65061)
* Fix/unskip some tests / try to make flaky FE test to pass in CI

* adding branching tests, unskipping admin tests

* PR Feedback

* PR Feedback

---------

Co-authored-by: Anderson <anderson@metabase.com>
2025-10-29 11:37:29 -03:00
Nick Fitzpatrick
4c160134ba only delay modal dismiss on success (#65127) 2025-10-29 11:29:06 -03:00
Nemanja Glumac
46894a8008 Update module ownership (#65150) 2025-10-29 15:11:48 +01:00
Nemanja Glumac
215a3c6c49 Fix the hard coded store api url in billing (#65135) 2025-10-29 14:05:30 +00:00
Jeff Bruemmer
4d14b02aa2 documents - add public links (#64630) 2025-10-29 13:38:57 +00:00
Noah Moss
6bcfc60eff Add source_type field to transforms with temporary backfill job (#64970)
* Add type field to transforms with temporary backfill job

* add a default value for tests

* add some new tests, fix serdes

* lint

* remove debugging defs

* revert serdes spec change

* Revert "remove transforms from serdes baseline (?)"

This reverts commit e8fc8fe80bfe15e00eb031b4050877f271b8081f.

* try again to fix serialization tests

* address bot comments

* Revert "try again to fix serialization tests"

This reverts commit 13d78664b79b7f13406d89e1f8f910610ea2cce9.

* Fix search ingestion functions to use :type field + some cleanup

* Update baseline to fix serialization test

* Revert "Update baseline to fix serialization test"

This reverts commit 60cb7909e5a73d04c42d36c915a32bb28d684e37.

* fix up comment

* reset serialization_baseline to version on master

* let's try this again: manually update baseline to add type field

* fix search tests by adding correct types to transfomrs

* update metabot tool apis

* fix revision test

* simplify test

* address feedback - move type setting to the model layer

* simplify tests

* Fix up transform serdes tests: remove top-level type fields and updated_at from being serialized, and fix shape of transforms in extraction tests

* set :type after select just in case; fix serdes tests again

* guard against empty source on select

* remove redundant search spec for transforms (introduced via a previous merge)

* switch from type to source_type to avoid conflict with type field on the frontend

* add better error handling
2025-10-29 08:51:20 -04:00
Timofey Kachalov
1bbe525200 Adjust sample-apps runner for the new token check (#65139) 2025-10-29 16:39:55 +04:00
Phoomparin Mano
83b0eb3174 fix(sdk): secondary background color is not mapped to theme (#65116) 2025-10-29 19:14:15 +07:00
Nicolò Pretto
eeb44b4b5a remove .local reference from rspack as .local lookup is slow and we can (#65060)
use .localhost
2025-10-29 12:08:53 +01:00
Nicola Mometto
0e20f5a8b8 respect column definition order for transform create-table (#65089)
* feat: respect column definition order for transform create-table

* add test
2025-10-29 10:10:51 +00:00
Sébastien
92dad88e6a Closes UXW-2112 preserve default colors when renaming breakout values in cartesian charts (#65053)
* Add tests for getSeriesColors with custom titles

* Closes UXW-2112 custom colors breakout labels

* .
2025-10-29 07:16:52 +01:00
Mahatthana (Kelvin) Nomsawadi
94e1c1e387 fix(sdk): Avoid portal root taking space under flex parents (#65088)
* Avoid portal root taking space under flex parents

* Add missing comment

* Preserve format
2025-10-29 02:32:02 +00:00
Nemanja Glumac
6c6b702b29 Enable Trunk Quarantine for general backend tests (#65128) 2025-10-29 02:17:39 +01:00
Aleksandr Lesnenko
38e2e81388 refetch settings after updating remote sync settings (#65124)
* refetch settings after updating remote sync settings

* specs
2025-10-29 01:00:45 +00:00
Nemanja Glumac
5b2fd35367 Enable Trunk Quarantine for drivers (#64995) 2025-10-29 01:24:54 +01:00
Cam Saul
527b8e8e9a Add custom Kondo linter for defendpoint query parameter naming (#65114)
* Add custom Kondo linter for defendpoint query parameter naming

* cljfmt
2025-10-28 17:17:25 -07:00
William
82ea0f4f7e Fix default tag values for temporal template tags (#65112)
This should stop the log spam and fix dependency backfilling
2025-10-28 17:31:41 -05:00
William
39ceced98f Add support for table-functions and selecting tables directly (#65074)
Basically, the same case found two unrelated bugs.  For one, we don't support table functions like `select * from
my_function()`.  For another, `select orders from orders` is also unsupported but apparently legal (at least in
postgres).  This updates sql parsing/validation to support both things.
2025-10-28 17:31:21 -05:00
Ryan Laurie
a67ad3b258 Correct tooltips across map zoom levels (#65080)
* better event handler attachment logic to account for array size change

* test tooltip correctness
2025-10-28 16:31:07 -06:00
Oleksandr Solovyov
bc6694c1a1 no more Workflows team (#64983) 2025-10-29 00:28:39 +02:00
Jeff Bruemmer
c257c954fb docs -remote sync (#65009)
* draft

* notes

* edits

* edits

* updates

* numbering and links

* edits

* edits

* typos
2025-10-28 22:00:23 +00:00
Nemanja Glumac
689d4f0e9b Run e2e tests using staging tokens (#65044)
This pull request updates the configuration and environment handling for E2E and compatibility tests, mainly to support running tests against a staging license/token server and to improve test reliability. The changes affect GitHub Actions workflows, environment variables, and some test and backend logic.

*Backend Logic for E2E Mode*

Added `is-e2e?` flag in core.clj to distinguish E2E test runs from dev/prod/test modes, allowing for custom behavior in E2E scenarios.
Modified token check logic in token_check.clj to allow E2E tests to use a staging server for license validation.
Changed store API settings in settings.clj to use staging endpoints when in dev or E2E mode, ensuring tests interact with the correct backend.
2025-10-28 22:57:14 +01:00
eliotmetabase
c831d2cabf Update error message to make it more obvious things will be deleted (#65117)
* Update error message to make it more obvious things will be deleted

* Better copy

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

* Update button text as well

---------

Co-authored-by: Ryan Laurie <30528226+iethree@users.noreply.github.com>
2025-10-28 14:50:46 -07:00
metamben
bbb0074de4 Fix dependencies backfilling: ignore analysis errors (#65078)
* Fix dependencies backfilling: ignore analysis errors

Fixes QUE-2714

* Catch everything that can fly

* Rename error ignoring macro
2025-10-28 21:12:06 +00:00
Ryan Laurie
d3b69c4c86 DANGEROUSLY allow patches on red commits (#58260)
* DANGEROUSLY allow patches on red commits

* allow override sha

* throw on invalid override

* handle undefined
2025-10-28 13:34:57 -06:00
Cam Saul
ae17be3ee1 Add custom Kondo linter to enforce kebab-case in REST API routes (#65100)
* Add Kondo linter to enforce kebab-case in REST API routes

* Remove Claude guidelines (no longer needed)
2025-10-28 19:01:34 +00:00
Nathan Voxland
4f9dc213ed Fix some indexing race conditions (#64783) 2025-10-28 13:47:15 -05:00
Riley Thompson
280e416af4 exclude databricks from database-schema-filtering-test (#65106) 2025-10-28 18:35:43 +00:00
Alex Yarosh
5db25732ee Update documentation for MB_ATTACHMENT_ROW_LIMIT (#65104) 2025-10-28 18:16:34 +00:00
Oleksandr Yakushev
c51d5b5f79 [malli] Don't include docstrings in mu/defn when compiling CLJS (#63793) 2025-10-28 19:53:35 +02:00
Alexander Polyankin
5b8a087754 Fix search with documents (#65000) 2025-10-28 17:42:09 +00:00
Vamsi Peri
7611b467f3 Remove some instructions from CLAUDE.md (#65103)
Removed instructions and comments regarding emoji usage, spelling conventions, tarot card readings, and formatting for specific users.
2025-10-28 13:29:51 -04:00
Nicolò Pretto
9ac8f80da8 feat(sdk): adds handleLink to customize how links should be open (#64960)
* poc of handleLink

* safer implementation

* make it return a boolean to prevent default

* fix types?

* fix static viz build

* adds tests

* make tests more consistents with fns

* test return value undefined

* Update enterprise/frontend/src/embedding-sdk-shared/lib/sdk-global-plugins.ts

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

* refactor plugin call

* fix types

* removed reduntant test

* change the api to use `{handled: boolean}`

* support links rendered as anchor tags, refactor the logic and tests

* add story

---------

Co-authored-by: metabase-bot[bot] <109303359+metabase-bot[bot]@users.noreply.github.com>
2025-10-28 18:05:28 +01:00
Alexander Polyankin
6ef2472613 Prepare dependencies for v57 (#65093) 2025-10-28 16:25:13 +00:00
Phoomparin Mano
c24bea6939 Make HoverCard dropdown default to bg-primary (#65047)
Co-authored-by: Ryan Laurie <iethree@gmail.com>
2025-10-28 23:19:13 +07:00
Edward Paget
8d09595bb8 Remove the instruction to indent docstrings (#65094)
* Remove the instruction to indent docstrings

* Remove example
2025-10-28 10:57:41 -05:00
Riley Thompson
4a23fc0ee0 Fix add interval honeysql form (#65091)
* add back driver hierarchy

* use driver instead of db-type
2025-10-28 15:28:54 +00:00
Sébastien
e23658dd9a Closes EMB-928 sdk popover flashing at 0,0 (#65086) 2025-10-28 16:17:45 +01:00
Mahatthana (Kelvin) Nomsawadi
afaee50a4c fix(sdk): Fix missing SDK CSS custom properties (#65084)
* Follow core app color order

* Add missing CSS custom properties

* Revert "Follow core app color order"

This reverts commit 01a6a17483.
2025-10-28 14:06:23 +00:00
1048 changed files with 632776 additions and 548499 deletions

View File

@@ -56,20 +56,22 @@
;;
;; globally-enabled custom linters
;;
:metabase/check-defmulti-arglists {:level :warning}
:metabase/check-me-humanize {:level :warning}
:metabase/defsetting-must-specify-export {:level :warning}
:metabase/defsetting-namespace {:level :warning}
:metabase/mbql-query-first-arg {:level :warning}
: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/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/validate-logging {:level :warning}
:metabase/validate-mb-driver-tests {:level :warning}
:metabase/validate-mb-once {:level :warning}
:metabase/discourage-millis-duration {:level :warning}
:metabase/check-defmulti-arglists {:level :warning}
:metabase/check-me-humanize {:level :warning}
:metabase/defsetting-must-specify-export {:level :warning}
:metabase/defsetting-namespace {:level :warning}
:metabase/discourage-millis-duration {:level :warning}
:metabase/mbql-query-first-arg {:level :warning}
: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/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/validate-defendpoint-route-uses-kebab-case {:level :warning}
:metabase/validate-defendpoint-query-params-use-kebab-case {:level :warning}
:metabase/validate-logging {:level :warning}
:metabase/validate-mb-driver-tests {:level :warning}
:metabase/validate-mb-once {:level :warning}
:metabase/validate-deftest
{:level :warning
@@ -551,6 +553,8 @@
metabase.embedding.api.embed-test/with-temp-card hooks.common/let-one-with-optional-value
metabase.embedding.api.embed-test/with-temp-dashcard hooks.common/let-one-with-optional-value
metabase.legacy-mbql.schema.macros/defclause hooks.metabase.legacy-mbql.schemas.macros/defclause
metabase.legacy-mbql.schema.macros/defclause* hooks.metabase.legacy-mbql.schemas.macros/defclause*
metabase.legacy-mbql.schema.macros/one-of hooks.metabase.legacy-mbql.schemas.macros/one-of
metabase.lib.schema.mbql-clause/define-catn-mbql-clause hooks.metabase.lib.schema.mbql-clause/define-mbql-clause
metabase.lib.schema.mbql-clause/define-mbql-clause hooks.metabase.lib.schema.mbql-clause/define-mbql-clause
metabase.lib.schema.mbql-clause/define-tuple-mbql-clause hooks.metabase.lib.schema.mbql-clause/define-mbql-clause
@@ -898,7 +902,9 @@
performance-sensitive
{:linters
{:discouraged-var
{clojure.core/every? {:message "Use metabase.util.performance/every?"}
{clojure.core/empty? {:message "Use metabase.util.performance/empty?"}
clojure.core/not-empty {:message "Use metabase.util.performance/not-empty"}
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/select-keys {:message "Use metabase.util.performance/select-keys"}
@@ -907,7 +913,9 @@
clojure.walk/keywordize-keys {:message "Use metabase.util.performance/keywordize-keys"}
clojure.walk/postwalk {:message "Use metabase.util.performance/postwalk"}
clojure.walk/prewalk {:message "Use metabase.util.performance/prewalk"}
clojure.walk/walk {:message "Use metabase.util.performance/walk"}}}}
clojure.walk/walk {:message "Use metabase.util.performance/walk"}
clojure.walk/for {:message "Use metabase.util.performance/for"}
clojure.walk/doseq {:message "Use metabase.util.performance/doseq"}}}}
qp-and-driver-source-namespaces
{:linters

View File

@@ -46,7 +46,7 @@
;; you need to make
{:metabase/modules
{actions
{:team "Workflows"
{:team "Gadget"
:api #{metabase.actions.api
metabase.actions.args
metabase.actions.core
@@ -249,7 +249,7 @@
;; TODO -- way too many API namespaces.
channel
{:team "Workflows"
{:team "Gadget"
:api #{metabase.channel.api
metabase.channel.core
metabase.channel.email
@@ -557,9 +557,10 @@
util}}
glossary
{:team "Workflows"
{:team "Gadget"
:api #{metabase.glossary.api}
:uses #{api
events
models
util}}
@@ -604,6 +605,7 @@
: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.core
metabase.lib.equality
metabase.lib.field
@@ -740,7 +742,7 @@
util}}
notification
{:team "Workflows"
{:team "Gadget"
:api #{metabase.notification.api
metabase.notification.core
metabase.notification.init
@@ -875,7 +877,7 @@
util}}
pulse
{:team "Workflows"
{:team "Gadget"
:api #{metabase.pulse.api
metabase.pulse.core
metabase.pulse.init}
@@ -1503,12 +1505,13 @@
warehouse-schema}}
enterprise/action-v2
{:team "Workflows"
{:team "Gadget"
:api #{metabase-enterprise.action-v2.api
metabase-enterprise.action-v2.init}
:uses #{actions
api
driver
events
lib
models
query-processor
@@ -1621,7 +1624,9 @@
{:team "UX West"
:api #{metabase-enterprise.billing.api.routes}
:uses #{api
premium-features util}}
premium-features
store-api
util}}
enterprise/bookmarks
{:team "UX West"
@@ -1643,11 +1648,12 @@
:uses #{api
events
premium-features
store-api
util
enterprise/harbormaster}}
enterprise/comments
{:team "Workflows"
{:team "UX West"
:api #{metabase-enterprise.comments.api
metabase-enterprise.comments.init}
:uses #{analytics
@@ -1683,7 +1689,7 @@
:uses :any}
enterprise/dashboard-subscription-filters
{:team "Workflows"
{:team "Querying"
:api #{}
:uses #{premium-features}}
@@ -1731,6 +1737,7 @@
lib-be
models
native-query-snippets
permissions
premium-features
queries
query-processor
@@ -1754,8 +1761,10 @@
events
models
premium-features
public-sharing
queries
query-permissions
query-processor
revisions
search
util
@@ -1887,6 +1896,16 @@
:uses #{premium-features
util}}
enterprise/public-sharing
{:team "UX West"
:api #{metabase-enterprise.public-sharing.api}
:uses #{api
events
premium-features
public-sharing
query-processor
util}}
enterprise/remote-sync
{:team "UX West"
:api #{metabase-enterprise.remote-sync.api
@@ -1900,8 +1919,8 @@
models
premium-features
settings
startup
task
task-history
util
enterprise/serialization}}
@@ -1972,7 +1991,7 @@
enterprise/metabot-v3}}
enterprise/serialization
{:team "Workflows"
{:team "Querying"
:api #{metabase-enterprise.serialization.api
metabase-enterprise.serialization.cmd
metabase-enterprise.serialization.core

View File

@@ -1,7 +1,67 @@
(ns hooks.metabase.api.macros
(:require
[clj-kondo.hooks-api :as api]
[hooks.common]))
[clojure.string :as str]))
(defn- validate-route!
"Make sure the route uses kebab-case rather than snake_case."
[route]
(letfn [(validate-route-string! [route-string]
(when (and (api/string-node? route-string)
(str/includes? (api/sexpr route-string) "_"))
(api/reg-finding! (assoc (meta route-string)
:message "REST API routes and query params should use kebab-case, not snake_case"
:type :metabase/validate-defendpoint-route-uses-kebab-case))))]
(cond
(api/string-node? route)
(validate-route-string! route)
;; otherwise route is a vector like ["/abc/:d/" :d <regex>]
(api/vector-node? route)
(validate-route-string! (first (:children route))))))
(defn- validate-query-params!
"Make sure query params use kebab-case rather than snake_case.
This only works on inline schemas for now. If you define the schema elsewhere then we'd have to implement this
validation in Clojure-land since we can't resolve the schemas in Kondo. It should however still work on complicated
schemas like
[:merge <map-1> <map-2>]"
[query-param-schema-node]
(letfn [(map-schema? [node]
(and (api/vector-node? node)
(when-let [first-child (first (:children node))]
(and (api/keyword-node? first-child)
(= (api/sexpr first-child) :map)))))
(map-schema-keys [{:keys [children], :as _node}]
(let [child-schemas (if (api/map-node? (second children))
(drop 2 children)
(drop 1 children))]
(keep (fn [child-schema]
(when (api/vector-node? child-schema)
(when-let [k (first (:children child-schema))]
(when (api/keyword-node? k)
k))))
child-schemas)))
(validate-map-schema! [form]
;; only warn once per endpoint -- just once on the first bad node
(when-let [bad-node (some (fn [key-node]
(when (str/includes? (str (api/sexpr key-node)) "_")
key-node))
(map-schema-keys form))]
(api/reg-finding! (assoc (meta bad-node)
:message "REST API routes and query params should use kebab-case, not snake_case"
:type :metabase/validate-defendpoint-query-params-use-kebab-case))))
(validate! [node]
(cond
(and (api/vector-node? node)
(map-schema? node))
(validate-map-schema! node)
(api/vector-node? node)
(doseq [child (:children node)]
(validate! child))))]
(validate! query-param-schema-node)))
(defn defendpoint
[arg]
@@ -18,16 +78,21 @@
(cons nil more))
[params & body] more
[bindings schemas] (when (api/vector-node? params)
(loop [bindings [], schemas [], [x y & more] (:children params)]
(loop [bindings [], schemas [], [x y z & more] (:children params)]
(cond
(not x)
[bindings schemas]
(= (api/sexpr x) :-)
(recur bindings (conj schemas y) more)
(and (api/keyword-node? y)
(= (api/sexpr y) :-))
(recur (conj bindings x) (conj schemas z) more)
:else
(recur (conj bindings x) schemas (cons y more)))))]
(recur (conj bindings x) (conj schemas nil) (list* y z more)))))]
(validate-route! route)
(let [[_route-param-schema query-param-schema _body-param-schema] schemas]
(when query-param-schema
(validate-query-params! query-param-schema)))
(-> (api/list-node
(list
(api/token-node 'do)
@@ -54,3 +119,27 @@
body))))
(with-meta (meta node)))))]
(update arg :node update-defendpoint)))
(comment
(defn -defendpoint [form]
(-> {:node (-> form pr-str api/parse-string)}
defendpoint
:node
api/sexpr))
(defn x []
(-defendpoint '(api.macros/defendpoint :get "/:id/syncable_schemas" ; snake_case route should trigger a warning
"Returns a list of all syncable schemas found for the database `id`."
[{:keys [id]} :- [:map
[:id ms/PositiveInt]]
;; snake_case query parameter, should trigger a warning
{:keys [filter_by]} :- [:map
[:filter_by {:optional true} :string]]]
(let [db (get-database id)]
(api/check-403 (or (:is_attached_dwh db)
(and (mi/can-write? db)
(mi/can-read? db))))
(->> db
(driver/syncable-schemas (:engine db))
(vec)
(sort)))))))

View File

@@ -33,18 +33,36 @@
(defclause [ag:var var] field-or-expression FieldOrExpressionDef)
=>
(def ag:var [FieldOrExpressionDef])"
[{:keys [node]}]
(let [[_defclause clause-name-form & arg-specs] (:children node)]
{:node (-> (hooks/list-node
(list
(hooks/token-node 'def)
(unwrap-defclause-clause-name clause-name-form)
(hooks/string-node "Docstring.")
(collect-defclause-body-schemas arg-specs)))
(with-meta (meta node)))}))
[{:keys [node], :as x}]
(let [[_defclause clause-name & arg-specs] (:children node)]
(assoc x :node (-> (hooks/list-node
(list
(hooks/token-node 'do)
(-> (hooks/keyword-node (keyword "metabase.legacy-mbql.schema" (name (hooks/sexpr clause-name))))
(with-meta (meta clause-name))
(hooks/reg-keyword! 'metabase.legacy-mbql.schemas.macros/defclause))
(collect-defclause-body-schemas arg-specs)))
(with-meta (meta node))))))
(defn defclause*
"e.g.
(defclause [ag:var var] field-or-expression FieldOrExpressionDef)
=>
(def ag:var [FieldOrExpressionDef])"
[{:keys [node], :as x}]
(let [[_defclause clause-name schema] (:children node)]
(assoc x :node (-> (hooks/list-node
(list
(hooks/token-node 'do)
(-> (hooks/keyword-node (keyword "metabase.legacy-mbql.schema" (name (hooks/sexpr clause-name))))
(with-meta (meta clause-name))
(hooks/reg-keyword! 'metabase.legacy-mbql.schemas.macros/defclause*))
schema))
(with-meta (meta node))))))
(comment
(defn- defclause* [form]
(defn- expand-defclause [form]
(hooks/sexpr
(:node
(defclause
@@ -55,15 +73,35 @@
form)))}))))
(defn- x []
(defclause* '(defclause [ag:var var]
field-or-expression FieldOrExpressionDef)))
(expand-defclause '(defclause var
field-or-expression FieldOrExpressionDef)))
;; =>
(def ag:var "Docstring." [FieldOrExpressionDef])
(do :metabase.legacy-mbql.schema/var [FieldOrExpressionDef])
(defn- y []
(defclause* '(defclause var
x (some-list-schema)
y (optional FieldOrExpressionDef)
z (rest (some-other-schema)))))
(expand-defclause '(defclause var
x (some-list-schema)
y (optional FieldOrExpressionDef)
z (rest (some-other-schema)))))
;; =>
(def var "Docstring." [(some-list-schema) FieldOrExpressionDef (some-other-schema)]))
(do :metabase.legacy-mbql.schema/var [(some-list-schema) FieldOrExpressionDef (some-other-schema)]))
(defn one-of [{:keys [node], :as x}]
(let [[_one-of & schema-nodes] (:children node)
node' (-> (hooks/vector-node
(mapv (fn [schema-node]
(if (and (hooks/token-node? schema-node)
(simple-symbol? (hooks/sexpr schema-node)))
(-> (hooks/keyword-node (keyword "mteabase.legacy-mbql.schema" (name (hooks/sexpr schema-node))))
(with-meta (meta schema-node)))
schema-node))
schema-nodes))
(with-meta (meta node)))]
(assoc x :node node')))
(comment
(defn- expand-one-of [form]
(hooks/sexpr (:node (one-of {:node (hooks/parse-string (with-out-str (clojure.pprint/pprint form)))}))))
(defn- z []
(expand-one-of '(one-of absolute-datetime relative-datetime time))))

View File

@@ -1,6 +1,7 @@
(ns hooks.metabase.api.macros-test
(:require
[clj-kondo.hooks-api :as api]
[clj-kondo.impl.utils]
[clojure.test :refer :all]
[hooks.metabase.api.macros]))
@@ -69,3 +70,41 @@
(respond :x)
(catch Throwable e
(raise e))))))))
(defn- defendpoint [form]
(hooks.metabase.api.macros/defendpoint
{:node (-> form pr-str api/parse-string)}))
(defn- defendpoint-warnings
[form]
(binding [clj-kondo.impl.utils/*ctx* {:config {:linters {:metabase/validate-defendpoint-route-uses-kebab-case {:level :warning}
:metabase/validate-defendpoint-query-params-use-kebab-case {:level :warning}}}
:ignores (atom nil)
:findings (atom [])
:namespaces (atom {})}]
(defendpoint form)
@(:findings clj-kondo.impl.utils/*ctx*)))
(deftest ^:parallel validate-route-kebab-case-test
(is (=? [{:message "REST API routes and query params should use kebab-case, not snake_case"
:type :metabase/validate-defendpoint-route-uses-kebab-case
:row pos-int?
:col pos-int?}]
(defendpoint-warnings
'(api.macros/defendpoint :get "/:id/syncable_schemas" ; snake_case route should trigger a warning
"Returns a list of all syncable schemas found for the database `id`."
[{:keys [id]}]
id)))))
(deftest ^:parallel validate-query-params-kebab-case-test
(is (=? [{:message "REST API routes and query params should use kebab-case, not snake_case",
:type :metabase/validate-defendpoint-query-params-use-kebab-case
:row pos-int?
:col pos-int?}]
(defendpoint-warnings
'(api.macros/defendpoint :get "/:id/syncable-schemas"
"Returns a list of all syncable schemas found for the database `id`."
[{:keys [id]}
{:keys [filter_by]} :- [:map
[:filter_by {:optional true} :string]]]
id)))))

View File

@@ -2,3 +2,4 @@ frontend/src/cljs
frontend/src/cljs_release
e2e/support/cypress_sample_database.js
e2e/support/cypress_sample_instance_data.js
e2e/embedding-sdk-host-apps

View File

@@ -10,6 +10,9 @@ outputs:
node-cache-key:
description: "The cache key for the Node.js cache."
value: ${{ steps.keys-factory.outputs.node-cache-key }}
eslint-cache-key:
description: "The cache key for Eslint cache"
value: ${{ steps.keys-factory.outputs.eslint-cache-key }}
runs:
using: "composite"
@@ -19,9 +22,11 @@ runs:
run: |
M2_CACHE_PREFIX='M2'
NODE_CACHE_PREFIX='node-modules'
ESLINT_CACHE_PREFIX='eslint'
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
shell: bash

View File

@@ -27,9 +27,18 @@ runs:
- name: Test database driver
run: clojure -X:dev:ci:ee:ee-dev:drivers:drivers-dev:test ${{ inputs.test-args }}
shell: bash
id: run-test
# Trunk Quarantine controls the final state of the run in the CI!
# Even if this step fails, we let it pass and then `trunk-io/analytics-uploader` determines whether to fail or to
# pass the whole job, based on the quarantine list.
# We only want to "continue on error" (ignore failures) when the Trunk upload is active - i.e. not on drafts!
continue-on-error: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.draft == true) }}
- name: Publish Test Report (JUnit)
uses: dorny/test-reporter@v1
if: failure()
# 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'
with:
path: "target/junit/**/*_test.xml"
name: JUnit Test Report ${{ inputs.junit-name }}
@@ -38,9 +47,11 @@ runs:
list-tests: failed
fail-on-error: false
- name: Upload Logs on Failure
if: always() && !success()
if: always() && steps.run-test.outcome != 'success'
uses: actions/upload-artifact@v4
with:
name: test-logs-${{ github.job }}
path: logs/test-log.json
retention-days: 1
# Failing to upload the artifact should never affect the outcome of the whole test run.
continue-on-error: true

View File

@@ -1,3 +1,5 @@
version: 1
name: "Metabase CodeQL config"
paths-ignore:

View File

@@ -127,10 +127,6 @@ e2e_ci: &e2e_ci
e2e_specs: &e2e_specs
- e2e/!(test-host-app)**/*.cy.*.{js,ts}
e2e_cross_version: &e2e_cross_version
- ".github/workflows/e2e-cross-version.yml"
- "e2e/test/scenarios/cross-version/**"
e2e_embedding_sdk:
- *frontend_embedding_sdk_ci
- *sources
@@ -170,6 +166,7 @@ yaml:
- "**/*.yaml"
codeql:
- ".github/workflows/codeql.yml"
- "frontend/src/**"
- "enterprise/frontend/src/**"

13
.github/team.json vendored
View File

@@ -32,15 +32,6 @@
"lorem--ipsum"
]
},
{
"name": "Workflows",
"label": ".Team/Workflows",
"members": [
"piranha",
"crisptrutski",
"spalt08"
]
},
{
"name": "Admin Webapp",
"label": ".Team/AdminWebapp",
@@ -69,7 +60,9 @@
"sloansparger",
"somtom",
"tsplude",
"lbrdnk"
"lbrdnk",
"piranha",
"crisptrutski"
]
},
{

View File

@@ -10,19 +10,202 @@ jobs:
# don't run this workflow on a cron for forks
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
runs-on: ubuntu-22.04
timeout-minutes: 90
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
modules:
- actions
- activity-feed
- analytics
- analyze
- api
- api-keys
- api-routes
- app-db
- appearance
- audit-app
- auth-provider
- batch-processing
- bookmarks
- bug-reporting
- cache
- channel
- classloader
- cloud-migration
- cmd
- collections
- config
- connection-pool
- content-translation
- content-verification
- core
- dashboards
- database-routing
- driver
- driver-api
- eid-translation
- embedding
- events
- formatter
- geojson
- glossary
- graph
- indexed-entities
- internal-stats
- legacy-mbql
- lib
- lib-be
- logger
- login-history
- model-persistence
- models
- native-query-snippets
- notification
- parameters
- permissions
- pivot
- plugins
- premium-features
- product-feedback
- public-sharing
- pulse
- queries
- query-permissions
- query-processor
- remote-sync
- request
- revisions
- sample-data
- search
- secrets
- segments
- server
- session
- settings
- setup
- sso
- startup
- store-api
- sync
- system
- task
- task-history
- testing-api
- tiles
- timeline
- types
- upload
- user-key-value
- users
- util
- version
- view-log
- warehouse-schema
- warehouses
- xrays
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: Collect the test coverage
run: clojure -X:dev:ci:ee:ee-dev:test:cloverage
run: |
clojure -X:dev:ci:ee:ee-dev:test:cloverage \
:ns-regex '["^metabase\\.${{ matrix.modules }}\\..*"]' \
:test-ns-path '["test/metabase/${{ matrix.modules }}"]'
continue-on-error: true
- name: Upload coverage to codecov.io
uses: codecov/codecov-action@v4
if: always()
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./target/coverage/codecov.json
flags: back-end
be-linter-cloverage-enterprise:
# don't run this workflow on a cron for forks
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
runs-on: ubuntu-22.04
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
modules:
- action-v2
- advanced-config
- advanced-permissions
- ai-entity-analysis
- ai-sql-fixer
- ai-sql-generation
- analytics
- api
- audit-app
- auth-provider
- billing
- bookmarks
- cache
- cloud-add-ons
- comments
- content-translation
- content-verification
- core
- dashboard-subscription-filters
- database-replication
- database-routing
- dependencies
- documents
- email
- embedding-hub
- gsheets
- harbormaster
- impersonation
- internal-stats
- llm
- metabot-v3
- permission-debug
- premium-features
- public-sharing
- remote-sync
- sandbox
- scim
- search
- semantic-search
- serialization
- snippet-collections
- sso
- stale
- transforms
- transforms-python
- upload-management
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: Collect the test coverage
run: |
clojure -X:dev:ci:ee:ee-dev:test:cloverage \
:ns-regex '["^metabase-enterprise\\.${{ matrix.modules }}\\..*"]' \
:test-ns-path '["enterprise/backend/test/metabase/${{ matrix.modules }}"]'
continue-on-error: true
- name: Upload coverage to codecov.io
if: always()
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./target/coverage/codecov.json

View File

@@ -129,6 +129,11 @@ jobs:
clojure -X:dev:ci:test:${{ matrix.job.edition }}:${{ matrix.job.edition }}-dev
:exclude-tags '[:mb/driver-tests ${{ env.__ADDITIONAL_EXCLUDED_TAG__ }}]'
${{ matrix.job.test-args }}
# Trunk Quarantine controls the final state of the run in the CI!
# Even if this step fails, we let it pass and then `trunk-io/analytics-uploader` determines whether to fail or to
# pass the whole job, based on the quarantine list.
# We only want to "continue on error" (ignore failures) when the Trunk upload is active - i.e. not on drafts!
continue-on-error: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.draft == true) }}
- name: Upload Test Results
uses: ./.github/actions/upload-test-results

View File

@@ -48,6 +48,7 @@ jobs:
outputs:
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 }}
generate-m2-cache:
runs-on: ubuntu-22.04
@@ -73,12 +74,13 @@ jobs:
~/.gitlibs
key: ${{ env.M2_CACHE_KEY }}
generate-node-modules-cache:
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
# `prepare-frontend` action (1) prepares Node.js and (2) fetches the node_modules cache if it exists.
@@ -97,3 +99,9 @@ jobs:
with:
path: node_modules
key: ${{ env.NODE_CACHE_KEY }}
- name: Update eslint cache
uses: ./.github/actions/update-cache
with:
path: .eslintcache
key: ${{ env.ESLINT_CACHE_KEY }}

View File

@@ -2,6 +2,10 @@ name: "Claude Code Review"
on:
pull_request:
types:
- closed
- synchronize
- labeled
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}-claude-code-review
@@ -9,7 +13,12 @@ concurrency:
jobs:
review:
if: github.event.pull_request.draft == false
if: |
(
github.event.action == 'closed' &&
github.event.pull_request.merged == true
) ||
contains(github.event.pull_request.labels.*.name, 'Claude Code Review')
runs-on: ubuntu-latest
permissions:
contents: read

View File

@@ -30,9 +30,10 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v4
with:
languages: javascript
config-file: ./.github/codeql/codeql-config.yml
trap-caching: false
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v4

View File

@@ -390,10 +390,6 @@ jobs:
name: H2
steps:
- uses: actions/checkout@v4
- name: Setup python-runner
uses: ./.github/actions/setup-python-runner
with:
metabase-automation-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
- name: Test H2 driver
id: test-driver
uses: ./.github/actions/test-driver
@@ -413,12 +409,6 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
- name: Cleanup python-runner
if: always()
uses: ./.github/actions/cleanup-python-runner
with:
upload-logs: ${{ steps.test-driver.outcome == 'failure' }}
logs-artifact-suffix: ${{ matrix.job.name }} ${{ matrix.version.name }}
be-tests-mysql-mariadb:
if: ${{ !inputs.skip }}

View File

@@ -1,4 +1,4 @@
# Thi workflow does the backward compatibility tests
# 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
@@ -93,13 +93,14 @@ jobs:
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.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
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

View File

@@ -108,13 +108,14 @@ jobs:
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.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
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_IS_EMBEDDING_SDK: "true"
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

View File

@@ -1,171 +0,0 @@
name: E2E Cross-version Tests
on:
schedule:
- cron: '0 9 * * 1-5'
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
jobs:
files-changed:
name: Check which files changed
# don't run this workflow on a cron for forks
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
runs-on: ubuntu-22.04
timeout-minutes: 3
outputs:
e2e_cross_version: ${{ steps.changes.outputs.e2e_cross_version }}
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
cross-version-testing:
needs: files-changed
if: ${{ needs.files-changed.outputs.e2e_cross_version == 'true' || github.event_name == 'schedule'}}
runs-on: ubuntu-22.04
timeout-minutes: 20
strategy:
matrix:
version: [
# Major OSS upgrade
{ source: v0.42.2, target: v0.48.7 },
# OSS upgrade
{ source: v0.41.3.1, target: v0.42.2 },
# EE upgrade
{ source: v1.43.4, target: v1.44.0 },
# EE downgrade
{ source: v1.42.0, target: v1.41.3.1 },
# Cross-edition upgrade
{ source: v0.41.3.1, target: v1.42.2 }
]
fail-fast: false
env:
CROSS_VERSION_SOURCE: ${{ matrix.version.source }}
CROSS_VERSION_TARGET: ${{ matrix.version.target }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set source Docker image to OSS
run: |
echo "DOCKER_SOURCE_IMAGE=metabase/metabase:${{ matrix.version.source }}" >> $GITHUB_ENV
if: startsWith(matrix.version.source, 'v0')
- name: Set source Docker image to EE
run: |
echo "DOCKER_SOURCE_IMAGE=metabase/metabase-enterprise:${{ matrix.version.source }}" >> $GITHUB_ENV
if: startsWith(matrix.version.source, 'v1')
- name: Prepare front-end environment
uses: ./.github/actions/prepare-frontend
- name: Start Metabase ${{ matrix.version.source }}
run: |
docker run -d \
-v $PWD/my-metabase:/metabase.db \
-p 3000:3000 \
-e CYPRESS_MB_ALL_FEATURES_TOKEN=${{ secrets.MB_ALL_FEATURES_TOKEN }} \
-e CYPRESS_MB_STARTER_CLOUD_TOKEN=${{ secrets.MB_STARTER_CLOUD_TOKEN }} \
-e CYPRESS_MB_PRO_CLOUD_TOKEN=${{ secrets.MB_PRO_CLOUD_TOKEN }} \
-e CYPRESS_MB_PRO_SELF_HOSTED_TOKEN=${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }} \
--name metabase-${{ matrix.version.source }} \
${{ env.DOCKER_SOURCE_IMAGE }}
- name: Wait for Metabase to start on port 3000
run: while ! curl -s 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
- name: Prepare Cypress environment
id: cypress-prep
uses: ./.github/actions/prepare-cypress
- name: Run Cypress on the source
run: |
yarn cypress run \
--browser ${{ steps.cypress-prep.outputs.chrome-path }} \
--config-file e2e/test/scenarios/cross-version/source/shared/cross-version-source.config.js \
--spec e2e/test/scenarios/cross-version/source/**/*.cy.spec.js
- name: Stop Metabase ${{ matrix.version.source }}
run: docker stop metabase-${{ matrix.version.source }}
- name: Set target Docker image to OSS
run: |
echo "DOCKER_TARGET_IMAGE=metabase/metabase:${{ matrix.version.source }}" >> $GITHUB_ENV
if: startsWith(matrix.version.source, 'v0')
- name: Set target Docker image to EE
run: |
echo "DOCKER_TARGET_IMAGE=metabase/metabase-enterprise:${{ matrix.version.source }}" >> $GITHUB_ENV
if: startsWith(matrix.version.source, 'v1')
- name: Start Metabase ${{ matrix.version.target }}
run: |
docker run -d \
-v $PWD/my-metabase:/metabase.db \
-p 3001:3000 \
-e CYPRESS_MB_ALL_FEATURES_TOKEN=${{ secrets.MB_ALL_FEATURES_TOKEN }} \
-e CYPRESS_MB_STARTER_CLOUD_TOKEN=${{ secrets.MB_STARTER_CLOUD_TOKEN }} \
-e CYPRESS_MB_PRO_CLOUD_TOKEN=${{ secrets.MB_PRO_CLOUD_TOKEN }} \
-e CYPRESS_MB_PRO_SELF_HOSTED_TOKEN=${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }} \
--name metabase-${{ matrix.version.target }} \
${{ env.DOCKER_TARGET_IMAGE }}
- name: Wait for Metabase to start on port 3001
run: while ! curl -s 'http://localhost:3001/api/health' | grep '{"status":"ok"}'; do sleep 1; done
- name: Run Cypress on the target
run: |
yarn cypress run \
--browser ${{ steps.cypress-prep.outputs.chrome-path }} \
--config-file e2e/test/scenarios/cross-version/target/shared/cross-version-target.config.js \
--spec e2e/test/scenarios/cross-version/target/**/*.cy.spec.js
- name: Upload Cypress Artifacts upon failure
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-artifacts-${{ matrix.version.source}}-to-${{ matrix.version.target }}
path: |
./cypress
if-no-files-found: ignore
notify-on-failure:
needs: cross-version-testing
if: ${{ always() && contains(needs.*.result, 'failure') && github.event_name == 'schedule' }}
name: Cross-version test failure
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/setup-node@v4
with:
node-version: lts/Jod # 22.x.x
- run: npm install @slack/web-api
- name: notify slack of failure
uses: actions/github-script@v7
with:
script: | # js
const FAILED_RUN_URL = "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}";
const REF_NAME = "${{ github.ref_name }}";
// notify slack of failure
const { WebClient } = require('@slack/web-api');
const slack = new WebClient('${{ secrets.SLACK_BOT_TOKEN }}');
await slack.chat.postMessage({
channel: 'engineering-ci',
text: 'Cross-version Tests Have Failed',
blocks: [
{
"type": "header",
"text": {
"type": "plain_text",
"text": `:broken_heart: Cross-version tests are failing on ${REF_NAME}`,
"emoji": true,
}
},
],
attachments: [{
color: "#BF40BF",
blocks: [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": `See <${FAILED_RUN_URL}|failing run details>.`
}
},
]
}]
});

View File

@@ -213,7 +213,9 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
MB_RUN_MODE: e2e
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
CYPRESS_IS_EMBEDDING_SDK: "true"
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true
@@ -343,7 +345,9 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
MB_RUN_MODE: e2e
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }}
CYPRESS_IS_EMBEDDING_SDK: "true"
TZ: US/Pacific # to make node match the instance tz
CYPRESS_CI: true

View File

@@ -37,8 +37,26 @@ on:
default: true
jobs:
determine-suite:
name: Determine test suite
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
suite: ${{ steps.detect.outputs.suite }}
steps:
- name: Detect suite from spec path
id: detect
run: |
SPEC='${{ inputs.spec }}'
if [[ "$SPEC" == e2e/test-component/scenarios/embedding-sdk/* ]]; then
echo "suite=component" >> $GITHUB_OUTPUT
else
echo "suite=e2e" >> $GITHUB_OUTPUT
fi
workflow-summary:
name: Stress test inputs
needs: [determine-suite]
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
@@ -48,6 +66,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 '- `burn_in`: ${{ inputs.burn_in }}' >> $GITHUB_STEP_SUMMARY
echo '- `grep`: "${{ inputs.grep }}"' >> $GITHUB_STEP_SUMMARY
echo '- `qa_db`: "${{ inputs.qa_db }}"' >> $GITHUB_STEP_SUMMARY
@@ -56,6 +75,7 @@ jobs:
echo 'triggered by: @${{ github.event.sender.login }}' >> $GITHUB_STEP_SUMMARY
stress-test-flake-fix:
needs: [determine-suite]
runs-on: ubuntu-22.04
timeout-minutes: 60
name: Stress test E2E flake fix
@@ -63,10 +83,12 @@ jobs:
DISPLAY: ""
QA_DB_ENABLED: ${{ contains(fromJSON('["sql", "mongo"]'), inputs.qa_db) }}
CYPRESS_QA_DB_MONGO: ${{ inputs.qa_db == 'mongo' }}
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
MB_RUN_MODE: e2e
METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }}
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 }}
@@ -98,6 +120,16 @@ 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' }}
run: yarn build-embedding-sdk-package
- name: Prepare JDK 21
uses: actions/setup-java@v4
with:
@@ -116,8 +148,9 @@ jobs:
- name: Stress-test ${{ github.event.inputs.spec }} ${{ github.event.inputs.burn_in }} times
env:
GREP: ${{ github.event.inputs.grep }}
CYPRESS_IS_EMBEDDING_SDK: ${{ needs.determine-suite.outputs.suite == 'component' }}
run: |
node e2e/runner/run_cypress_ci.js e2e \
node e2e/runner/run_cypress_ci.js ${{ needs.determine-suite.outputs.suite }} \
--spec '${{ github.event.inputs.spec }}' \
--env burn=${{ github.event.inputs.burn_in }} \
--config-file e2e/support/cypress-stress-test.config.js \

View File

@@ -42,12 +42,14 @@ jobs:
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.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
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

View File

@@ -35,13 +35,16 @@ jobs:
uses: ./.github/actions/prepare-frontend
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Get Eslint cache key
uses: ./.github/actions/get-cache-keys
id: get-cache-keys
- name: Restore ESLint cache
uses: actions/cache@v4
uses: actions/cache/restore@v4
with:
path: .eslintcache
key: eslintcache-${{ hashFiles('yarn.lock', '.eslintrc.js') }}
restore-keys: |
eslintcache-
key: ${{ steps.get-cache-keys.outputs.eslint-cache-key }}
- name: Compile CLJS
run: yarn build-pure:cljs
- name: Find CSS variables that are used but never defined

View File

@@ -24,6 +24,39 @@ on:
required: true
jobs:
test-mode-config:
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
run_mode: ${{ fromJson(steps.config.outputs.result).runMode }}
dev_server: ${{ fromJson(steps.config.outputs.result).metastoreDevServer }}
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: release
- name: Prepare build scripts
run: cd ${{ github.workspace }}/release && yarn && yarn build
# note: this block can be removed after we stop needing to be able to test versions before v55
- name: Get test mode config
id: config
uses: actions/github-script@v7
with:
script: | # js
const { getMajorVersion } = require('${{ github.workspace }}/release/dist/index.cjs');
// Versions before v55 used a single token for testing
// with v55 and later we use enterprise tokens that mirror actual Metabase plans
const MULTIPLE_TEST_TOKEN_THRESHOLD = 55;
const version = '${{ inputs.version }}';
const majorVersion = Number(getMajorVersion(version));
const oldTestToken = majorVersion < MULTIPLE_TEST_TOKEN_THRESHOLD;
return ({
runMode: oldTestToken ? 'prod' : 'e2e',
metastoreDevServer: oldTestToken ? '' : '${{ vars.METASTORE_DEV_SERVER_URL }}'
});
release-artifact:
runs-on: ubuntu-22.04
timeout-minutes: 10
@@ -96,17 +129,19 @@ jobs:
run-sanity-check:
runs-on: ubuntu-22.04
timeout-minutes: 30
needs: [release-artifact]
needs: [test-mode-config, release-artifact]
strategy:
matrix:
edition: [oss, ee]
env:
MB_EDITION: ${{ matrix.edition }}
DISPLAY: ""
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
MB_RUN_MODE: ${{ needs.test-mode-config.outputs.run_mode }}
METASTORE_DEV_SERVER_URL: ${{ needs.test-mode-config.outputs.dev_server }}
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 }}
# these are needed for backwards compatibility with release branches earlier than v55, since
# this workflow always runs from master, but we run tests from the release branch
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}

View File

@@ -47,7 +47,7 @@ jobs:
with:
script: | # js
const {
getVersionFromReleaseBranch,
getMajorVersionFromRef,
getMajorVersion,
} = require('${{ github.workspace }}/release/dist/index.cjs');
@@ -60,14 +60,15 @@ jobs:
}
// otherwise, get the version from the release branch name
const branch = context.payload.ref;
const version = getVersionFromReleaseBranch(branch);
const majorVersion = getMajorVersion(version);
const ref = context.payload.ref;
const majorVersion = getMajorVersionFromRef(ref);
console.log({ branch, version, majorVersion });
console.log({ ref, majorVersion });
core.exportVariable('VERSION', majorVersion);
- name: generate release Log
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cd release && tsx ./src/release-log-run.ts $VERSION > v$VERSION.html
- name: generate release channel log
run: cd release && tsx ./src/release-channel-log.ts > channels.html

View File

@@ -8,6 +8,11 @@ on:
description: 'Major Metabase version (e.g. 45, 52, 68)'
type: number
required: true
override_sha:
description: DANGEROUSLY allow releasing from this commit sha, regardless of the state of CI (can be empty)
type: string
required: false
default: ''
schedule:
- cron: '0 21 * * 1-5' # every weekday at 4 pm EST/5 pm EDT
@@ -37,7 +42,7 @@ jobs:
const lastRelease = currentRelease - 1;
const AUTO_RELEASE_VERSIONS = [lastRelease, currentRelease];
async function releasePatchFor(majorVersion) {
async function releasePatchFor(majorVersion, overrideSha) {
const nextPatch = await getNextPatchVersion({
github,
owner: context.repo.owner,
@@ -45,7 +50,7 @@ jobs:
majorVersion,
});
const goodCommit = await getLatestGreenCommit({
const releaseCommit = overrideSha || await getLatestGreenCommit({
github,
owner: context.repo.owner,
repo: context.repo.repo,
@@ -56,25 +61,25 @@ jobs:
github,
owner: context.repo.owner,
repo: context.repo.repo,
ref: goodCommit,
ref: releaseCommit,
majorVersion: Number(majorVersion),
});
if (nextPatch && goodCommit && !hasBeenReleased) {
if (nextPatch && releaseCommit && !hasBeenReleased) {
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'tag-for-release.yml',
ref: 'refs/heads/master',
inputs: {
commit: goodCommit,
commit: releaseCommit,
version: nextPatch,
auto: true,
}
});
} else {
console.log(
{ nextPatch, goodCommit, hasBeenReleased }
{ nextPatch, releaseCommit, hasBeenReleased }
);
console.error(`No new patch version or no green commit found for v${majorVersion}`);
}
@@ -88,7 +93,15 @@ jobs:
throw new Error(`Invalid version number: ${inputVersion}`);
}
await releasePatchFor(inputVersion);
// only allow overriding the commit SHA for workflow_dispatch events with a provided sha
const overrideSha = String(context.payload?.inputs?.override_sha ?? '').trim();
const isValidOverride = overrideSha.length === 40;
if (!isValidOverride && overrideSha.length > 0) {
throw new Error(`Invalid override SHA provided: ${overrideSha}`);
}
await releasePatchFor(inputVersion, isValidOverride ? overrideSha : undefined);
} else { // scheduled release of AUTO_RELEASE_VERSIONS
await Promise.all(AUTO_RELEASE_VERSIONS.map(releasePatchFor));
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

@@ -165,10 +165,8 @@ Review pull requests with a focus on:
## More Instructions
- Use **tons** of emojis in every comment you write -- the more, the better! 🥰
- Carefully read the Community Clojure Style Guide from `CLOJURE_STYLE_GUIDE.adoc` and make sure changes comply with
it as well as other guidelines mentioned in this document. Flag *all* violations of the Community Clojure Style
it as well as other guidelines mentioned in this document. Flag _all_ violations of the Community Clojure Style
Guide.
- Do not post comments congratulating someone for trivial changes, or for following the style guidelines, or
@@ -186,17 +184,6 @@ Review pull requests with a focus on:
> Test name properly ends with -test as required by the style guide.
- In the Metabase codebase, spelling words ending with `-ck` as `-cc` instead, e.g. `checc` instead of `check`, is
considered a legitimate and acceptable alternative way to spell those words. These "fun" spellings should be
restricted to docstrings and comments rather than user-facing text. Do not flag these as typos or misspellings.
- Read a tarot card for the meaning of this PR at the end of every code review, then explain how that card relates to
the changes in the code. **Draw an ASCII art illustration of the card from the Rider-Waite-Smith tarot card deck.
(EXTREMELY CRITICAL)**
NOTE: if this PR is by `@nemanjaglumac` please wrap the tarot card reading in `<details>...</details>` so he doesn't
have to see it.
- Do not post comments about missing parentheses.
# Code Conventions and Style Guide
@@ -313,12 +300,12 @@ Review pull requests with a focus on:
- Don't mark things `^:const` unless you have a really good reason for doing so. Add a comment explaining why you
marked it `^:const`.
- Every public var in `src` or `enterprise/backend/src` must have a *useful* docstring. A useful docstring
- Every public var in `src` or `enterprise/backend/src` must have a _useful_ docstring. A useful docstring
should clearly explain the purpose of the function, its inputs and outputs, and anything else that is otherwise not
immediately clear. If there are other functions that have similar purposes, explain how the use-cases for this
function differ.
Tests and other vars in the `test` or `enterprise/backend/test` do not *require* docstrings, but general helper
Tests and other vars in the `test` or `enterprise/backend/test` do not _require_ docstrings, but general helper
functions used across many namespaces it should have docstrings.
Schemas defined with `mr/def` e.g. `(mr/def ::my-schema)` do not require docstrings.
@@ -335,24 +322,6 @@ Review pull requests with a focus on:
- Make sure to update comments and docstrings when you change the code they describe.
- Docstrings should be indented two spaces.
```clj
;;; BAD
(defn update-transform-tags!
"Update the tags associated with a transform using smart diff logic.
Only modifies what has changed: deletes removed tags, updates positions for moved tags,
and inserts new tags. Duplicate tag IDs are automatically deduplicated."
...)
;;; GOOD
(defn update-transform-tags!
"Update the tags associated with a transform using smart diff logic.
Only modifies what has changed: deletes removed tags, updates positions for moved tags,
and inserts new tags. Duplicate tag IDs are automatically deduplicated."
...)
```
- `TODO` comments should include the author and date, for example
```clj
@@ -560,19 +529,8 @@ Review pull requests with a focus on:
...)
```
- REST API route strings (the second arg to `defendpoint`) should use `kebab-case`, e.g. `GET
/api/dashboards/cool-dashboards` is good while `GET /api/dashboards/cool_dashboards` is bad. More examples:
```clj
;;; Bad
(api.macros/defendpoint :post "/check_transform" ...)
;;; Good
(api.macros/defendpoint :post "/check-transform" ...)
```
- Query parameters should also use kebab-case e.g. `GET /api/dashboards?include-archived=true` is good while `GET
/api/dashboards?include_archived=true` or `GET /api/dashboards?includeArchived=true` is bad.
/api/dashboards?include_archived=true` or `GET /api/dashboards?includeArchived=true` is bad.
- HTTP request bodies should use `snake_case`.
@@ -586,7 +544,7 @@ Review pull requests with a focus on:
- `defendpoint` forms should be small wrappers around Toucan model code. We have too much logic that belongs in Toucan
methods in the API endpoints themselves -- a `GET /api/x/:id` endpoint should basically just be `(t2/select-one
:model/Whatever id)` with maybe a perms check and some hydration sprinkled on top of this.
:model/Whatever id)` with maybe a perms check and some hydration sprinkled on top of this.
- All API endpoints should have Malli schemas for any parameters that aren't ignored. `_route-params` doesn't need a
schema, but `{:keys [x]}` should have one.

3
bb.edn
View File

@@ -2,7 +2,8 @@
;; we put path as bin, and everything is in the ./mage subdirectory,
;; so the namespaces are mage.cli, mage.format, etc.
:paths ["mage/src" "mage/test" "bin/lint-migrations-file/src"]
:deps {org.babashka/json {:mvn/version "0.1.6"}
:deps {dev.weavejester/cljfmt {:mvn/version "0.15.3"}
org.babashka/json {:mvn/version "0.1.6"}
metosin/malli {:mvn/version "0.17.0"}
table/table {:mvn/version "0.5.0"}
mvxcvi/puget {:mvn/version "1.3.4"}}

View File

@@ -56,7 +56,7 @@
com.google.guava/guava {:mvn/version "33.4.8-jre"} ; dep for BigQuery, Spark, and GA. Require here rather than letting different dep versions stomp on each other — see comments on #9697
com.h2database/h2 ^:antq/exclude ; https://metaboat.slack.com/archives/CKZEMT1MJ/p1727191010259979
{:mvn/version "2.1.214"} ; embedded SQL database
com.ibm.icu/icu4j {:mvn/version "77.1"} ; Used to transliterate Unicode characters into Latin characters
com.ibm.icu/icu4j {:mvn/version "78.1"} ; Used to transliterate Unicode characters into Latin characters
com.knuddels/jtokkit {:mvn/version "1.1.0"} ; Java tokenizer library for OpenAI models, used for token counting in semantic search
com.mchange/c3p0 {:mvn/version "0.11.2"} ; DB connection pool
com.snowplowanalytics/snowplow-java-tracker ^:antq/exclude ; 2+ depend on apache httpclient 5.x, but saml and clj-http depend on 4.x
@@ -78,7 +78,7 @@
:exclusions [ring/ring-codec]}
crypto-random/crypto-random {:mvn/version "1.2.1"} ; library for generating cryptographically secure random bytes and strings
diehard/diehard {:mvn/version "0.12.0"}
dk.ative/docjure {:mvn/version "1.21.0" ; excel export
dk.ative/docjure {:mvn/version "1.22.0" ; excel export
:exclusions [org.apache.poi/poi
org.apache.poi/poi-ooxml]}
environ/environ {:mvn/version "1.2.0"} ; env vars/Java properties abstraction
@@ -90,7 +90,7 @@
:git/sha "4998a1fdd9d3713d7034d04509e9212204773bf2"
:git/url "https://github.com/eerohele/pp"}
;; TODO: replace back to normal artifact
io.github.metabase/macaw {:mvn/version "0.2.28"} ; Parse native SQL queries
io.github.metabase/macaw {:mvn/version "0.2.29"} ; Parse native SQL queries
io.github.resilience4j/resilience4j-retry ^:antq/exclude ; 2.x do not support Java 8
{:mvn/version "1.7.1"} ; Support for retrying operations
io.prometheus/simpleclient_hotspot {:mvn/version "0.16.0"} ; prometheus jvm collector
@@ -135,7 +135,7 @@
:exclusions [org.bouncycastle/bcpkix-jdk15on
org.bouncycastle/bcprov-jdk15on]}
org.apache.poi/poi-ooxml-full {:mvn/version "5.4.1"}
org.apache.sshd/sshd-core {:mvn/version "2.16.0" ; ssh tunneling and test server
org.apache.sshd/sshd-core {:mvn/version "3.0.0-M2" ; ssh tunneling and test server
:exclusions [org.slf4j/slf4j-api
org.slf4j/jcl-over-slf4j]}
org.apache.tika/tika-core {:mvn/version "3.2.2"}
@@ -147,7 +147,7 @@
org.clj-commons/hickory {:mvn/version "0.7.7" ; Parse HTML into Clojure data structures
:exclusions [org.jsoup/jsoup]}
org.clojars.pntblnk/clj-ldap {:mvn/version "0.0.17"} ; LDAP client
org.clojure/clojure {:mvn/version "1.12.2"}
org.clojure/clojure {:mvn/version "1.12.3"}
org.clojure/core.async {:mvn/version "1.7.701"
:exclusions [org.clojure/tools.reader]}
org.clojure/core.logic {:mvn/version "1.1.0"} ; optimized pattern matching library for Clojure
@@ -166,14 +166,14 @@
org.clojure/tools.namespace {:mvn/version "1.5.0"}
org.clojure/tools.reader {:mvn/version "1.5.2"}
org.clojure/tools.trace {:mvn/version "0.8.0"} ; function tracing
org.eclipse.jetty/jetty-server {:mvn/version "12.0.24"}
org.eclipse.jetty/jetty-unixdomain-server {:mvn/version "12.0.25"}
org.eclipse.jetty.ee9/jetty-ee9-servlet {:mvn/version "12.0.24"}
org.eclipse.jetty.ee9.websocket/jetty-ee9-websocket-jetty-server {:mvn/version "12.0.25"}
org.eclipse.jetty/jetty-server {:mvn/version "12.1.3"}
org.eclipse.jetty/jetty-unixdomain-server {:mvn/version "12.1.3"}
org.eclipse.jetty.ee9/jetty-ee9-servlet {:mvn/version "12.1.3"}
org.eclipse.jetty.ee9.websocket/jetty-ee9-websocket-jetty-server {:mvn/version "12.1.3"}
org.eclipse.jgit/org.eclipse.jgit {:mvn/version "7.3.0.202506031305-r"}; Java implementation of Git version control system
org.flatland/ordered {:mvn/version "1.15.12"} ; ordered maps & sets
org.graalvm.polyglot/js-community {:mvn/version "24.2.2" :extension "pom"} ; JavaScript engine
org.graalvm.polyglot/polyglot {:mvn/version "24.2.2"} ; GraalVM platform, required by JS engine
org.graalvm.polyglot/js-community {:mvn/version "25.0.1" :extension "pom"} ; JavaScript engine
org.graalvm.polyglot/polyglot {:mvn/version "25.0.1"} ; GraalVM platform, required by JS engine
org.jsoup/jsoup {:mvn/version "1.21.1"} ; required by hickory
org.liquibase/liquibase-core {:mvn/version "4.33.0" ; migration management (Java lib)
:exclusions [ch.qos.logback/logback-classic]}
@@ -199,8 +199,8 @@
org.eclipse.jetty.ee9/jetty-ee9-servlet
org.eclipse.jetty.ee9.websocket/jetty-ee9-websocket-jetty-server]}
slingshot/slingshot {:mvn/version "0.12.2"} ; enhanced throw/catch, used by other deps
software.amazon.awssdk/s3 {:mvn/version "2.33.0"} ; AWS SDK v2 for S3
software.amazon.awssdk/sts {:mvn/version "2.33.0"} ; Required for S3 client to use service account
software.amazon.awssdk/s3 {:mvn/version "2.36.2"} ; AWS SDK v2 for S3
software.amazon.awssdk/sts {:mvn/version "2.36.2"} ; Required for S3 client to use service account
stencil/stencil {:mvn/version "0.5.0"} ; Mustache templates for Clojure
user-agent/user-agent {:mvn/version "0.1.1"} ; User-Agent string parser, for Login History page & elsewhere
weavejester/dependency {:mvn/version "1.0.0"} ; Dependency graphs and topological sorting
@@ -245,7 +245,7 @@
;; (dev/start!)
:dev
{:extra-deps
{cider/cider-nrepl {:mvn/version "0.57.0"} ; nREPL server for CIDER
{cider/cider-nrepl {:mvn/version "0.58.0"} ; nREPL server for CIDER
clj-http-fake/clj-http-fake {:mvn/version "1.0.4"
:exclusions [slingshot/slingshot]}
clj-kondo/clj-kondo {:mvn/version "2025.07.28"} ; included here mainly to facilitate working on the stuff in `.clj-kondo/src`
@@ -256,7 +256,7 @@
{:mvn/version "0.4.0"} ; Enables easy memory measurement
com.gfredericks/test.chuck {:mvn/version "0.2.15"} ; generating strings from regexes (useful with malli)
criterium/criterium {:mvn/version "0.4.6"} ; benchmarking library
djblue/portal {:mvn/version "0.61.0"} ; ui for inspecting values
djblue/portal {:mvn/version "0.62.0"} ; ui for inspecting values
io.github.camsaul/humane-are {:mvn/version "1.0.2"} ; cleaner test output
io.github.metabase/hawk {:mvn/version "1.0.13"} ; test runner
jonase/eastwood {:mvn/version "1.4.3" ; inspects namespaces and reports possible problems using tools.analyzer
@@ -264,7 +264,7 @@
[org.ow2.asm/asm-all]}
lambdaisland/deep-diff2 {:mvn/version "2.12.219"} ; way better diffs
net.solovyov/hashp {:mvn/version "0.4.0-1"} ; debugging/spying utility
nrepl/nrepl {:mvn/version "1.4.0"} ; nREPL server
nrepl/nrepl {:mvn/version "1.5.1"} ; nREPL server
peridot/peridot {:git/url "https://github.com/piranha/peridot.git"
:sha "db627c627db3b527a63caf472f0422e4cbfdf574"} ; mocking Ring requests; waiting for upstream release of commit 0fc7c01 (explicit charset)
pjstadig/humane-test-output {:mvn/version "0.11.0"}
@@ -410,8 +410,8 @@
{:extra-paths ["test"]
:extra-deps
{binaryage/devtools {:mvn/version "1.0.7"}
cider/cider-nrepl {:mvn/version "0.57.0"}
cider/piggieback {:mvn/version "0.6.0"}
cider/cider-nrepl {:mvn/version "0.58.0"}
cider/piggieback {:mvn/version "0.6.1"}
cljs-bean/cljs-bean {:mvn/version "1.9.0"}
com.lambdaisland/glogi {:mvn/version "1.3.169"}
io.github.metabase/hawk {:mvn/version "1.0.13"}
@@ -691,7 +691,7 @@
;;
;; ./bin/mage cljfmt-all -h for more info
:cljfmt
{:deps {io.github.weavejester/cljfmt {:git/sha "7de286008766127128a156275b9add3bf443d7e5"}}
{:deps {io.github.weavejester/cljfmt {:mvn/version "0.15.3"}}
:ns-default cljfmt.tool
:exec-fn cljfmt.tool/fix}
@@ -706,7 +706,7 @@
{com.bhauman/spell-spec {:mvn/version "0.1.2"} ; used to find misspellings in YAML files
expound/expound {:mvn/version "0.9.0"} ; better output of spec validation errors
io.github.borkdude/grasp {:mvn/version "0.1.4"}
io.github.clojure/tools.build {:mvn/version "0.10.10"}
io.github.clojure/tools.build {:mvn/version "0.10.11"}
io.github.seancorfield/build-uber-log4j2-handler
{:git/tag "v2.25.1" :git/sha "1cfab45"} ; collect binary files for log4j2
org.clojure/data.xml {:mvn/version "0.2.0-alpha9"}
@@ -807,7 +807,7 @@
;;
;; clojure -M:dev:nrepl (etc.)
:nrepl
{:extra-deps {nrepl/nrepl {:mvn/version "1.4.0"}}
{:extra-deps {nrepl/nrepl {:mvn/version "1.5.1"}}
:main-opts ["-m" "nrepl.cmdline" "-p" "50605"]}
;; - start a Socket REPL on port 50505 that you can connect your editor to:
@@ -821,7 +821,7 @@
;;
;; clojure -M:liquibase dbDoc target/liquibase
:liquibase
{:extra-deps {ch.qos.logback/logback-classic {:mvn/version "1.5.18"}}
{:extra-deps {ch.qos.logback/logback-classic {:mvn/version "1.5.20"}}
:extra-paths ["dev/src"]
:main-opts ["-m" "dev.liquibase"]}

View File

@@ -1,6 +1,5 @@
(ns dev.deps-graph
(:require
[clojure.core.memoize :as memoize]
[clojure.edn :as edn]
[clojure.java.io :as io]
[clojure.string :as str]
@@ -126,6 +125,7 @@
(= (z/tag zloc) :uneval)))
(mu/defn- find-requires :- [:maybe [:sequential ::zloc]]
"Find all the zipper locations for `(require ...)` nodes."
[zloc :- ::zloc]
(concat
(when-not (comment-loc? zloc)
@@ -261,41 +261,46 @@
(file-dependencies "src/metabase/query_processor/middleware/permissions.clj"))
(def ^{:arglists '([])} dependencies
(memoize/ttl
(fn []
(doall (pmap file-dependencies (find-source-files))))
;; memoize for five seconds
:ttl/threshold 5000))
(defn dependencies []
(pmap file-dependencies (find-source-files)))
(defn external-usages
"All usages of a module named by `module-symb` outside that module."
[module-symb]
(for [dep (dependencies)
:when (not= (:module dep) module-symb)
ns-dep (:deps dep)
:when (= (:module ns-dep) module-symb)]
{:namespace (:namespace dep)
:module (:module dep)
:depends-on-namespace (:namespace ns-dep)
:depends-on-module (:module ns-dep)}))
([module-symb]
(external-usages (dependencies) module-symb))
([deps module-symb]
(for [dep deps
:when (not= (:module dep) module-symb)
ns-dep (:deps dep)
:when (= (:module ns-dep) module-symb)]
{:namespace (:namespace dep)
:module (:module dep)
:depends-on-namespace (:namespace ns-dep)
:depends-on-module (:module ns-dep)})))
(defn external-usages-by-namespace
"Return a map of module namespace => set of external namespaces using it"
[module-symb]
(into (sorted-map)
(map (fn [[k v]]
[k (into (sorted-set) (map :namespace) v)]))
(group-by :depends-on-namespace (external-usages module-symb))))
([module-symb]
(external-usages-by-namespace (dependencies) module-symb))
([deps module-symb]
(into (sorted-map)
(map (fn [[k v]]
[k (into (sorted-set) (map :namespace) v)]))
(group-by :depends-on-namespace (external-usages deps module-symb)))))
(defn externally-used-namespaces
"All namespaces from a module that are used outside that module."
[module-symb]
(into (sorted-set) (map :depends-on-namespace) (external-usages module-symb)))
([module-symb]
(externally-used-namespaces (dependencies) module-symb))
([deps module-symb]
(into (sorted-set) (map :depends-on-namespace) (external-usages deps module-symb))))
(defn module-dependencies
"Build a graph of module => set of modules it refers to."
([]
([deps]
(letfn [(reduce-module-deps [module-deps module deps]
(reduce
(fn [module-deps {dep-module :module, :as _dep}]
@@ -305,15 +310,15 @@
deps))
(reduce-deps [module->deps {:keys [module deps]}]
(update module->deps module reduce-module-deps module deps))]
(reduce reduce-deps (sorted-map) (dependencies))))
(reduce reduce-deps (sorted-map) deps)))
([module]
(get (module-dependencies) module)))
([deps module]
(get (module-dependencies deps) module)))
(defn circular-dependencies
"Build a graph of module => set of modules it refers to that also refer to this module."
([]
(let [module->deps (module-dependencies)]
([deps]
(let [module->deps (module-dependencies deps)]
(letfn [(circular-dependency? [module-x module-y]
(and (contains? (get module->deps module-x) module-y)
(contains? (get module->deps module-y) module-x)))
@@ -329,37 +334,40 @@
[module circular-deps])))
(keys module->deps)))))
([module]
(get (circular-dependencies) module)))
([deps module]
(get (circular-dependencies deps) module)))
(defn non-circular-module-dependencies
"A graph of [[module-dependencies]], but with modules that have any circular dependencies filtered out. This is mostly
meant to make it easier to fill out the `:metabase/modules` `:uses` section of the Kondo config, or to figure out
which ones can easily get a consolidated API namespace without drama."
[]
(let [circular-dependencies (circular-dependencies)]
[deps]
(let [circular-dependencies (circular-dependencies deps)]
(into (sorted-map)
(remove (fn [[module _deps]]
(contains? circular-dependencies module)))
(module-dependencies))))
(module-dependencies deps))))
(defn module-usages-of-other-module
"Information about how `module-x` uses `module-y`."
[module-x module-y]
(let [module-x-ns->module-y-ns (->> (external-usages module-y)
(filter #(= (:module %) module-x))
(map (juxt :namespace :depends-on-namespace)))]
(reduce
(fn [m [module-x-ns module-y-ns]]
(update m module-x-ns (fn [deps]
(conj (or deps (sorted-set)) module-y-ns))))
(sorted-map)
module-x-ns->module-y-ns)))
([module-x module-y]
(module-usages-of-other-module (dependencies) module-x module-y))
([deps module-x module-y]
(let [module-x-ns->module-y-ns (->> (external-usages deps module-y)
(filter #(= (:module %) module-x))
(map (juxt :namespace :depends-on-namespace)))]
(reduce
(fn [m [module-x-ns module-y-ns]]
(update m module-x-ns (fn [deps]
(conj (or deps (sorted-set)) module-y-ns))))
(sorted-map)
module-x-ns->module-y-ns))))
(defn full-dependencies
"Like [[dependencies]] but also includes transient dependencies."
[]
(let [deps-graph (module-dependencies)
[deps]
(let [deps-graph (module-dependencies deps)
expand-deps (fn expand-deps [deps]
(let [deps' (into (sorted-set)
(mapcat deps-graph)
@@ -372,33 +380,23 @@
[k (expand-deps v)]))
deps-graph)))
(defn module-deps-count []
(defn module-deps-count [deps]
(into (sorted-map)
(map (fn [[k v]]
[k (count v)]))
(full-dependencies)))
(defn module-dependencies-mermaid []
(println "flowchart TD")
(doseq [[module deps] (module-dependencies)
dep deps]
(printf "%s-->%s\n" module dep)))
(defn module-dependencies-graphviz []
(println "digraph {")
(doseq [[module deps] (module-dependencies)
dep deps]
(printf " \"%s\" -> \"%s\"\n" module dep))
(println "}"))
(full-dependencies deps)))
(defn generate-config
"Generate the Kondo config that should go in `.clj-kondo/config/modules/config.edn`."
[]
(into (sorted-map)
(map (fn [[module uses]]
[module {:api (externally-used-namespaces module)
:uses uses}]))
(module-dependencies)))
([]
(generate-config (dependencies)))
([deps]
(into (sorted-map)
(map (fn [[module uses]]
[module {:api (externally-used-namespaces deps module)
:uses uses}]))
(module-dependencies deps))))
(defn kondo-config
"Read out the Kondo config for the modules linter."
@@ -422,13 +420,16 @@
diff))
(defn kondo-config-diff
[]
(-> (ddiff/diff
(update-vals (kondo-config) #(dissoc % :team))
(generate-config))
ddiff/minimize
kondo-config-diff-ignore-any
ddiff/minimize))
([]
(kondo-config-diff (dependencies)))
([deps]
(-> (ddiff/diff
(update-vals (kondo-config) #(dissoc % :team))
(generate-config deps))
ddiff/minimize
kondo-config-diff-ignore-any
ddiff/minimize)))
(defn print-kondo-config-diff
"Print the diff between how the config would look if regenerated with [[generate-config]] versus how it looks in
@@ -437,6 +438,6 @@
(ddiff/pretty-print (kondo-config-diff)))
(comment
(module-dependencies 'lib)
(module-dependencies (dependencies) 'lib)
(module-usages-of-other-module 'lib 'models))

View File

@@ -37,7 +37,7 @@ The core team runs a pretty well defined product process. It is actively being t
### A) Identify product needs from the community
We actively look for new feature ideas from our community, user base and our own use of Metabase internally. We concentrate on the underlying _problem_ or _need_ as opposed to requests for specific features. While sometimes suggested features are built as requested, often we find that they involve changes to existing features, and perhaps an entirely different solution to the underlying problem. These will typically be collected in a number of issues, and tagged [Proposal](https://github.com/metabase/metabase/labels/.Proposal)
We actively look for new feature ideas from our community, user base and our own use of Metabase internally. We concentrate on the underlying _problem_ or _need_ as opposed to requests for specific features. While sometimes suggested features are built as requested, often we find that they involve changes to existing features, and potentially an entirely different solution to the underlying problem. These will typically be collected in a number of issues, and tagged [Proposal](https://github.com/metabase/metabase/labels/.Proposal)
### B) Synthesize these needs into a concrete feature
@@ -107,4 +107,4 @@ Generally speaking, any issue in [Help Wanted](https://github.com/metabase/metab
### #YOLO JUST SUBMIT A PR
If you come up with something really cool, and want to share it with us, just submit a PR. If it hasn't gone through the above process, we probably won't merge it as is, but if it's compelling, we're more than willing to help you via code review, design review and generally OCD nitpicking so that it fits into the rest of our codebase.
If you come up with something cool, and want to share it with us, just submit a PR. If it hasn't gone through the above process, we probably won't merge it as is, but if it's compelling, we're more than willing to help you via code review, design review and generally OCD nitpicking so that it fits into the rest of our codebase.

View File

@@ -51,6 +51,7 @@ Metabase's reference documentation.
- [Monitoring your Metabase](./installation-and-operation/monitoring-metabase.md)
- [Development instances](./installation-and-operation/development-instance.md)
- [Serialization](./installation-and-operation/serialization.md)
- [Remote sync](./installation-and-operation/remote-sync.md)
- [Commands](./installation-and-operation/commands.md)
- [Supported browsers](./installation-and-operation/supported-browsers.md)
- [Privacy](./installation-and-operation/privacy.md)

View File

@@ -55,7 +55,7 @@ There are multiple ways to run actions:
Just something to clarify here: actions, even though they are added to models, make their changes to the underlying table that a model queries. Which means that anyone who has access to the underlying table, or to questions or other models based on that table, will be able to see the effects of an action. Tools other than Metabase that are connected to that database will also pick up these changes.
In this sense, models are containers for actions; models are a way to organize actions. In fact, you could (in theory) add a [custom action](./custom.md) to a model that performs some update unrelated to its model's data. For example, you could write a custom action that updates the `Accounts` table, and add that action to a model that only queries an unrelated table (e.g., the `Orders` table). But, you know, maybe don't do that (unless you have a really good reason). [Basic actions](./basic.md), however, are only be available for models that wrap a single raw table.
In this sense, models are containers for actions; models are a way to organize actions. In fact, you could (in theory) add a [custom action](./custom.md) to a model that performs some update unrelated to its model's data. For example, you could write a custom action that updates the `Accounts` table, and add that action to a model that only queries an unrelated table (e.g., the `Orders` table). But, you know, maybe don't do that (unless you have a good reason). [Basic actions](./basic.md), however, are only be available for models that wrap a single raw table.
Before using actions in production, consider playing around with actions on some sample data (like the Sample Database included with Metabase) to get a feel for how they work.

File diff suppressed because one or more lines are too long

30736
docs/api.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -34,7 +34,7 @@ Here's how to set it up:
5. Give the service account **Viewer** permissions. Metabase will only have access to this folder or sheet; it won't have access to any other files in your Google Drive. If you select folder, Metabase will also sync any sheets it finds in any subfolders.
6. Click **Send** to share the folder with the Metabase service account.
7. Copy the sharing link for the folder or sheet.
8. Return to Metabase and paste the sharing link into the field that asks for "the sharing link for this folder/file".
8. Return to Metabase and paste the sharing link into "the sharing link for this folder/file" field.
**If you synced a Google Drive folder**, Metabase will sync with the Google Drive folder (and its subfolders) and import all Google Sheets, creating a new table in your Metabase Cloud Storage database for each sheet. For sheets with multiple tabs, Metabase will create a table for each tab. Metabase will only sync Google Sheets; it'll ignore other file types in the folder. After the initial sync, Metabase will sync every 15 minutes.

View File

@@ -16,7 +16,7 @@ There are some additional steps you'll need to take to migrate from Heroku to Me
## Follow the migration guide to get the migration script
You should follow along with the [migration guide](./guide.md). Once you download the migration script you'll need to get shell access to your Heroku server in order to execute the migration script.
You should follow along with the [migration guide](./guide.md). Once you download the migration script you'll need to get shell access to your Heroku server to execute the migration script.
## Install Heroku CLI for your OS

View File

@@ -79,7 +79,7 @@ To remove Metabase Cloud Storage (which will _permanently_ erase all its data):
3. Click **Manage storage**.
4. Click **Edit**.
5. Click **Disable storage**.
6. Click **Erase all data**, which---**WARNING**--will erase _all of its data_. We won't be able to recover the data, so only do this if you're absolutely sure you no need the storage and its data.
6. Click **Erase all data**, which---**WARNING**--will erase _all of its data_. We won't be able to recover the data, so only do this if you're certain you no longer need the storage and its data.
## Syncing Google Sheets with Metabase

View File

@@ -30,7 +30,13 @@ Appearance settings are split across different tabs:
## Dark mode
People can display their Metabase in dark mode in their [account settings](../people-and-groups/account-settings.md#theme). Dark mode is a user-level setting, not an instance-level setting. Currently, there's no way to change the theme to dark mode for the entire instance, but you can edit some [user interface colors](#user-interface-colors).
People can display their Metabase in dark mode in their [account settings](../people-and-groups/account-settings.md#theme). Options are:
- System default (which is also the default setting). Metabase will switch between light and dark mode when the system switches without having to reload the page.
- Always use dark mode.
- Always use light mode.
Dark mode is a user-level setting, not an instance-level setting. Currently, there's no way to change the theme to dark mode for the entire instance, but you can edit some [user interface colors](#user-interface-colors).
## Branding
@@ -74,7 +80,7 @@ Custom colors are unavailable for:
## Logo
You can replace Metabase’s familiar, tasteful, inspired-yet-not-threateningly-avant-garde dotted M logo with your very own logo. For things to work best, the logo you upload should be an SVG file that looks good when it’s around 60px tall. (In other words, ask the nearest designer for help.)
You can replace Metabase's familiar, tasteful, inspired-yet-not-threateningly-avant-garde dotted M logo with your very own logo. For things to work best, the logo you upload should be an SVG file that looks good when it's around 60px tall. (In other words, ask the nearest designer for help.)
## Font

View File

@@ -155,6 +155,7 @@ config:
health-check-logging-enabled: true
help-link: metabase
help-link-custom-destination: https://www.metabase.com/help/premium
hide-stacktraces: false
http-channel-host-strategy: external-only
humanization-strategy: simple
index-update-thread-count: 2
@@ -215,6 +216,9 @@ config:
query-caching-max-kb: 2000
query-caching-max-ttl: 3024000.0
redirect-all-requests-to-https: false
remote-sync-auto-import: false
remote-sync-auto-import-rate: 5
remote-sync-task-time-limit-ms: 300000
report-timezone: null
reset-token-ttl-hours: 48
retry-initial-interval: 500
@@ -272,6 +276,5 @@ config:
synchronous-batch-updates: false
unaggregated-query-row-limit: null
uploads-settings: null
use-tenants: false
user-visibility: all
```

View File

@@ -747,6 +747,14 @@ Keyword setting to control whitelabeling of the help link. Valid values are `:me
Custom URL for the help link.
### `MB_HIDE_STACKTRACES`
- Type: boolean
- Default: `false`
- [Configuration file name](./config-file.md): `hide-stacktraces`
Prevent the exception middleware from including stacktraces in responses.
### `MB_HTTP_CHANNEL_HOST_STRATEGY`
- Type: keyword
@@ -1306,6 +1314,30 @@ The absolute maximum time to keep any cached query results, in seconds.
Force all traffic to use HTTPS via a redirect, if the site URL is HTTPS.
### `MB_REMOTE_SYNC_AUTO_IMPORT`
- Type: boolean
- Default: `false`
- [Configuration file name](./config-file.md): `remote-sync-auto-import`
Whether to automatically import from the remote git repository. Only applies if remote-sync-type is :production.
### `MB_REMOTE_SYNC_AUTO_IMPORT_RATE`
- Type: integer
- Default: `5`
- [Configuration file name](./config-file.md): `remote-sync-auto-import-rate`
If remote-sync-type is :production and remote-sync-auto-import is true, the rate (in minutes) at which to check for updates to import. Defaults to 5.
### `MB_REMOTE_SYNC_TASK_TIME_LIMIT_MS`
- Type: integer
- Default: `300000`
- [Configuration file name](./config-file.md): `remote-sync-task-time-limit-ms`
The maximum amount of time a remote sync task will be given to complete.
### `MB_REPORT_TIMEZONE`
- Type: string
@@ -1886,16 +1918,6 @@ Upload settings.
Prefix for upload table names.
### `MB_USE_TENANTS`
> Only available on Metabase [Pro](https://www.metabase.com/product/pro) and [Enterprise](https://www.metabase.com/product/enterprise) plans.
- Type: boolean
- Default: `false`
- [Configuration file name](./config-file.md): `use-tenants`
Turn on the Tenants feature, allowing users to be assigned to a particular Tenant.
### `MB_USER_VISIBILITY`
> Only available on Metabase [Pro](https://www.metabase.com/product/pro) and [Enterprise](https://www.metabase.com/product/enterprise) plans.
@@ -1950,7 +1972,7 @@ Maximum number of async Jetty threads. If not set, then [MB_JETTY_MAXTHREADS](#m
Type: integer<br>
Default: `20`<br>
Limits the number of rows Metabase will display in tables sent with dashboard subscriptions and alerts. Range: 1-100. To limit the total number of rows included in the file attachment for an email dashboard subscription, use [MB_UNAGGREGATED_QUERY_ROW_LIMIT](#mb_unaggregated_query_row_limit).
Limits the number of rows Metabase will display in tables sent with dashboard subscriptions and alerts. Range: 1-100. To limit the total number of rows included in the file attachment for an email dashboard subscription, use [MB_ATTACHMENT_ROW_LIMIT](#mb_attachment_row_limit).
### `MB_AUDIT_MAX_RETENTION_DAYS`

View File

@@ -46,7 +46,7 @@ For **Font**, select **Custom...** and enter URLs to your font files.
## Font style options
You can set three different font styles with three different URLs, one for each font style (size and weight) that Metabase will use in order to display its user interface properly. The font weights are:
You can set three different font styles with three different URLs, one for each font style (size and weight) that Metabase will use to display its user interface properly. The font weights are:
- Regular 400
- Bold 700

View File

@@ -80,7 +80,7 @@ java -Dlog4j.configurationFile=file:/path/to/custom/log4j2.xml -jar metabase.jar
## Configure Jetty logs
You can configure Metabase's web server to provide more detail in the logs by setting the log level to `DEBUG`. Just keep in mind that Jetty's debug logs can be really chatty, which can make it difficult to find the data you're looking for.
You can configure Metabase's web server to provide more detail in the logs by setting the log level to `DEBUG`. Just keep in mind that Jetty's debug logs can be chatty, which can make it difficult to find the data you're looking for.
To get Jetty logs, add the following lines to the Log4J2 XML file in the <Loggers> node:

View File

@@ -15,7 +15,7 @@ Go ahead and click **Let’s get started**.
## Setting up an admin account
The first thing you’ll need to do is set up an admin account. The account you create when you first install Metabase is an admin account by default — handy! If you’ve installed Metabase on a production server, you should be really careful to remember the password for this account since it will be used to add other users, connect to databases, set up email, and more. You can also create additional admin accounts later.
The first thing you'll need to do is set up an admin account. The account you create when you first install Metabase is an admin account by default — handy! If you've installed Metabase on a production server, you should be careful to remember the password for this account since it will be used to add other users, connect to databases, set up email, and more. You can also create additional admin accounts later.
For now, let's just create an account for ourselves to explore Metabase. Type in your info, and when you’re ready to continue, click the **Next** button.

View File

@@ -45,6 +45,6 @@ The exact data type will depend on your database. Some Metabase features only wo
## Common pitfalls
1. Your database is using date/time columns without any timezone information. Typically when this happens your database will assume all the data is from whatever timezone the database is configured in or possible just default to UTC (check your database vendor to be sure).
2. Your JVM timezone is different from your Metabase `Report Timezone` choice. This is a very common issue and can be corrected by launching java with the `-Duser.timezone=<timezone>` option properly set to match your Metabase report timezone.
2. Your JVM timezone is different from your Metabase `Report Timezone` choice. This is a common issue and can be corrected by launching java with the `-Duser.timezone=<timezone>` option properly set to match your Metabase report timezone.
If you are still experiencing timezone problems, then have a look at the [timezone troubleshooting guide](../troubleshooting-guide/timezones.md).

View File

@@ -43,7 +43,7 @@ And the data as seen in the table view, which Metabase will send as a `raw_data`
![Results as table view](./images/table-view.png)
Here's an example payload for an alert (we truncated the PNG encoding because it's long and extremely boring):
Here's an example payload for an alert (we truncated the PNG encoding because it's boring):
```JSON
{

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

View File

@@ -283,9 +283,7 @@ If you don't see the palette icon, you'll need to:
After you've made your ideal dashboard, you may want to put the dashboard on a TV to help keep your team up to date throughout the day.
To enter fullscreen mode, click the **fullscreen** icon in the top right of the dashboard (the icon with the arrows pointing in opposite directions). Once you've entered fullscreen mode, you can also switch the dashboard into "Night mode" for higher contrast.
![Night mode](images/dark-mode.png)
To enter fullscreen mode, click the **fullscreen** icon in the top right of the dashboard (the icon with the arrows pointing in opposite directions).
## Auto refresh

View File

@@ -56,7 +56,7 @@ Metabase uses database column metadata to populate values for linked filters, wh
- You can't create linked filters on custom columns.
- Native/SQL questions must have a [field filter](../questions/native-editor/field-filters.md) variable in order to be linked. Basic SQL variables aren't connected to database columns, so they won't work for linked filters.
- Native/SQL questions must have a [field filter](../questions/native-editor/field-filters.md) variable to be linked. Basic SQL variables aren't connected to database columns, so they won't work for linked filters.
- You can't link filters that use "Custom List" or "From another model or question" as their value's source.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

View File

@@ -93,7 +93,7 @@ Click the preview button to see sample data from that field.
_Admin settings > Table Metadata > Database > Table > Field_
To scan or discard field values for a specific field, click on the **Field values** button. Metabase uses these values to populate dropdown menus in filter widgets. (To be clear, values aren't actually dropped from your database.)
To scan or discard field values for a specific field, click on the **Field values** button. Metabase uses these values to populate dropdown menus in filter widgets. (Values aren't dropped from your database.)
## Field data

View File

@@ -16,7 +16,7 @@ Models:
- Can [surface individual records in search results](#surface-individual-records-in-search-by-matching-against-this-column).
- Can be [persisted for faster loading](./model-persistence.md).
For a deep dive on why and how to use models, check out our [Learn article on models][learn-models].
For more on why and how to use models, check out our [Learn article on models][learn-models].
## How to use models
@@ -121,7 +121,10 @@ You can edit a model's query by clicking on the down arrow next to the model's n
## Model list view
![Viewing a model as a list, with a detail view](./images/model-list-detail.png)
![Viewing a model as a list](./images/model-list.png)
List view helps you explore records one by one instead of sorting through big tables. You can customize the layout to highlight the most important fields.
To view a model as a list:
@@ -131,7 +134,7 @@ To view a model as a list:
4. Navigate to the **Settings** tab.
5. Under "What should the default view of this data be?", toggle to **List**.
![Model list view](./images/model-list-view.png)
![Model list edit](./images/model-list-edit.png)
### Customize model list view
@@ -141,21 +144,18 @@ You can customize how the data appears by clicking **Customize the List layout**
Each item in the list has:
- An entity icon
- A left column with:
- The title or primary identifier on top.
- A subtitle/description or secondary identifier.
- An image (only if the record contains an image link)
- A right column for up to 5 additional columns.
- **An entity icon.** If the record has an image link, it shows the image, which you can hide anytime.
- **A left column** showing the title or primary identifier.
- **A right column** for up to 5 additional columns.
You can:
- **Search for columns** using the "Find a column..." search box
- **Drag columns** from the available list into either the left (Title + Subtitle) or right columns areas
- **Reorder columns** by dragging them within their respective areas
- **Search for columns** using the "Find a column..." search box.
- **Drag columns** from the available list into either the left column or right columns areas.
- **Reorder columns** by dragging them within their respective areas.
- **Remove columns** by clicking on the X on the column.
You can see a preview on the bottom with sample data from your model.
You can see a preview on the bottom with sample data from your model.
Click **Done** to save your changes.

View File

@@ -42,7 +42,7 @@ You can think of semantic types as adding meaning and context to a field to comm
- **Entity key.** Used to indicate that the field uniquely identifies each row. Could be a Product ID, serial number, etc.
- **Foreign key.** Used to refer to an Entity key of another table in order to connect data from different tables that are related. For example, in a Products table, you might have a Customer ID field that points to a Customers table, where Customer ID is the Entity key. If you want to use [linked filters on dashboards](../dashboards/linked-filters.md), you must set up foreign key relationships.
- **Foreign key.** Used to refer to an Entity key of another table to connect data from different tables that are related. For example, in a Products table, you might have a Customer ID field that points to a Customers table, where Customer ID is the Entity key. If you want to use [linked filters on dashboards](../dashboards/linked-filters.md), you must set up foreign key relationships.
### Semantic types for numeric fields

View File

@@ -77,13 +77,13 @@ If you've selected **Choose when syncs and scans happen** > **ON**, you'll be ab
#### Scanning for filter values
Metabase can scan the values present in each field in this database to enable checkbox filters in dashboards and questions. This can be a somewhat resource-intensive process, particularly if you have a very large database.
Metabase can scan the values present in each field in this database to enable checkbox filters in dashboards and questions. This can be a resource-intensive process, particularly if you have a large database.
If you've selected **Choose when syncs and scans happen** > **ON**, you'll see the following options under **Scanning for filter values**:
- **Regularly, on a schedule** allows you to run [scan queries](../sync-scan.md#how-database-scans-work) at a frequency that matches the rate of change to your database. The time is set in the timezone of the server where your Metabase app is running. This is the best option for a small database, or tables with distinct values that get updated often.
- **Only when adding a new filter widget** is a great option if you want scan queries to run on demand. Turning this option **ON** means that Metabase will only scan and cache the values of the field(s) that are used when a new filter is added to a dashboard or SQL question.
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large, or which never really have new values added. Use the [Re-scan field values](../sync-scan.md#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large, or which rarely have new values added. Use the [Re-scan field values](../sync-scan.md#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
### Periodically refingerprint tables

View File

@@ -80,7 +80,7 @@ A fingerprinting query examines the first 10,000 rows from each column and uses
## Connecting to MySQL 8+ servers
Metabase uses the MariaDB connector to connect to MySQL servers. The MariaDB connector lacks support for MySQL 8's default authentication plugin. In order to connect, you'll need to change the plugin used by the Metabase user:
Metabase uses the MariaDB connector to connect to MySQL servers. The MariaDB connector lacks support for MySQL 8's default authentication plugin. To connect, you'll need to change the plugin used by the Metabase user:
```
mysql_native_password`: `ALTER USER 'metabase'@'%' IDENTIFIED WITH mysql_native_password BY 'thepassword';
@@ -183,7 +183,7 @@ Choose whether to enable features related to [Metabase models](../../data-modeli
### Model actions
Turn this setting on to allow [actions](../../actions/introduction.md) from models created from this data to be run. Actions are able to read, write, and possibly delete data. Your database user will need write permissions.
Turn this setting on to allow [actions](../../actions/introduction.md) from models created from this data to be run. Actions can read, write, and delete data. Your database user will need write permissions.
### Model persistence

View File

@@ -102,7 +102,7 @@ Note that only the `*` wildcard is supported; you can't use other special charac
### Use a secure connection (SSL)
Metabase automatically tries to connect to databases with SSL first, then without if that doesn't work. If it's possible to connect to your database with an SSL connection, Metabase will make that the default setting for your database. If you prefer to connect without this layer of security, you can always change this setting later, but we highly recommend keeping SSL turned on to keep your data secure.
Metabase automatically tries to connect to databases with SSL first, then without if that doesn't work. If it's possible to connect to your database with an SSL connection, Metabase will make that the default setting for your database. If you prefer to connect without this layer of security, you can always change this setting later, but we recommend keeping SSL turned on to keep your data secure.
#### SSL Mode
@@ -188,7 +188,7 @@ Choose whether to enable features related to [Metabase models](../../data-modeli
### Model actions
Turn this setting on to allow [actions](../../actions/introduction.md) from models created from this data to be run. Actions are able to read, write, and possibly delete data. Your database user will need write permissions.
Turn this setting on to allow [actions](../../actions/introduction.md) from models created from this data to be run. Actions can read, write, and delete data. Your database user will need write permissions.
### Model persistence

View File

@@ -46,7 +46,7 @@ The password for the username that you use to connect to the database.
### Use a secure connection (SSL)
Metabase automatically tries to connect to databases with SSL first, then without if that doesn't work. If it's possible to connect to your database with an SSL connection, Metabase will make that the default setting for your database. If you prefer to connect without this layer of security, you can always change this setting later, but we highly recommend keeping SSL turned on to keep your data secure.
Metabase automatically tries to connect to databases with SSL first, then without if that doesn't work. If it's possible to connect to your database with an SSL connection, Metabase will make that the default setting for your database. If you prefer to connect without this layer of security, you can always change this setting later, but we recommend keeping SSL turned on to keep your data secure.
### Use SSL certificate?

View File

@@ -61,13 +61,13 @@ If you've selected **Choose when syncs and scans happen** > **ON**, you'll be ab
#### Scanning for filter values
Metabase can scan the values present in each field in this database to enable checkbox filters in dashboards and questions. This can be a somewhat resource-intensive process, particularly if you have a very large database.
Metabase can scan the values present in each field in this database to enable checkbox filters in dashboards and questions. This can be a resource-intensive process, particularly if you have a large database.
If you've selected **Choose when syncs and scans happen** > **ON**, you'll see the following options under **Scanning for filter values**:
- **Regularly, on a schedule** allows you to run [scan queries](../sync-scan.md#how-database-scans-work) at a frequency that matches the rate of change to your database. The time is set in the timezone of the server where your Metabase app is running. This is the best option for a small database, or tables with distinct values that get updated often.
- **Only when adding a new filter widget** is a great option if you want scan queries to run on demand. Turning this option **ON** means that Metabase will only scan and cache the values of the field(s) that are used when a new filter is added to a dashboard or SQL question.
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large, or which never really have new values added. Use the [Re-scan field values now](../sync-scan.md#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large, or which rarely have new values added. Use the [Re-scan field values now](../sync-scan.md#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
### Periodically refingerprint tables

View File

@@ -48,7 +48,7 @@ The password for the username that you use to connect to the database.
### Use a secure connection (SSL)
Metabase automatically tries to connect to databases with SSL first, then without if that doesn't work. If it's possible to connect to your database with an SSL connection, Metabase will make that the default setting for your database. If you prefer to connect without this layer of security, you can always change this setting later, but we highly recommend keeping SSL turned on to keep your data secure.
Metabase automatically tries to connect to databases with SSL first, then without if that doesn't work. If it's possible to connect to your database with an SSL connection, Metabase will make that the default setting for your database. If you prefer to connect without this layer of security, you can always change this setting later, but we recommend keeping SSL turned on to keep your data secure.
### Use an SSH tunnel
@@ -77,13 +77,13 @@ If you've selected **Choose when syncs and scans happen** > **ON**, you'll be ab
### Scanning for filter values
Metabase can scan the values present in each field in this database to enable checkbox filters in dashboards and questions. This can be a somewhat resource-intensive process, particularly if you have a very large database.
Metabase can scan the values present in each field in this database to enable checkbox filters in dashboards and questions. This can be a resource-intensive process, particularly if you have a large database.
If you've selected **Choose when syncs and scans happen** > **ON**, you'll see the following options under **Scanning for filter values**:
- **Regularly, on a schedule** allows you to run [scan queries](../sync-scan.md#how-database-scans-work) at a frequency that matches the rate of change to your database. The time is set in the timezone of the server where your Metabase app is running. This is the best option for a small database, or tables with distinct values that get updated often.
- **Only when adding a new filter widget** is a great option if you want scan queries to run on demand. Turning this option **ON** means that Metabase will only scan and cache the values of the field(s) that are used when a new filter is added to a dashboard or SQL question.
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large, or which never really have new values added. Use the [Re-scan field values](../sync-scan.md#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large, or which rarely have new values added. Use the [Re-scan field values](../sync-scan.md#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
### Periodically refingerprint tables

View File

@@ -45,13 +45,13 @@ If you've selected **Choose when syncs and scans happen** > **ON**, you'll be ab
### Scanning for filter values
Metabase can scan the values present in each field in this database to enable checkbox filters in dashboards and questions. This can be a somewhat resource-intensive process, particularly if you have a very large database.
Metabase can scan the values present in each field in this database to enable checkbox filters in dashboards and questions. This can be a resource-intensive process, particularly if you have a large database.
If you've selected **Choose when syncs and scans happen** > **ON**, you'll see the following options under **Scanning for filter values**:
- **Regularly, on a schedule** allows you to run [scan queries](../sync-scan.md#how-database-scans-work) at a frequency that matches the rate of change to your database. The time is set in the timezone of the server where your Metabase app is running. This is the best option for a small database, or tables with distinct values that get updated often.
- **Only when adding a new filter widget** is a great option if you want scan queries to run on demand. Turning this option **ON** means that Metabase will only scan and cache the values of the field(s) that are used when a new filter is added to a dashboard or SQL question.
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large, or which never really have new values added. Use the [Re-scan field values](../sync-scan.md#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large, or which rarely have new values added. Use the [Re-scan field values](../sync-scan.md#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
### Periodically refingerprint tables

View File

@@ -16,7 +16,7 @@ You can download the JDBC driver from [Vertica's JDBC driver downloads page](htt
Head to this page, log in to your account, accept the license agreement, and download `vertica-jdbc-8.0.0-0.jar` (for Vertica DB version 8.0)
or whatever driver version most closely matches the version of Vertica you're running.
It's very important to make sure you use the correct version of the JDBC driver; version
It's important to make sure you use the correct version of the JDBC driver; version
8.0 of the driver won't work with Vertica version 7.2; version 7.2 of the driver won't work with Vertica version 7.1, and so forth. If in doubt,
consult Vertica's documentation to find the correct version of the JDBC driver for your version of Vertica.

View File

@@ -48,7 +48,7 @@ Options include:
- **Regularly, on a schedule** allows you to run [scan queries](#how-database-scans-work) at a frequency that matches the rate of change to your database. The time is set in the timezone of the server where your Metabase app is running. This is the best option for a small database or tables with distinct values that get updated often.
- **Only when adding a new filter widget** is a great option if you want scan queries to run on demand. Turning this option **ON** means that Metabase will only scan and cache the values of the field(s) that are used when someone adds a new filter widget to a dashboard or SQL question (i.e., they add a parameter to their SQL query).
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large or which never really have new values added. Use the [Re-scan field values](#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
- **Never, I'll do this manually if I need to** is an option for databases that are either prohibitively large or which never have new values added. Use the [Re-scan field values](#manually-scanning-column-values) button to run a manual scan and bring your filter values up to date.
Regardless of which option you pick, if you [set a field to use a dropdown list in filter widgets](../data-modeling/metadata-editing.md#filtering), Metabase will need to get values for that dropdown. Whenever someone uses that filter widget, Metabase will first look for cached values (valid for fourteen days) to populate that dropdown; otherwise, it will re-scan that field for the most up-to-date values.
@@ -165,7 +165,7 @@ Cached column values are displayed in filter dropdown menus. If people type in t
A scan is more intensive than a sync query, so it only runs once during setup and again once a day by default. If you [disable scans](#scanning-for-filter-values) entirely, you'll need to bring things up to date by running [manual scans](#manually-scanning-column-values).
To reduce the number of tables and fields Metabase needs to scan in order to stay current with your connected database, Metabase will only scan values for fields that someone has used in the last fourteen days.
To reduce the number of tables and fields Metabase needs to scan to stay current with your connected database, Metabase will only scan values for fields that someone has used in the last fourteen days.
Here's the kind of data that scans get and why:

View File

@@ -30,7 +30,8 @@ Anyone can build a community driver. These are the currently known third-party d
| ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| [CSV](https://github.com/Markenson/csv-metabase-driver) | ![GitHub stars](https://img.shields.io/github/stars/Markenson/csv-metabase-driver) | ![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/Markenson/csv-metabase-driver) |
| [Databend](https://github.com/databendcloud/metabase-databend-driver) | ![GitHub stars](https://img.shields.io/github/stars/databendcloud/metabase-databend-driver) | ![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/databendcloud/metabase-databend-driver) |
| [DB2](https://github.com/damienchambe/metabase-db2-driver) | ![GitHub stars](https://img.shields.io/github/stars/damienchambe/metabase-db2-driver) | ![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/damienchambe/metabase-db2-driver) |
| [DB2 for LUW](https://github.com/alisonrafael/metabase-db2-driver) | ![GitHub stars](https://img.shields.io/github/stars/alisonrafael/metabase-db2-driver) | ![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/alisonrafael/metabase-db2-driver) |
| [IBM i](https://github.com/damienchambe/metabase-ibmi-driver) | ![GitHub stars](https://img.shields.io/github/stars/damienchambe/metabase-ibmi-driver) | ![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/damienchambe/metabase-ibmi-driver) |
| [Dremio](https://github.com/Baoqi/metabase-dremio-driver) | ![GitHub stars](https://img.shields.io/github/stars/Baoqi/metabase-dremio-driver) | ![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/Baoqi/metabase-dremio-driver) |
| [DuckDB](https://github.com/MotherDuck-Open-Source/metabase_duckdb_driver) | ![GitHub stars](https://img.shields.io/github/stars/MotherDuck-Open-Source/metabase_duckdb_driver) | ![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/MotherDuck-Open-Source/metabase_duckdb_driver) |
| [Firebolt](https://github.com/firebolt-db/metabase-firebolt-driver) | ![GitHub stars](https://img.shields.io/github/stars/firebolt-db/metabase-firebolt-driver) | ![GitHub (Pre-)Release Date](https://img.shields.io/github/release-date-pre/firebolt-db/metabase-firebolt-driver) |

View File

@@ -51,6 +51,7 @@ To edit a chart, click the **three-dot** menu in the chart's upper right. You ca
- Edit visualization
- Edit query
- Replace the chart with another question or model
- [Download results](../questions/exporting-results.md#exporting-results-from-document-cards)
Edits only affect the chart in the document. If you added the chart from a collection, Metabase will have created a copy of the chart. Any changes made to the chart in the document won't affect the original question.
@@ -123,6 +124,10 @@ This deletion is permanent.
To print a document, click on the **three-dot** menu and select **Print document**.
## Sharing documents
Admins can create [public links](../embedding/public-links.md#create-a-public-link-for-a-document) to share documents with anyone.
## When to use a document vs. a dashboard
Documents and dashboards both have their use cases.

View File

@@ -9,7 +9,7 @@ redirect_from:
> Only admins can create public links and iframes.
Admins can create and share public links (URLs) for questions and dashboards. People can view them as standalone destinations (URLs) or as embedded iframes in another page or app. In both cases, the public item will display static (view-only) results of your question or dashboard, so visitors won't be able to drill down into the underlying data on their own.
Admins can create and share public links (URLs) for questions, dashboards, and documents. People can view them as standalone destinations (URLs) or as embedded iframes in another page or app. Public items display view-only results of your question, dashboard, or document, so visitors won't be able to drill down into the underlying data on their own.
## Create a public link for a question
@@ -39,6 +39,12 @@ To share a dashboard via a public link, admins can click on the **Sharing** butt
To embed a dashboard, see [static embedding](./static-embedding.md).
## Create a public link for a document
To share a document via a public link, admins can click on the **Sharing** button in the top right menu and select **Create a public link**.
Public documents are read-only: viewers cannot edit the content or add comments. For charts embedded in the document, viewers can download the results in CSV, XLSX, or JSON format using the **Download results** option in the chart menu.
## Exporting raw, unformatted question results
To export the raw, unformatted rows, you'll need to append `?format_rows=false` to the URL Metabase generates. For example, if you create a public link for a CSV download, the URL would look like:
@@ -155,7 +161,7 @@ To disable public sharing:
3. In the **Settings** tab, select **Public sharing**.
4. Toggle off **Public sharing**.
Once toggled on, the **Public sharing** section will display Metabase questions, dashboards, and actions with active public links.
Once toggled on, the **Public sharing** section will display Metabase questions, dashboards, documents, and actions with active public links.
If you disable public sharing, then re-enable public sharing, all your previously generated public links will still work (as long as you didn't deactivate them).
@@ -180,7 +186,7 @@ Admins can view and deactivate all public links for a Metabase.
## See all publicly shared content
Admins can see all publicly shared questions, dashboards, and actions in **Admin Settings > Public Sharing**.
Admins can see all publicly shared questions, dashboards, documents, and actions in **Admin Settings > Public Sharing**.
![See shared content](./images/see-shared-content.png)

View File

@@ -8,7 +8,7 @@ title: "Embedded analytics SDK - dashboards"
You can embed an interactive, editable, or static dashboard.
**Please keep in mind - embedding multiple instances of dashboards on the same page is not yet supported.**
**Keep in mind that embedding multiple instances of dashboards on the same page is not yet supported.**
## Embedding a dashboard

View File

@@ -78,4 +78,4 @@ Run your app and visit the page with the embedded dashboard.
## Next steps
- Explore [theming to change the look and feel](./appearance.md).
- Continue by [setting up JWT SSO in Metabase and your app](./authentication.md) in order to sign people in, manage permissions, and deploy your app in production.
- Continue by [setting up JWT SSO in Metabase and your app](./authentication.md) to sign people in, manage permissions, and deploy your app in production.

View File

@@ -36,7 +36,7 @@ Metabase admins can designate collections as "official" with the following effec
Pairing Official badges with [verified items](./content-verification.md) can help everyone in your Metabase sort out which questions people can trust.
To add an Official badge to a collection, an admin can visit the collection and click on the dot dot dot menu (**...**) and select **Make collection official**. Admins can also remove an Official badge in the same menu. Admins can also mark a collection as Official or not when they first create the collection.
To add an Official badge to a collection, an admin can visit the collection and click on the three-dot menu (**...**) and select **Make collection official**. Admins can also remove an Official badge in the same menu. Admins can also mark a collection as Official or not when they first create the collection.
## Collection permissions

View File

@@ -6,7 +6,7 @@ redirect_from:
# Events and timelines
A lot of discussions around data have a moment when someone asks a question related to a specific point in time: "Wait, what's the spike in March again?", or "When did the new widget launch?"
A lot of discussions around data have a moment when someone has a question related to a specific point in time: "Wait, what's the spike in March again?", or "When did the new widget launch?"
Events and timelines are a way to capture that chronological knowledge and make it available when you need it, in context (that is, when you're viewing a chart). Events are a great way to store institutional knowledge about what happened and when, so people (including yourself three months from now) won't have to figure out (again) why the line chart spiked back in March.

View File

@@ -8,7 +8,7 @@ redirect_from:
## See what your teammates have made
As long as you're not the very first user in your team's Metabase, the easiest way to start exploring your data is by looking at dashboards, charts, and lists that your teammates have already created. The best place to start is by checking out any dashboards that might be pinned on your home page, or in [collections][collections] you have access to.
As long as you're not the first user in your team's Metabase, the easiest way to start exploring your data is by looking at dashboards, charts, and lists that your teammates have already created. The best place to start is by checking out any dashboards that might be pinned on your home page, or in [collections][collections] you have access to.
## Command palette
@@ -32,7 +32,7 @@ To filter your search results, hit `cmd/ctrl + k` to bring up the command palett
![Search results](./images/search-results.png)
Searches take into account items’ titles, descriptions, and other metadata — you can even search the contents of your SQL queries. For example, you can search for things like `SELECT escape_pod FROM mothership` and find that one question you worked on six months ago. The results will display which collection each item is saved in, what kind of object it is, and whether it’s pinned. Note that you'll only ever see items in that are in collections you have permission to view.
Searches consider items' titles, descriptions, and other metadata — you can even search the contents of your SQL queries. For example, you can search for things like `SELECT escape_pod FROM mothership` and find that one question you worked on six months ago. The results will display which collection each item is saved in, what kind of object it is, and whether it's pinned. Note that you'll only ever see items in that are in collections you have permission to view.
You can search by:

View File

@@ -9,7 +9,7 @@ redirect_from:
While we're working to make a product that is easy to use and inclusive to all, we're not yet fully compliant with [the U.S. federal government's Section 508 standards](https://www.section508.gov/) or the [Web Content Accessibility Guidelines (WCAG) 2.1](https://www.w3.org/TR/WCAG21/) at Level AA. We expect to build on our current state in the future, and as of today these are some general notes on our state of compliance:
- **Navigation and screen readers:** Most information is presented in a way to ensure it can be accessed by screen readers. Some interactive elements are not operable for screen reader users.
- **Navigation and screen readers:** Most information should be accessible to screen readers. Some interactive elements are not operable for screen reader users.
- **Non-text content:** While Metabase provides text alternatives for most non-text elements, some functional images either lack descriptions or have incomplete alt text.
- **Keyboard navigation:** Most form elements are keyboard-accessible, but certain interactive components, such as custom controls and non-modal dialogs, may lack full keyboard operability.
- **Focus management:** Some interactive elements lack a visible focus indicator. A few hidden interactive elements receive the keyboard focus.

View File

@@ -10,7 +10,7 @@ If you're self-hosting Metabase and you've opted in to provide us with anonymous
**[We only collect anonymous Metabase data; we don't collect any of your data](https://www.metabase.com/security).** We don't collect any usernames, emails, server IPs, database details of any kind, or any personally identifiable information (PII).
This anonymous data helps us understand how people are actually using Metabase, which in turn helps us prioritize what to work on next.
This anonymous data helps us understand how people are using Metabase, which in turn helps us prioritize what to work on next.
## Examples of the anonymous data we collect and how we use it
@@ -41,6 +41,25 @@ If you're self-hosting Metabase, you can opt out of providing us with your anony
If you're in the process of setting up your Metabase, you can also toggle off tracking during the `Usage Data Preferences` onboarding step. We collect a few anonymous events before that point, but won't do so anymore if you choose to opt out.
## Token validation requests for paid plans
If you're on a paid plan (Pro, Enterprise, or a trial), Metabase periodically sends a token validation request to verify your license. This is separate from the anonymous usage data described above.
### Data included in token validation requests
The token validation request includes:
- Count of active users (used for billing)
- Count of external users
- Count of internal users
- Count of email domains
- Count of embedded dashboards and questions
- Types of embedding (static, interactive, Embedded analytics SDK, Embedded analytics JS)
- Site UUID (just an identifier for your Metabase)
- Metabase version
- Query execution timestamp (last UTC day)
- Metabot usage statistics: count of tokens, queries, users, and date (just counts and the date).
## Further reading
Check out our page on [data privacy and security](https://www.metabase.com/security).

View File

@@ -82,7 +82,7 @@ When running into memory-related issues, typically the first question to ask is:
### Thread dump
Another useful picture of a running Metabase system is a Thread Dump. In cases when Metabase appears stalled or extremely slow, a thread dump will indicate what each thread is executing (or blocked on) for that specific point in time Collect a thread dump via the "Threads" tab:
Another useful picture of a running Metabase system is a Thread Dump. In cases when Metabase appears stalled or slow, a thread dump will indicate what each thread is executing (or blocked on) for that specific point in time Collect a thread dump via the "Threads" tab:
![threaddump](images/ThreadDump.png)

View File

@@ -0,0 +1,416 @@
---
title: Remote sync
description: Version control your dashboards, questions, and models with Git. Sync content between development and production instances automatically.
---
# Remote sync
{% include plans-blockquote.html feature="Remote sync" %}
## Overview
Remote Sync lets you develop analytics content in a development Metabase and automatically deploy it to a read-only production instance through Git.
You work with Remote Sync through special collections called "synced collections". Content in these collections is automatically versioned and can be pushed to or pulled from your Git repository directly from the Metabase UI.
### Key concepts
**Development and Production modes**: Remote Sync has two configuration modes that determine how a Metabase instance interacts with your Git repository:
- **Development mode**: For creating and editing content. You can push changes to Git, pull changes from others, create branches, and work on feature branches. Multiple Metabase instances can be in Development mode, each working on different branches.
- **Production mode**: For serving approved, read-only content to users. Production instances only pull changes from Git (typically from your main branch) and don't allow direct editing of synced content. You can set up auto-sync to automatically pull approved changes every five minutes.
**Synced collections**: Special collections that are tracked in Git. When you connect a Metabase instance in Development mode, it creates a "Library" collection by default. Everything inside a synced collection is versioned and synchronized with your Git repository.
**Serialized YAML files**: Remote Sync stores your Metabase content as YAML files in your Git repository. Each dashboard, question, model, and document is represented as a YAML file that can be reviewed in pull requests and versioned like code. For more details on the YAML format and command-line workflows, see [serialization](./serialization.md).
**Branch-based workflow**: In Development mode, you can create branches, switch between them, and commit changes—all from the Metabase UI. This enables feature-branch workflows where you develop on a branch, open a pull request for review, and merge to production.
### Why use Remote Sync?
Remote Sync is designed for teams that want to maintain a **read-only production environment** where analytics content is created by a centralized team and deployed through a controlled process.
- **Read-only production**: Users in production can view and use dashboards, but cannot create or edit content. All content creation happens in development.
- **Version control for new content**: Add new dashboards, questions, and models to production through Git, with full version history.
- **Peer review**: Use pull requests to review new content before it goes live in production.
- **Controlled deployment**: Choose when new content appears in production by controlling when you merge to your main branch.
### How Remote Sync works
Here's a basic remote-sync workflow:
1. Create a dashboard in a **Metabase configured in Development mode**.
2. Push it to a Git branch.
3. Open a pull request for review.
4. Merge the PR to production.
5. Your **Metabase configured in Production mode** automatically pulls in the changes.
We'll cover [setting up Remote Sync](#setting-up-remote-sync), an [example dev-to-production workflow](#an-example-dev-to-production-workflow), and [branch management](#branch-management) and some other odds and ends.
### Remote Sync vs. Serialization
Remote Sync uses the same underlying serialization format as the [Metabase CLI serialization feature](./serialization.md), but serves a different purpose:
- **Remote Sync**: Designed for adding new content to a read-only production environment through a Git-based workflow. Best when you want a centralized team creating content in development and deploying it to production automatically.
- **Serialization**: Command-line tool for exporting and importing Metabase content. Best for migrating existing content, complex multi-environment setups, and scenarios requiring full control over what gets exported and imported.
## Setting up Remote Sync
You'll need to be an admin to set up Remote Sync.
1. [Set up a repository to store your content](#1-set-up-a-repository-to-store-your-content)
2. [Create a personal access token for development](#2-create-a-personal-access-token-for-development)
3. [Understand Development and Production modes](#3-understand-development-and-production-modes)
4. [Connect your development Metabase to your repository](#4-connect-your-development-metabase-to-your-repository)
5. [Add an item to your synced collection](#5-add-an-item-to-your-synced-collection)
6. [Push your changes to your repository](#6-push-your-changes-to-your-repository)
7. [Create a personal access token for production](#7-create-a-personal-access-token-for-production)
8. [Connect your production Metabase to your repository](#8-connect-your-production-metabase-to-your-repository)
## 1. Set up a repository to store your content
Before you connect Metabase to your Git repository, create a [new GitHub repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository). Initialize the repo with a README.md.
## 2. Create a personal access token for development
GitHub offers two types of personal access tokens. We recommend the fine-grained token (not the classic) because you can limit their permissions to specific repositories.
1. Go to Settings > Developer settings > Personal access tokens > Fine-grained tokens.
2. Click "Generate new token".
3. Give it a descriptive name like "Metabase Remote Sync - Development".
4. Select the specific repository you want Metabase to access.
5. Add permissions:
- **Contents:** Read and write (it defaults to Read-only, so make sure to change this to Read and write for your development Metabase).
- **Metadata:** Read-only (required)
6. Click "Generate token" and copy it immediately (you won't see it again). Store it somewhere safe; you'll need to paste it into your Metabase.
For more, see GitHub's docs on [personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).
## 3. Understand Development and Production modes
Remote Sync has two modes: Development and Production.
**Development mode** is where you create and edit content. You can have multiple development instances for different teams, projects, or workflows. Each connects to the same repository but can work on different branches. Development mode has:
- **Bidirectional sync:** Push changes to Git and pull changes from others.
- **Full editing:** Create and modify dashboards, questions, and documents in the UI in your synced collection.
- **Branch management:** Create, switch between, and work on different branches.
**Production mode** is read-only and designed for your live environment. Production Metabases:
- **Pull changes only:** Automatically or manually pull approved content from Git.
- **Read-only content:** Users can view and use synced content but can't edit it.
- **Auto-sync option:** Automatically pull changes from your main branch every five minutes.
You can use any Metabase instance in Development mode. Metabase also offers [Development instances](./development-instance.md) for testing, which allow you to test with multiple users without paying per user account. You can use these Development instances in Remote Sync's Development mode (but not in Production mode, as they're intended for testing, not live production use).
## 4. Connect your development Metabase to your repository
1. Go to **Admin settings** > **Settings** > **Remote sync**.
2. Enter your repository URL:
- For example, `https://github.com/your-org/your-repo`. The repository must already exist and be initialized with at least one commit.
3. Select **Development mode**.
4. Add your access token:
- Paste the personal access token you created earlier. Make sure the token has [read and write permissions](#2-create-a-personal-access-token-for-development). Metabase encrypts your token before storing it.
5. Save and test the connection:
- Click "Save changes". Metabase will check whether it can reach your repository. If the connection fails, make sure your token has the appropriate permissions and hasn't expired. You may also have incorrectly copied and pasted the PAT, in which case you'll need to generate a new token.
## 5. Add an item to your synced collection
When you first connect in Development mode, Metabase automatically creates a special collection called "Library" that's synced with your Git repository. This is a **synced collection**—any content you add to it will be tracked in Git and can be pushed to your repository.
You can rename the Library collection if you want, and you can add sub-collections within it to organize your content.
1. (Optional) Create a new branch for your work:
- Click the branch dropdown in the synced collections section.
- Type a name for your new branch (e.g., `feature/my-dashboard`).
- Press Enter to create the branch.
This is useful if you want to work on changes without affecting the main branch. For more details, see [Branch management](#branch-management).
2. Navigate to the "Library" collection in your synced collections section (look for it in the left sidebar).
3. Create or move content into the Library collection:
- **Create new content:** Click "New" and choose a dashboard, question, or document. Save it to the Library collection.
- **Move existing content:** Drag and drop items from other collections into the Library collection, or use the move option in the item's menu.
[Items in synced collections can't depend on items outside of synced collections](#items-in-synced-collections-cant-depend-on-items-outside-of-the-synced-collection). For example, if you try to add a question that references a model, make sure the model is also in a synced collection.
## 6. Push your changes to your repository
Once you've added content, you'll see a yellow dot on your Library collection indicating uncommitted changes.
1. Click the up arrow (push) icon next to the Library collection in the left sidebar.
2. Enter a commit message describing your changes (e.g., "Added dashboard on mammoth populations").
3. Click "Continue" to commit and push your changes to your repository.
Check your repository—you should see the collection with your content in it.
## 7. Create a personal access token for production
Now that you have content in your repository, you can set up your production Metabase to pull that content.
[Create a personal access token](#2-create-a-personal-access-token-for-development) following the same steps as before, but add Contents permissions to the token that are **Read-only** (NOT write), as you only want your production Metabase reading from the repo. (Contents permissions require Metadata permissions, which GitHub will add automatically).
## 8. Connect your production Metabase to your repository
1. Go to **Admin settings** > **Settings** > **Remote sync**.
2. Enter your repository URL:
- Use the same repository as your development Metabase, for example, `https://github.com/your-org/your-repo.git`.
3. Select **Production mode**.
4. Add your access token:
- Paste the read-only personal access token you created for this production Metabase.
5. Save and test the connection:
- Click "Save changes". Metabase will verify it can reach your repository. If the connection fails, verify your token has the appropriate permissions and hasn't expired.
6. Pull changes and/or enable auto-sync (optional):
- Pull changes to sync from your repo.
- Toggle on "Auto-sync with Git" to automatically pull changes from your main branch every five minutes.
In Production mode, synced collections appear in the regular collections list with a special icon to indicate that they're versioned and read-only.
At this point, you should be all set up. Exit Admin settings, then reload your browser. You should see your synced Library collection in your production Metabase.
## An example dev-to-production workflow
Let's say your team wants to build a new analytics dashboard. Here's a workflow that ensures that all production content goes through a review process.
### Step 1: Create a new branch
In your development Metabase, click the branch dropdown in the synced collections section and [create a new branch](#branch-management) for your work, like `feature/megafauna-dashboard`.
### Step 2: Create content in your development Metabase
Create a dashboard called "Megafauna Analytics" and add some questions. The questions should be saved to the dashboard or to the synced collection. Save the dashboard to the synced collection.
### Step 3: Push to your development branch
1. You should see a yellow dot on your synced collection (indicating local changes).
2. Click the up arrow (push) icon next to your synced collection.
3. Enter a commit message: "Add Megafauna Analytics dashboard".
4. Metabase commits your changes to the branch you're working on and pushes them to your repo.
### Step 4: Create a pull request
In your Git repository:
1. Create a pull request from your branch, `feature/megafauna-dashboard`, to the main branch `main`.
2. Review the changes to the YAML files representing your dashboards and questions.
3. Someone who knows what they're doing approves and merges the PR.
### Step 5: Production automatically updates
On your production Metabase instance:
1. Within five minutes, the auto-sync process detects the new commits on `main` (you can also manually import the changes).
2. The "Megafauna Analytics" dashboard appears in production with all its questions.
3. The content is read-only for users (they can view and use it, but can't edit it).
## How your synced collection works in Development mode
Synced collections are special collections that are tracked in Git. Content in synced collections is versioned and can be pushed to or pulled from your repository.
- [Synced collections in the UI](#synced-collections-in-the-ui)
- [Moving and deleting content in synced collections](#moving-and-deleting-content-in-synced-collections)
- [Items in synced collections can't depend on items outside of the synced collection](#items-in-synced-collections-cant-depend-on-items-outside-of-the-synced-collection)
### Synced collections in the UI
When you first connect a Metabase to an initialized repository in Development mode, Metabase automatically creates a default synced collection called "Library". You can add items to that synced collection, including sub-collections.
In Development mode, your synced collection shows its current state with visual indicators:
- **Yellow dot:** You have unsynced local changes that need to be committed.
- **Up/down arrows:** Sync controls for pulling and pushing changes.
In Production mode, synced collections appear in the regular collections list (not in a separate "Synced Collections" section) with a special icon to indicate they're versioned and read-only.
### Moving and deleting content in synced collections
When you move content out of a synced collection, the UI may not immediately show the unpushed state. Refresh your browser to see the push indicator.
**Deletions sync to production:** When you remove content from a synced collection in Development mode and push that change, the content will also be removed from your Production instance when it syncs. This applies to moving content out of the synced collection or deleting it entirely.
Content in other Metabases that depended on this item may break since the dependency will no longer be in a synced collection.
### Items in synced collections can't depend on items outside of the synced collection
**Synced collections are self-contained.** Everything a dashboard or question needs must be inside the synced collection for Remote Sync to work properly. Metabase enforces these dependency constraints to ensure all content can be properly versioned and synced between instances.
**If it's not in the collection, it won't sync**—and that includes metadata. The one critical exception: table metadata (column types, descriptions, etc.) doesn't sync at all, even when questions that depend on it do sync. See [table metadata limitations](#important-table-metadata-limitations) for details.
For example:
- If a question references a model, both the question and the model must be in synced collections.
- If a dashboard includes questions, those questions must be saved to either the dashboard itself or to the synced collection.
- If a dashboard has click behaviors that link to other dashboards or questions, those linked items must be in synced collections.
- If a document contains @ mentions of other items (questions, dashboards, models, etc.), those mentioned items must be in synced collections.
Questions that depend on snippets can't be added to synced collections, as snippets aren't stored in collections and therefore can't be synced.
Items can reference other items in sub-collections that are also synced.
When you try to save an item with external dependencies to a synced collection, Metabase will show an error.
To resolve this:
1. Identify which items your content depends on.
2. Move those dependencies into synced collections first.
3. Then save your item to the synced collection.
Alternatively, you can modify your content to use a different source data that's already in synced collections.
## What Metabase syncs
Remote Sync uses the same serialization format as the [Metabase CLI serialization feature](./serialization.md), storing your content as YAML files in your Git repository.
**What syncs:**
- Dashboards and their cards
- Questions (saved queries and models)
- Model metadata (column descriptions, display settings, etc.)
- Documents
- Timelines and events
- Collection structure and metadata
**What doesn't sync:**
- Users, groups, and permissions
- Alerts and subscriptions
- Snippets
- Database connections
- Personal collections
- **Table metadata** (column types, descriptions, visibility settings, etc.)
### Important: Table metadata limitations
**Table metadata is not synced by Remote Sync.** This means any customizations you make to table metadata in your development instance—such as changing a column's display type from "Unix timestamp" to "Date", adding column descriptions, or adjusting visibility—will not automatically sync to production.
If your questions or dashboards rely on customized table metadata, you must manually apply the same metadata changes in your production instance. Otherwise, content that works in development may not work correctly in production.
**Why this matters:** If you have a question that displays a unixtime column as a date (because you changed the column type in development's table metadata), that question will sync to production, but the column will still appear as a unixtime in production unless you manually update the table metadata there as well.
For more details on the serialization format and command-line workflows, see the [serialization documentation](./serialization.md).
## Branch management
Branching is only available in Development mode.
### Creating a branch
You can create branches in Metabase or directly in your Git repository. Branches created in Git will appear in the Metabase branch dropdown once Metabase syncs with your repository.
We recommend pushing an initial commit to your main branch before creating branches. Creating a branch from an empty main branch can cause unexpected behavior.
To create a new branch in Metabase:
1. Click the branch dropdown in the synced collections section.
2. Type a name for the new branch in the search box.
3. Press Enter to create the branch.
The new branch starts from the current commit (not the latest remote).
### Switching branches
In the left sidebar under "SYNCED COLLECTIONS", you'll see a branch dropdown next to each synced collection name:
1. Click the branch dropdown to see available branches.
2. Select a different branch to switch to it.
If the branch doesn't appear, ensure it exists in your Git repository and that the name matches exactly (branch names are case-sensitive).
If you have unsynced changes, Metabase will show a dialog asking what you want to do:
- **Push changes to the current branch:** Commits your changes to the current branch before switching.
- **Create a new branch and push changes there:** Saves your work to a new branch, keeping the original branch clean.
- **Discard these changes:** Throws away your uncommitted changes (can't be undone).
The dialog shows you exactly which items have changed, so you can make an informed decision.
If you switch modes (from Development to Production or vice versa) with unpushed changes, you'll be prompted to save or discard them. You cannot switch to Production mode with uncommitted changes.
If changes don't appear after switching modes: Hard refresh your browser (Cmd/Ctrl + Shift + R).
## Deleting branches
Currently, you can only delete branches in GitHub or from the command line. Metabase will pick up the branch deletions on its next pull (though you may need to refresh your browser).
## Pushing changes to Git
You can only push changes in a Metabase with Remote sync set to Development mode.
### Committing your changes
When you make changes to items in a synced collection, a yellow dot appears on your synced collection (indicating uncommitted changes). To commit your changes:
1. Click the up arrow (push) icon next to the synced collection name in the left sidebar.
2. Enter a descriptive commit message explaining your changes.
3. Click "Continue" to push your changes to Git.
If you see "Remote is ahead of local", that means someone else pushed to the branch from another Metabase in Development mode. Pull the latest changes before pushing again.
## Pulling changes from Git
You can pull changes when in Development or Production mode.
In Development mode, you can get the latest changes from your Git repository:
1. Click the down arrow (pull) icon next to your synced collection in the left sidebar.
2. Review any summary of incoming changes if shown.
3. Confirm the import.
4. Metabase updates your collections with the latest content from Git.
If changes don't appear after pulling:
- Verify you're on the correct branch.
- Hard refresh your browser (Cmd/Ctrl + Shift + R).
- If you encounter sync errors, review error messages in the sync dialog, manually resolve conflicts in your Git repository, then pull again.
In Production mode, go to **Admin settings** > **Settings** > **Remote sync** and click **Pull changes**.
### Handling unsynced changes
If you have local uncommitted changes when trying to pull or switch branches, Metabase will prompt you with options:
- **Push changes to the current branch:** Commit your changes first, then proceed.
- **Create a new branch and push changes there:** Preserve your work on a new branch.
- **Discard these changes:** Throw away your uncommitted changes to accept what's in Git.
When in doubt, create a new branch and push changes to that branch. That way you won't lose any work.
### Pulling changes automatically
In Production mode, you can set Metabase to auto-sync changes from your main branch.
1. Navigate to **Admin settings** > **Settings** > **Remote sync**.
2. Enable Auto-sync with Git.
By default, Metabase will pull any changes (if any) from the branch you specify every five minutes. You can also manually sync as needed.
## If you already have a repo with serialized Metabase data
You can just keep doing what you're doing.
If you want to switch to this remote-sync setup, we still recommend you start with a new repo. In that case:
1. Check out a new branch in your Metabase instance in Development mode.
2. Import your data to your Metabase instance with the serialization command as you normally would.
3. Move the content you want to sync into the synced collection.
4. Push up your changes to the new repo.

View File

@@ -49,7 +49,7 @@ From the Azure Management console homepage, create a new resource. This time sea
![Azure PostgreSQL](images/AZDatabase.png)
In the next page you will have to select the way you will use the service. Choose **Single server** for now, which is a good starting point, but take into account that this will create just one instance of PostgreSQL that will be your single point of failure.
In the next page you will have to select the way you will use the service. Choose **Single server** for now, which is a good starting point, but consider that this will create just one instance of PostgreSQL that will be your single point of failure.
On the next screen, select or enter the following:
@@ -121,7 +121,7 @@ Return to the application configuration page and click on **Settings** -> **Conf
You'll need to add the [environment Variables](../configuring-metabase/environment-variables.md) for connecting Metabase to its [PostgreSQL Application Database](../installation-and-operation/configuring-application-database.md#postgresql). Make sure that you use the full **MB_DB_CONNECTION_URI**.
Also, take into account that the username in Azure PostgreSQL is `user@name_of_your_database_engine` so in this case the entire connection uri would be as follows:
Also, consider that the username in Azure PostgreSQL is `user@name_of_your_database_engine` so in this case the entire connection uri would be as follows:
```
postgresql://databasePrivateIPAddress:port/postgres?user=user@name_of_your_database_engine&password=configuredpassword&ssl=true&sslmode=required
@@ -182,7 +182,7 @@ In your Azure web app, visit **Settings** -> **Custom domains** to use a custom
Azure provides an easy way to increase the server's capacity by doing a Scale-up. Simply choose a pricing tier with more RAM and CPU count and restart the instance. This approach is easier than scaling out and you should choose this option first before scaling out.
For a highly-available Metabase deployment, you can tell your web app to scale-out (more servers serving the application in parallel). Simply go to Scale-out and use the slider to ask for more instances, or use a custom autoscaling policy (like using more servers during your work hours and fewer during off hours).
For a highly available Metabase deployment, you can tell your web app to scale-out (more servers serving the application in parallel). Simply go to Scale-out and use the slider to ask for more instances, or use a custom autoscaling policy (like using more servers during your work hours and fewer during off hours).
### CORS

View File

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

View File

@@ -9,7 +9,7 @@ redirect_from:
{% include plans-blockquote.html feature="Serialization" %}
Once you really get rolling with Metabase, it's often the case that you'll have more than one Metabase instance spun up. You might have a couple of testing or development instances and a few production ones, or maybe you have a separate Metabase per office or region.
Once you get rolling with Metabase, it's often the case that you'll have more than one Metabase instance spun up. You might have a couple of testing or development instances and a few production ones, or maybe you have a separate Metabase per office or region.
To help you out in situations like this, Metabase has a serialization feature which lets you create an _export_ of the contents of a Metabase that can then be _imported_ into one or more Metabases.

View File

@@ -14,7 +14,7 @@ This page covers how to upgrade to a new Metabase release.
## Upgrading Metabase Cloud
If you're on a [Metabase Cloud](https://www.metabase.com/pricing/) plan, we'll upgrade your Metabase automatically with each new release; no action needed on your end ([unless you're using the Embedded analytics SDK](#instances-using-the-embedded-analtyics-sdk-on-metabase-cloud-must-request-an-upgrade)).
If you're on a [Metabase Cloud](https://www.metabase.com/pricing/) plan, we'll upgrade your Metabase automatically with each new release; no action needed on your end ([unless you're using the Embedded analytics SDK](#instances-using-the-embedded-analytics-sdk-on-metabase-cloud-must-request-an-upgrade)).
How soon we upgrade you depends on the type of release:
@@ -23,7 +23,7 @@ How soon we upgrade you depends on the type of release:
Cloud customers can request an early upgrade by emailing support at help@metabase.com. Include the URL of the Metabase you want us to upgrade.
### Instances using the Embedded analtyics SDK on Metabase Cloud must request an upgrade
### Instances using the Embedded analytics SDK on Metabase Cloud must request an upgrade
If you're using the [Embedded analytics SDK](../embedding/sdk/introduction.md) on Metabase Cloud, we pin your version so that it doesn't upgrade automatically, as you should test the changes before upgrading.
@@ -144,7 +144,7 @@ Durning a **minor version upgrade** (e.g., 54.1 to 54.2), the new Metabase conta
In general, regular backups (especially backups before upgrading), are the best policy, so we recommend reverting to a backup of your application database to roll back an upgrade.
But if you've made any change (adding new questions/dashboards, etc) since upgrading that you want to keep, you may be able to use the `migrate down` command to roll back your Metabase application database to support the previous Metabase version you were running. When Metabase upgrades to a new version, it runs migrations that may change the application database schema. The `migrate down` command undoes those schema changes. In general, we recommend restoring from a backup (the backup that you definitely remembered to generate before upgrading), and only using the `migrate down` command if you really need to keep changes made after your upgrade.
But if you've made any change (adding new questions/dashboards, etc) since upgrading that you want to keep, you may be able to use the `migrate down` command to roll back your Metabase application database to support the previous Metabase version you were running. When Metabase upgrades to a new version, it runs migrations that may change the application database schema. The `migrate down` command undoes those schema changes. In general, we recommend restoring from a backup (the backup that you remembered to generate before upgrading), and only using the `migrate down` command if you need to keep changes made after your upgrade.
### Using the migrate down command

View File

@@ -11,7 +11,7 @@ redirect_from:
Integrating your SSO with Metabase allows you to:
- Provision a Metabase account when someone logs in to Metabase.
- Automatically pass user attributes from your SSO to Metabase in order to power [row and column security](../permissions/row-and-column-security.md).
- Automatically pass user attributes from your SSO to Metabase to power [row and column security](../permissions/row-and-column-security.md).
- Let people access Metabase without re-authenticating.
## Confirm the password for your Metabase admin account
@@ -82,7 +82,7 @@ Different IdPs use different names for the redirect URL. Here are some common ex
### User attributes
Metabase will automatically log in people who've been authenticated by your SAML identity provider. In order to do so, the first assertion returned in the identity provider's SAML response _must_ contain attributes for each person's first name, last name, and email.
Metabase will automatically log in people who've been authenticated by your SAML identity provider. To do so, the first assertion returned in the identity provider's SAML response _must_ contain attributes for each person's first name, last name, and email.
Most IdPs already include these assertions by default, but some (such as [Okta](./saml-okta.md)) must be configured to include them.
@@ -126,7 +126,7 @@ We recommend that you set this value to make your SAML configuration more secure
The SAML identity provider certificate is an encoded certificate that Metabase will use when connecting to the IdP URI. The certificate will look like a big blob of text that you'll want to copy and paste carefully — the spacing is important!
Your IdP might have you download this certificate as a file (usually `.cer` or `.pem`), which you'll then need to open up in a text editor in order to copy the contents to then paste into the box in Metabase.
Your IdP might have you download this certificate as a file (usually `.cer` or `.pem`), which you'll then need to open up in a text editor to copy the contents to then paste into the box in Metabase.
Note that your certificate text may include header and footer comments that look like `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----`. These comments should be included when pasting your certificate text into Metabase.

View File

@@ -38,9 +38,11 @@ Monitoring access sets permissions for the following:
## Subscriptions and alerts
This setting determines who can set up:
This setting determines who can create:
- [Dashboard subscriptions](../dashboards/subscriptions.md)
- [Alerts](../questions/alerts.md)
People will need to be in groups with either view or edit access to the collection that contains the dashboard or question in order to set up alerts. See [Collection permissions](../permissions/collections.md).
To prevent people from creating alerts and subscriptions, set the "Subscriptions and alerts" permission to "No".

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