Compare commits
350 Commits
attach-ren
...
docs-link-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e99ed1d4e | ||
|
|
72402e16cd | ||
|
|
998b28cddb | ||
|
|
7a83278718 | ||
|
|
89f12e7c01 | ||
|
|
e2670a1567 | ||
|
|
ecce383824 | ||
|
|
0637fefa67 | ||
|
|
74b2c11ea5 | ||
|
|
ce48b30e16 | ||
|
|
fa192d940b | ||
|
|
dbaddac9cb | ||
|
|
0b9bfbd21d | ||
|
|
bd6391cef0 | ||
|
|
27fc6ae43e | ||
|
|
2c04840477 | ||
|
|
3565d5e2b8 | ||
|
|
db3b8979c5 | ||
|
|
0e8787805f | ||
|
|
c966918bda | ||
|
|
1dceed32b8 | ||
|
|
514564290f | ||
|
|
cb055ac9de | ||
|
|
7f9e369c34 | ||
|
|
08c841f3ef | ||
|
|
d0096dc0fa | ||
|
|
dce9879067 | ||
|
|
442cedd5b9 | ||
|
|
105a72a008 | ||
|
|
05417a3a6c | ||
|
|
b3749f8fe5 | ||
|
|
79c8e9bd82 | ||
|
|
4a03070a9b | ||
|
|
7e7414e86e | ||
|
|
dab2d85277 | ||
|
|
992b2e899f | ||
|
|
488e08a7dd | ||
|
|
5638d79768 | ||
|
|
0081f202bc | ||
|
|
e5c14e16ae | ||
|
|
523ea2488b | ||
|
|
08613cb3b6 | ||
|
|
c006657dce | ||
|
|
3f788bbaf2 | ||
|
|
bbde99dd31 | ||
|
|
80c34c673d | ||
|
|
89bdaa2fa8 | ||
|
|
301ab32cef | ||
|
|
737c24af95 | ||
|
|
870dcd6c4a | ||
|
|
fa32093271 | ||
|
|
4f53b0b9a9 | ||
|
|
3ccf4d411c | ||
|
|
891260cb57 | ||
|
|
863bc82af1 | ||
|
|
6f5c43d358 | ||
|
|
0a550944f6 | ||
|
|
9e4cbda477 | ||
|
|
f0db81fccd | ||
|
|
5efb56c065 | ||
|
|
c643f094f1 | ||
|
|
c17bb33f0e | ||
|
|
400a1a2a10 | ||
|
|
f284a522e3 | ||
|
|
b41a5e840f | ||
|
|
0e9076c0ff | ||
|
|
6daecbc66b | ||
|
|
613318f786 | ||
|
|
35f97092e0 | ||
|
|
ce95331f30 | ||
|
|
7de0faa635 | ||
|
|
37abc08449 | ||
|
|
6622470420 | ||
|
|
4f6bf67629 | ||
|
|
cc17b9e88e | ||
|
|
1b78f5a361 | ||
|
|
bdbaee5a2a | ||
|
|
d6873e86d5 | ||
|
|
413efacef5 | ||
|
|
bc78552d5f | ||
|
|
cb9fac1ddd | ||
|
|
191572d90f | ||
|
|
9c18d099ce | ||
|
|
844188a97e | ||
|
|
4ab0cfca9c | ||
|
|
8cb98be8af | ||
|
|
f57be777d4 | ||
|
|
4d907fe8fb | ||
|
|
62e8739fed | ||
|
|
337dbbe074 | ||
|
|
1c83904ee2 | ||
|
|
7f19247f7f | ||
|
|
ea9dfd1d2b | ||
|
|
66a189f77f | ||
|
|
f8298e49e2 | ||
|
|
01db0a2a70 | ||
|
|
a0dfc99c41 | ||
|
|
a72afa4751 | ||
|
|
5fd247c5a1 | ||
|
|
fdc0b71512 | ||
|
|
13c71cd054 | ||
|
|
93334133ea | ||
|
|
aac751c212 | ||
|
|
9a68f25867 | ||
|
|
9ac932ae16 | ||
|
|
74e73d2b6a | ||
|
|
dd1eb6cb4d | ||
|
|
27e1ff6452 | ||
|
|
6d87ed281e | ||
|
|
7d2112e697 | ||
|
|
f702aee6a0 | ||
|
|
8c416bd9ab | ||
|
|
dd00df1a06 | ||
|
|
0e8469f4b0 | ||
|
|
e1ade5c665 | ||
|
|
e677eb7ad2 | ||
|
|
012a763522 | ||
|
|
d7a1e86798 | ||
|
|
4bbc3163e2 | ||
|
|
c769688711 | ||
|
|
5258ec54f8 | ||
|
|
4f25a4720b | ||
|
|
1bfcdf8c90 | ||
|
|
7854e07a62 | ||
|
|
81a586df95 | ||
|
|
884901f20a | ||
|
|
9decd3e8ed | ||
|
|
62123c073e | ||
|
|
a8d5ea6437 | ||
|
|
a95ff7f595 | ||
|
|
e33acdc6b6 | ||
|
|
1088baf011 | ||
|
|
ba182e1745 | ||
|
|
458fbf9efb | ||
|
|
4772b5e249 | ||
|
|
04a08d3304 | ||
|
|
2e94093025 | ||
|
|
d971a83601 | ||
|
|
16599b223e | ||
|
|
c7bf7d1def | ||
|
|
d843973a8e | ||
|
|
c7e46dc961 | ||
|
|
ee38f0e449 | ||
|
|
6e87cb9306 | ||
|
|
68bd9781ae | ||
|
|
c5ef3fe772 | ||
|
|
ffbad1d6ae | ||
|
|
3afe4821a0 | ||
|
|
8824bd9a19 | ||
|
|
e2144d140d | ||
|
|
837beda619 | ||
|
|
eb9bb2dad7 | ||
|
|
6240dee136 | ||
|
|
bab6387cdf | ||
|
|
44cfdf48e2 | ||
|
|
0cce65e2cb | ||
|
|
edcd2ff7c9 | ||
|
|
fa8c7a2361 | ||
|
|
d638e94971 | ||
|
|
d7bd5603bc | ||
|
|
acd7c31f22 | ||
|
|
cbda131e84 | ||
|
|
121054b293 | ||
|
|
fad00d4346 | ||
|
|
084dd3b2ae | ||
|
|
937e3daac1 | ||
|
|
01e9387f62 | ||
|
|
14db7aeeac | ||
|
|
f7502d96e7 | ||
|
|
bae0aedf2c | ||
|
|
ae2c960913 | ||
|
|
febfe4a5aa | ||
|
|
9ebb679f6d | ||
|
|
ce5d2547e7 | ||
|
|
6c1458ff2f | ||
|
|
8af1555502 | ||
|
|
7b849da346 | ||
|
|
7374e61ed7 | ||
|
|
a742b3408b | ||
|
|
d876627b24 | ||
|
|
64f82436ef | ||
|
|
28fc332064 | ||
|
|
6ec9de852e | ||
|
|
eebf4b5239 | ||
|
|
c0a804bfe6 | ||
|
|
40ef144430 | ||
|
|
6113998662 | ||
|
|
ddb6299993 | ||
|
|
459429985c | ||
|
|
a46b9d7fc2 | ||
|
|
e8fedf0164 | ||
|
|
8936df34fb | ||
|
|
80d33f6869 | ||
|
|
c62003fff3 | ||
|
|
f530b0fd31 | ||
|
|
f971c42ada | ||
|
|
be9740ca70 | ||
|
|
dc4614151c | ||
|
|
84fd549fff | ||
|
|
a2f3d74950 | ||
|
|
121fe66f67 | ||
|
|
a297e9a6ad | ||
|
|
8609c02bb6 | ||
|
|
46215d51fc | ||
|
|
752749f79e | ||
|
|
5fc87983ff | ||
|
|
b6dea77ab0 | ||
|
|
f106ffa776 | ||
|
|
2cf666d9af | ||
|
|
67fec430a5 | ||
|
|
7046fef3c4 | ||
|
|
88734ca33c | ||
|
|
897a22f298 | ||
|
|
35b8b8b814 | ||
|
|
8f399a1b3e | ||
|
|
7b919f8b27 | ||
|
|
51098a6cfa | ||
|
|
c93403e98f | ||
|
|
92242d99b0 | ||
|
|
7f4fd36b4e | ||
|
|
522b0df40a | ||
|
|
85ba3ac755 | ||
|
|
f54fd3b1b6 | ||
|
|
6dff2dfe7e | ||
|
|
74500ba310 | ||
|
|
4e81aed3fb | ||
|
|
f307977168 | ||
|
|
1d904a7eff | ||
|
|
9e191a48e6 | ||
|
|
95adc26b34 | ||
|
|
1b164bf49d | ||
|
|
2cb5dd1919 | ||
|
|
19e92f3ee0 | ||
|
|
bbde8ff568 | ||
|
|
e34d653777 | ||
|
|
296636e5a6 | ||
|
|
9f27f3775f | ||
|
|
dfdaab03b3 | ||
|
|
e13c64ec2c | ||
|
|
905625eb5a | ||
|
|
40d11066a9 | ||
|
|
33df115357 | ||
|
|
2b01d9fd3c | ||
|
|
4520bf9324 | ||
|
|
0d4c0e7850 | ||
|
|
ceeac2912c | ||
|
|
dd30ead9a8 | ||
|
|
3c97497126 | ||
|
|
25c4cb0bd8 | ||
|
|
f54e3d5a76 | ||
|
|
486e3370af | ||
|
|
1e50d9f3a8 | ||
|
|
e3f166bf7b | ||
|
|
6d0f5e69d6 | ||
|
|
c7048cf89e | ||
|
|
49b126efcd | ||
|
|
2473fa2f8b | ||
|
|
ea2d0a7e03 | ||
|
|
8cb8d6405d | ||
|
|
df62bb0cb4 | ||
|
|
e199d76e6f | ||
|
|
4a88a0c86a | ||
|
|
2cdae6bc9a | ||
|
|
7a9767e110 | ||
|
|
3d1cbd3b8e | ||
|
|
8eeacc60c4 | ||
|
|
b8907454c9 | ||
|
|
60bb8d6158 | ||
|
|
5a481f98b8 | ||
|
|
18d5388de0 | ||
|
|
080efbc837 | ||
|
|
b9c10c5178 | ||
|
|
2bfaab28e6 | ||
|
|
56b3b5054f | ||
|
|
3164995660 | ||
|
|
13e51d4ecc | ||
|
|
74e524c057 | ||
|
|
18581104b9 | ||
|
|
01840901fe | ||
|
|
4b66bdbabc | ||
|
|
b87281c531 | ||
|
|
855c840bc2 | ||
|
|
49360f68bf | ||
|
|
54d9fb2257 | ||
|
|
ac6bb7b452 | ||
|
|
e430b776e3 | ||
|
|
0ade074b53 | ||
|
|
7789ce34bf | ||
|
|
6fcbf23e54 | ||
|
|
6ac4fe977f | ||
|
|
5bf50a2131 | ||
|
|
c7c5b3568b | ||
|
|
13aae6632d | ||
|
|
f05fa8e607 | ||
|
|
937e30fbed | ||
|
|
8659846f0b | ||
|
|
50e4cf7798 | ||
|
|
2a260cc9ff | ||
|
|
f61a065796 | ||
|
|
5c5f6c39a1 | ||
|
|
a691754a94 | ||
|
|
7251aa834c | ||
|
|
f28991450a | ||
|
|
f025758d8f | ||
|
|
0fb138af86 | ||
|
|
4ec415a024 | ||
|
|
7c636450c2 | ||
|
|
b561b0111c | ||
|
|
44fb3171f4 | ||
|
|
1e4fe0f1b8 | ||
|
|
03d60d8fed | ||
|
|
b97d9791ec | ||
|
|
75fbccb765 | ||
|
|
68938adb0c | ||
|
|
fa0cf11b25 | ||
|
|
590be77299 | ||
|
|
ce5b1cfe2f | ||
|
|
384af8167e | ||
|
|
5b5b05973e | ||
|
|
9d61985fcc | ||
|
|
7d0357d983 | ||
|
|
a727faddda | ||
|
|
d9aaa9fd43 | ||
|
|
cefd7a61e8 | ||
|
|
c5404ea285 | ||
|
|
8b6a4c966e | ||
|
|
91b4bd6b34 | ||
|
|
d53b0a7a80 | ||
|
|
fea8f89a57 | ||
|
|
ecad0c94b5 | ||
|
|
237a663b3a | ||
|
|
0da1dd1662 | ||
|
|
6763b13cfc | ||
|
|
816e1b0dbc | ||
|
|
3305c815b0 | ||
|
|
2f0bc49783 | ||
|
|
85e113420d | ||
|
|
95d4179e28 | ||
|
|
9c7e96a857 | ||
|
|
9f73b0ceb8 | ||
|
|
12e25b65a1 | ||
|
|
3206c87a61 | ||
|
|
4c2aed648f | ||
|
|
f10ab55f8a | ||
|
|
97fe4c437c | ||
|
|
34b6159658 | ||
|
|
cb4264c6b3 | ||
|
|
5c8de49521 | ||
|
|
6bf7bfca9a | ||
|
|
d228123152 |
@@ -107,6 +107,7 @@
|
||||
malli.core/explainer {:message "Use metabase.util.malli.registry/explainer instead of malli.core/explainer"}
|
||||
me.flowthing.pp/pprint {:message "Use metabase.util.log instead of me.flowthing.pp/pprint"}
|
||||
medley.core/random-uuid {:message "Use clojure.core/random-uuid instead of medley.core/random-uuid"}
|
||||
metabase.driver/database-supports? {:message "Use metabase.driver.util/supports? instead of metabase.driver/database-supports?"}
|
||||
metabase.lib.equality/find-column-indexes-for-refs {:message "Use lib.equality/closest-matches-in-metadata or lib.equality/find-closest-matches-for-refs instead of lib.equality/find-column-indexes-for-refs"}
|
||||
metabase.test/with-temp* {:message "Use mt/with-temp instead of mt/with-temp*"}
|
||||
toucan2.tools.with-temp {:message "Use mt/with-temp instead of t2.with-temp/with-temp"}}
|
||||
@@ -135,7 +136,7 @@
|
||||
;; namespace(s). This is mostly a temporary placeholder until we go in and create module namespaces, which means
|
||||
;; you should go create one.
|
||||
;;
|
||||
;; 2. A set of namespace symbols. All namespaces in other modules will only be allowed ;; to use namespaces from
|
||||
;; 2. A set of namespace symbols. All namespaces in other modules will only be allowed to use namespaces from
|
||||
;; this set. Ideally this set should only have one namespace, but restricting it to a set of several is still
|
||||
;; better than `:any`.
|
||||
;;
|
||||
@@ -158,8 +159,10 @@
|
||||
metabase.async #{metabase.async.streaming-response
|
||||
metabase.async.streaming-response.thread-pool
|
||||
metabase.async.util} ; TODO -- consolidate these into a real API namespace.
|
||||
metabase.audit #{metabase.audit}
|
||||
metabase.bootstrap #{metabase.bootstrap}
|
||||
metabase.cmd #{} ; there are no namespaces here since you shouldn't be using this in any other module.
|
||||
metabase.channel #{metabase.channel.core}
|
||||
metabase.config #{metabase.config}
|
||||
metabase.core #{metabase.core.initialization-status} ; TODO -- only namespace used outside of EE, this probably belongs in `metabase.server` anyway since that's the only place it's used.
|
||||
metabase.db #{metabase.db
|
||||
@@ -259,9 +262,11 @@
|
||||
metabase.analyze :any
|
||||
metabase.api :any
|
||||
metabase.async :any
|
||||
metabase.audit :any
|
||||
metabase.bootstrap #{}
|
||||
metabase.cmd :any
|
||||
metabase.compatibility :any
|
||||
metabase.channel :any
|
||||
metabase.config #{metabase.plugins}
|
||||
metabase.core :any
|
||||
metabase.db :any
|
||||
@@ -278,7 +283,12 @@
|
||||
metabase.metabot :any
|
||||
metabase.models :any
|
||||
metabase.moderation :any
|
||||
metabase.native-query-analyzer :any
|
||||
metabase.native-query-analyzer #{metabase.config
|
||||
metabase.driver
|
||||
metabase.lib
|
||||
metabase.public-settings
|
||||
metabase.query-processor
|
||||
metabase.util}
|
||||
metabase.permissions :any
|
||||
metabase.plugins :any
|
||||
metabase.public-settings :any
|
||||
@@ -409,6 +419,7 @@
|
||||
metabase.api.user api.user
|
||||
metabase.api.util api.util
|
||||
metabase.async.streaming-response.thread-pool thread-pool
|
||||
metabase.channel.core channel
|
||||
metabase.cmd.copy.h2 copy.h2
|
||||
metabase.config config
|
||||
metabase.config.file config.file
|
||||
@@ -835,7 +846,11 @@
|
||||
;; `metabase.driver.*`, excluding `-test` namespaces.
|
||||
;;
|
||||
{:pattern "metabase(?:(?:(?:-enterprise\\.sandbox)?\\.query-processor\\.)|(?:\\.driver\\.)).*(?<!-test)$"
|
||||
:name qp-and-driver-source-namespaces}]
|
||||
:name qp-and-driver-source-namespaces}
|
||||
|
||||
;; driver namespaces
|
||||
{:pattern "metabase\\.driver.*$"
|
||||
:name driver-namespaces}]
|
||||
|
||||
:config-in-ns
|
||||
{test-namespaces
|
||||
@@ -843,7 +858,9 @@
|
||||
{:inline-def {:level :off}
|
||||
:missing-docstring {:level :off}
|
||||
:private-call {:level :off}
|
||||
:metabase/defsetting-must-specify-export {:level :off}}
|
||||
:metabase/defsetting-must-specify-export {:level :off}
|
||||
:discouraged-var {metabase.driver/database-supports? {:level :off}}}
|
||||
|
||||
:hooks
|
||||
{:analyze-call
|
||||
{clojure.core/defmacro hooks.clojure.core/non-thread-safe-form-should-end-with-exclamation
|
||||
@@ -893,6 +910,11 @@
|
||||
toucan.util.test {:message "Don't use application database inside MLv2 code"}
|
||||
toucan2.core {:message "Don't use application database inside MLv2 code"}}}}
|
||||
|
||||
driver-namespaces
|
||||
{:linters
|
||||
{:discouraged-var
|
||||
{metabase.driver/database-supports? {:level :off}}}}
|
||||
|
||||
qp-and-driver-source-namespaces
|
||||
{:linters
|
||||
{:discouraged-namespace
|
||||
|
||||
@@ -189,7 +189,13 @@ module.exports = {
|
||||
"@typescript-eslint/no-inferrable-types": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-this-alias": "off",
|
||||
"@typescript-eslint/consistent-type-imports": "error",
|
||||
"@typescript-eslint/consistent-type-imports": [
|
||||
"error",
|
||||
{
|
||||
fixStyle: "inline-type-imports",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-import-type-side-effects": "error",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
|
||||
2
.github/actions/prepare-cypress/action.yml
vendored
@@ -5,7 +5,7 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Install Replay.io browser
|
||||
run: npx @replayio/cypress install
|
||||
run: npx replayio install
|
||||
shell: bash
|
||||
|
||||
- name: Check to see if dependencies should be cached
|
||||
|
||||
5
.github/actions/prepare-frontend/action.yml
vendored
@@ -1,10 +1,15 @@
|
||||
name: Prepare front-end environment
|
||||
inputs:
|
||||
node-version:
|
||||
description: "The version of Node.js to use, overriding .nvmrc"
|
||||
required: false
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Prepare Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ inputs.node-version }} # this overrides, if present
|
||||
node-version-file: ".nvmrc"
|
||||
- name: Check to see if dependencies should be cached
|
||||
if: ${{ contains(github.event.head_commit.message, '[ci nocache]') }}
|
||||
|
||||
5
.github/file-paths.yaml
vendored
@@ -43,6 +43,11 @@ frontend_all: &frontend_all
|
||||
- *frontend_sources
|
||||
- *frontend_specs
|
||||
|
||||
frontend_loki_ci: &frontend_loki_ci
|
||||
- ".github/workflows/loki.yml"
|
||||
- ".loki/**"
|
||||
- ".storybook/**"
|
||||
|
||||
backend_ci: &backend_ci
|
||||
- ".github/actions/prepare-frontend/**"
|
||||
- ".github/actions/prepare-backend/**"
|
||||
|
||||
8
.github/team.json
vendored
@@ -41,7 +41,6 @@
|
||||
"members": [
|
||||
"noahmoss",
|
||||
"escherize",
|
||||
"iethree",
|
||||
"npfitz",
|
||||
"johnswanson",
|
||||
"rafpaf",
|
||||
@@ -58,6 +57,13 @@
|
||||
"kulyk",
|
||||
"adam-james-v"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DevEx",
|
||||
"label": ".Team/DevEx",
|
||||
"members": [
|
||||
"iethree"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2
.github/workflows/auto-backport.yml
vendored
@@ -92,7 +92,7 @@ jobs:
|
||||
if: ${{ steps.create_backport_pull_request.outputs.has-conflicts == 'false' }}
|
||||
uses: peter-evans/enable-pull-request-automerge@v2
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
pull-request-number: ${{ steps.create_backport_pull_request.outputs.backport_pr_number }}
|
||||
merge-method: squash
|
||||
|
||||
|
||||
27
.github/workflows/backend-cloverage.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Backend-Cloverage
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 10 * * 1-5' # every weekday at 5am US eastern time
|
||||
|
||||
jobs:
|
||||
be-linter-cloverage:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: "cloverage"
|
||||
- name: Build static viz frontend
|
||||
run: yarn build-static-viz
|
||||
- name: Collect the test coverage
|
||||
run: clojure -X:dev:ci:ee:ee-dev:test:cloverage
|
||||
- name: Upload coverage to codecov.io
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./target/coverage/codecov.json
|
||||
flags: back-end
|
||||
23
.github/workflows/backend.yml
vendored
@@ -63,29 +63,6 @@ jobs:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/static-viz-sources.yaml
|
||||
|
||||
be-linter-cloverage:
|
||||
needs: files-changed
|
||||
if: (github.ref_name == 'master' && needs.files-changed.outputs.backend_all == 'true')
|
||||
|| contains(github.event.pull_request.labels.*.name, 'run-cloverage')
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: "cloverage"
|
||||
- name: Build static viz frontend
|
||||
run: yarn build-static-viz
|
||||
- name: Collect the test coverage
|
||||
run: clojure -X:dev:ci:ee:ee-dev:test:cloverage
|
||||
- name: Upload coverage to codecov.io
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./target/coverage/codecov.json
|
||||
flags: back-end
|
||||
|
||||
be-linter-clj-kondo:
|
||||
needs: [files-changed, static-viz-files-changed]
|
||||
if: |
|
||||
|
||||
11
.github/workflows/build-for-release.yml
vendored
@@ -17,28 +17,29 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Send build start message
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
SLACK_RELEASE_CHANNEL: ${{ vars.SLACK_RELEASE_CHANNEL }}
|
||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
with:
|
||||
script: | # js
|
||||
const { sendReleaseMessage } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const { sendPreReleaseMessage } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
await sendReleaseMessage({
|
||||
stage: 'build-start',
|
||||
await sendPreReleaseMessage({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: '${{ inputs.version }}',
|
||||
runId: '${{ github.run_id }}',
|
||||
releaseSha: '${{ inputs.commit }}',
|
||||
userName: '${{ github.actor }}',
|
||||
channelName: '${{ vars.SLACK_RELEASE_CHANNEL }}',
|
||||
}).catch(console.error);
|
||||
|
||||
check-version:
|
||||
|
||||
81
.github/workflows/check-milestone.yml
vendored
@@ -1,80 +1,41 @@
|
||||
name: Milestone Reminder
|
||||
name: Automatically set milestone
|
||||
run-name: Set milestone for ${{ github.event.head_commit.message }}
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- release-x.**
|
||||
|
||||
jobs:
|
||||
milestone-reminder:
|
||||
if: github.event.pull_request.merged == true
|
||||
name: Remind to set milestone
|
||||
set-milestone:
|
||||
name: Automatically set milestone
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: read
|
||||
issues: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
ref: master # we want the logic from master, even though we're triggering on a release branch
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const { setMilestoneForCommits } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
|
||||
const pullNumber = '${{ github.event.pull_request.number }}';
|
||||
const branchName = '${{ github.ref }}';
|
||||
const commitMessage = '${{ github.event.head_commit.message }}';
|
||||
|
||||
// the github API doesn't expose linked issues, so we have to parse the body ourselves
|
||||
function getLinkedIssueId(pull) {
|
||||
// https://regexr.com/7sk94
|
||||
const match = pull.data.body.match(/(close(s|d)?|fixe?(s|d)?|resolve(s|d)?) (#|https?:\/\/github.com\/.+\/issues\/)(\d+)/i);
|
||||
return match && match?.[2];
|
||||
}
|
||||
|
||||
function getMilestone(pullOrIssue) {
|
||||
// pull has pull.data.milestone, issue has issue.milestone
|
||||
return pullOrIssue?.data?.milestone || pullOrIssue?.milestone;
|
||||
}
|
||||
|
||||
const pull = await github.rest.pulls.get({
|
||||
await setMilestoneForCommits({
|
||||
github,
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pullNumber,
|
||||
});
|
||||
|
||||
if (getMilestone(pull)) {
|
||||
console.log("Pull request has milestone", pull.data.milestone?.title);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const issueId = getLinkedIssueId(pull);
|
||||
|
||||
if (issueId) {
|
||||
console.log('linked issue found', issueId);
|
||||
|
||||
const issue = await github.rest.issues.get({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueId,
|
||||
});
|
||||
|
||||
const milestone = getMilestone(issue);
|
||||
|
||||
if (milestone) {
|
||||
console.log("Linked issue has milestone", milestone.title);
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("No milestone found");
|
||||
|
||||
const author = pull.data.user.login;
|
||||
const guideLink = "https://www.notion.so/metabase/Metabase-Branching-Strategy-6eb577d5f61142aa960a626d6bbdfeb3?pvs=4#3dea255ffa3b4f74942a227844e889fa";
|
||||
const message = `@${author} Did you forget to add a milestone to the issue for this PR? _[When and where should I add a milestone?](${guideLink})_`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pullNumber,
|
||||
body: message,
|
||||
branchName,
|
||||
commitMessages: [commitMessage],
|
||||
});
|
||||
|
||||
57
.github/workflows/conventional-commit-pr-title-reminder.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: Conventional commit PR Title Reminder
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- enterprise/frontend/src/embedding-sdk/**
|
||||
|
||||
jobs:
|
||||
pr-title-reminder:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Check if the PR title is already following Conventional Commits style
|
||||
uses: actions/github-script@v7
|
||||
id: is-conventional-commit
|
||||
with:
|
||||
result-encoding: string
|
||||
script: | # js
|
||||
const pullRequestTitle = context.payload.pull_request.title
|
||||
const conventionalCommitRegex = /^(?<type>\w+)\((?<scope>\w+)\):/
|
||||
const match = pullRequestTitle.match(conventionalCommitRegex)
|
||||
if (match) {
|
||||
const { type, scope } = match.groups
|
||||
return ['feat', 'fix', 'perf', 'docs', 'style', 'refactor', 'test', 'build', 'ci'].includes(type) && scope === 'sdk'
|
||||
}
|
||||
|
||||
- name: Checkout repository so `gh` CLI works
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Remind PR authors to use conventional commit in the title
|
||||
if: ${{ steps.is-conventional-commit.outputs.result != 'true' }}
|
||||
run: |
|
||||
comment='@${{ github.event.pull_request.user.login }} You have modified embedding SDK code. Please make sure the PR title follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) style.
|
||||
|
||||
Here are all the supported types that will be shown in the changelog:
|
||||
- `feat`
|
||||
- `fix`
|
||||
- `perf`
|
||||
|
||||
These types `docs`, `style`, `refactor`, `test`, `build`, and `ci` are also encouraged for non-changelog related tasks.
|
||||
|
||||
Please also make sure to include `sdk` scope, otherwise, the changelog will not include this task.
|
||||
|
||||
For example, these are valid PR titles:
|
||||
- `feat(sdk): Add interactive dashboard component`
|
||||
- `feat(sdk): Support theming pie chart`
|
||||
- `fix(sdk): Fix static dashboard crash`'
|
||||
|
||||
gh pr comment -b "$comment" --edit-last || gh pr comment -b "$comment"
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
3
.github/workflows/drivers.yml
vendored
@@ -40,6 +40,9 @@ jobs:
|
||||
MB_ATHENA_TEST_ACCESS_KEY: ${{ secrets.MB_ATHENA_TEST_ACCESS_KEY }}
|
||||
MB_ATHENA_TEST_SECRET_KEY: ${{ secrets.MB_ATHENA_TEST_SECRET_KEY }}
|
||||
MB_ATHENA_TEST_S3_STAGING_DIR: ${{ secrets.MB_ATHENA_TEST_S3_STAGING_DIR }}
|
||||
# These credentials are used to test the driver when the user does not have the athena:GetTableMetadata permission
|
||||
MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_ACCESS_KEY: ${{ secrets.MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_ACCESS_KEY }}
|
||||
MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_SECRET_KEY: ${{ secrets.MB_ATHENA_TEST_WITHOUT_GET_TABLE_METADATA_SECRET_KEY }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test Athena driver
|
||||
|
||||
36
.github/workflows/e2e-tests.yml
vendored
@@ -39,8 +39,39 @@ jobs:
|
||||
id: e2e-matrix
|
||||
uses: ./.github/actions/build-e2e-matrix
|
||||
|
||||
# if this is a test on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
if: |
|
||||
!cancelled() &&
|
||||
contains(github.ref, 'release-x')
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
|
||||
node_version: ${{ fromJson(steps.dependencies.outputs.result).node_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get build dependencies
|
||||
uses: actions/github-script@v7
|
||||
id: dependencies
|
||||
with:
|
||||
script: | # js
|
||||
const { getBuildRequirements, getVersionFromReleaseBranch } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
const version = getVersionFromReleaseBranch('${{ github.ref }}');
|
||||
const requirements = getBuildRequirements(version);
|
||||
|
||||
return {
|
||||
java_version: requirements.java,
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
build:
|
||||
needs: [files-changed, e2e-matrix-builder]
|
||||
needs: [files-changed, e2e-matrix-builder, get-build-requirements]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
github.event.pull_request.draft == false &&
|
||||
@@ -58,10 +89,13 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
with:
|
||||
node-version: '${{ needs.get-build-requirements.outputs.node_version }}'
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: e2e-tests
|
||||
java-version: '${{ needs.get-build-requirements.outputs.java_version || 11 }}'
|
||||
|
||||
- name: Build uberjar with ./bin/build.sh
|
||||
run: ./bin/build.sh
|
||||
|
||||
28
.github/workflows/external-pr-label.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Mark External PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
on-pr-opened:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 1
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'External') }}
|
||||
steps:
|
||||
- uses: tspascoal/get-user-teams-membership@v3
|
||||
id: checkUserMember
|
||||
with:
|
||||
username: ${{ github.actor }}
|
||||
organization: 'metabase'
|
||||
team: 'employees'
|
||||
GITHUB_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }} # Token with read:org scope
|
||||
|
||||
- name: add labels
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
if: ${{ steps.checkUserMember.outputs.isTeamMember == 'false' }}
|
||||
with:
|
||||
labels: |
|
||||
External
|
||||
4
.github/workflows/loki-update.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
ref: ${{ github.head_ref }}
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: Remove 'loki-update' label
|
||||
uses: actions/github-script@v3
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{secrets.METABASE_AUTOMATION_USER_TOKEN}}
|
||||
script: |
|
||||
|
||||
21
.github/workflows/loki.yml
vendored
@@ -3,7 +3,26 @@ name: Loki Visual Regression Testing
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
frontend_ci: ${{ steps.changes.outputs.frontend_ci }}
|
||||
frontend_sources: ${{ steps.changes.outputs.frontend_sources }}
|
||||
frontend_loki_ci: ${{ steps.changes.outputs.frontend_loki_ci }}
|
||||
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
|
||||
|
||||
visual-test:
|
||||
needs: files-changed
|
||||
if: needs.files-changed.outputs.frontend_ci == 'true' || needs.files-changed.outputs.frontend_sources == 'true' || needs.files-changed.outputs.frontend_loki_ci == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
docker:
|
||||
@@ -19,7 +38,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare frontend environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
|
||||
59
.github/workflows/pre-release.yml
vendored
@@ -110,11 +110,10 @@ jobs:
|
||||
run-sanity-check:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
needs: [release-artifact, check-uberjar-health]
|
||||
needs: [release-artifact]
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [oss, ee]
|
||||
folder: [onboarding, search]
|
||||
env:
|
||||
MB_EDITION: ${{ matrix.edition }}
|
||||
DISPLAY: ""
|
||||
@@ -127,20 +126,17 @@ jobs:
|
||||
MB_SNOWPLOW_AVAILABLE: true
|
||||
MB_SNOWPLOW_URL: "http://localhost:9090" # Snowplow micro
|
||||
TERM: xterm
|
||||
services:
|
||||
maildev:
|
||||
image: maildev/maildev:2.0.5
|
||||
ports:
|
||||
- "1080:1080"
|
||||
- "1025:1025"
|
||||
credentials:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.release-artifact.outputs.commit }}
|
||||
- name: Prepare Docker containers
|
||||
uses: ./.github/actions/e2e-prepare-containers
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
maildev: true
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Prepare JDK 11
|
||||
@@ -163,7 +159,10 @@ jobs:
|
||||
- name: Run a few important Cypress tests as sanity check
|
||||
run: |
|
||||
mkdir -p ./target/uberjar && cp metabase.jar ./target/uberjar/metabase.jar
|
||||
yarn test-cypress-run --folder ${{ matrix.folder }}
|
||||
yarn test-cypress-run \
|
||||
--env grepTags="@smoke",grepOmitFiltered=true \
|
||||
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
|
||||
--browser 'replay-chromium'
|
||||
|
||||
- name: Upload Cypress Artifacts upon failure
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -176,7 +175,7 @@ jobs:
|
||||
if-no-files-found: ignore
|
||||
|
||||
containerize:
|
||||
needs: [release-artifact, run-sanity-check]
|
||||
needs: [release-artifact]
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 15
|
||||
strategy:
|
||||
@@ -285,3 +284,37 @@ jobs:
|
||||
- name: Wait for Metabase to start
|
||||
run: while ! curl -s 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
|
||||
timeout-minutes: 3
|
||||
|
||||
tests-complete-message:
|
||||
if: always()
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [run-sanity-check, check-uberjar-health, verify-docker-pull]
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Send tests complete message
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
SLACK_RELEASE_CHANNEL: ${{ vars.SLACK_RELEASE_CHANNEL }}
|
||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
with:
|
||||
script: | # js
|
||||
const { sendTestsCompleteMessage } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
const allJobsSuccessful =
|
||||
'${{ needs.run-sanity-check.result }}' === 'success' &&
|
||||
'${{ needs.check-uberjar-health.result }}' === 'success' &&
|
||||
'${{ needs.verify-docker-pull.result }}' === 'success';
|
||||
|
||||
await sendTestsCompleteMessage({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: '${{ inputs.version }}',
|
||||
runId: '${{ github.run_id }}',
|
||||
channelName: '${{ vars.SLACK_RELEASE_CHANNEL }}',
|
||||
testStatus: allJobsSuccessful ? 'success' : 'failure',
|
||||
}).catch(console.error);
|
||||
|
||||
79
.github/workflows/release-embedding-sdk.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
type: string
|
||||
required: true
|
||||
git_ref:
|
||||
description: 'Valid git reference e.g. branches, tags, hashes'
|
||||
description: 'A git commit hash that will be used to build the SDK'
|
||||
type: string
|
||||
required: true
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
|
||||
- name: check tags
|
||||
run: |
|
||||
if [ $(git tag -l | grep $tag) ]
|
||||
if [ $(git tag -l | grep $tag$) ]
|
||||
then
|
||||
echo "::error::Tag '${{ env.tag }}' already exists. If you expect to run this workflow with the same tag, please remove the tag first and rerun this workflow again."
|
||||
exit 1
|
||||
@@ -92,16 +92,9 @@ jobs:
|
||||
run: |
|
||||
./bin/embedding-sdk/release_utils.bash update_package_json_template ${{ inputs.sdk_version }}
|
||||
|
||||
# TODO: Remove this step after the build utils script is merged to master
|
||||
- name: Upload release utils script, so it can be used later on when checking out `master` branch
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-util
|
||||
path: ./bin/embedding-sdk/release_utils.bash
|
||||
|
||||
- name: Update changelog
|
||||
run: |
|
||||
yarn embedding-sdk:generate-changelog
|
||||
yarn embedding-sdk:generate-changelog -o changelog-diff
|
||||
|
||||
- name: Build SDK bundle
|
||||
run: yarn run build-embedding-sdk
|
||||
@@ -115,11 +108,11 @@ jobs:
|
||||
name: metabase-sdk
|
||||
path: ./resources/embedding-sdk
|
||||
|
||||
- name: Upload changelog
|
||||
- name: Upload changelog diff
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdk-changelog
|
||||
path: ./enterprise/frontend/src/embedding-sdk/CHANGELOG.md
|
||||
name: sdk-changelog-diff
|
||||
path: ./changelog-diff
|
||||
|
||||
build-jar:
|
||||
needs: test
|
||||
@@ -168,15 +161,8 @@ jobs:
|
||||
|
||||
- name: Setup git user
|
||||
run: |
|
||||
git config --global user.email "metabase-bot@metabase.com"
|
||||
git config --global user.name "Metabase bot"
|
||||
|
||||
# TODO: Remove this step after the build utils script is merged to master
|
||||
- name: Download release utils script
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: release-util
|
||||
path: ./bin/embedding-sdk/
|
||||
git config --global user.email "github-automation@metabase.com"
|
||||
git config --global user.name "Metabase Automation"
|
||||
|
||||
- name: Update readme
|
||||
run: |
|
||||
@@ -186,23 +172,17 @@ jobs:
|
||||
run: |
|
||||
bash ./bin/embedding-sdk/release_utils.bash update_package_json_template ${{ inputs.sdk_version }}
|
||||
|
||||
- name: Retrieve SDK changelog
|
||||
- name: Retrieve SDK changelog diff
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: sdk-changelog
|
||||
name: sdk-changelog-diff
|
||||
|
||||
# We need to do this because it's impossible to download an artifact to an existing location
|
||||
- name: Move over the downloaded changelog
|
||||
- name: Update changelog
|
||||
run: |
|
||||
mv CHANGELOG.md ./enterprise/frontend/src/embedding-sdk/CHANGELOG.md
|
||||
cat changelog-diff enterprise/frontend/src/embedding-sdk/CHANGELOG.md > new-changelog
|
||||
mv new-changelog enterprise/frontend/src/embedding-sdk/CHANGELOG.md
|
||||
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.METABASE_BOT_APP_ID }}
|
||||
private-key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Create a PR updating readme + published version, and changelog
|
||||
- name: Create a PR updating readme + published version, and changelog (using GitHub Metabase Automation account)
|
||||
run: |
|
||||
git checkout -b update-sdk-version-${{ inputs.sdk_version }}
|
||||
git commit -a -m 'Update Readme version references and published npm version to ${{ inputs.sdk_version }}'
|
||||
@@ -211,10 +191,33 @@ jobs:
|
||||
--assignee "${GITHUB_ACTOR}"\
|
||||
--title "Update SDK version to ${{ inputs.sdk_version }}"\
|
||||
--body "Update Readme version references and published npm package version to ${{ inputs.sdk_version }}"
|
||||
gh pr edit --add-reviewer @metabase/embedding
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.METABASE_BOT_APP_ID }}
|
||||
private-key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Edit PR adding useful information (using Metabase bot app)
|
||||
run: |
|
||||
gh pr edit --add-reviewer @metabase/embedding --add-label no-backport
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Auto approve PR (using GitHub Actions account)
|
||||
run: |
|
||||
gh pr review --approve
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Enable Pull request auto-merge (using GitHub Metabase Automation account)
|
||||
run: |
|
||||
gh pr merge --auto --squash
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
|
||||
- name: Retrieve build SDK package artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -239,11 +242,7 @@ jobs:
|
||||
with:
|
||||
ref: ${{ inputs.git_ref }}
|
||||
|
||||
- name: Setup git user
|
||||
run: |
|
||||
git config --global user.email "metabase-bot@metabase.com"
|
||||
git config --global user.name "Metabase bot"
|
||||
|
||||
# Lightweight tags don't need committer name and email
|
||||
- name: Create a new git tag
|
||||
run: |
|
||||
git tag ${{ env.tag }}
|
||||
|
||||
30
.github/workflows/release-status.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Release Status Check
|
||||
name: Release and Backport Status Check
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -38,3 +38,31 @@ jobs:
|
||||
repo: context.repo.repo,
|
||||
channelName: process.env.SLACK_RELEASE_CHANNEL,
|
||||
});
|
||||
|
||||
open-backport-reminder:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn --frozen-lockfile && yarn build
|
||||
- name: Check release status and post to Slack
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
with:
|
||||
script: | # js
|
||||
const { checkOpenBackports } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
if (!process.env.SLACK_BOT_TOKEN) {
|
||||
throw new Error('SLACK_BOT_TOKEN is required');
|
||||
}
|
||||
|
||||
const ossReleased = await checkOpenBackports({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
channelName: 'engineering-ci',
|
||||
});
|
||||
|
||||
95
.github/workflows/release.yml
vendored
@@ -90,6 +90,34 @@ jobs:
|
||||
|
||||
return versions;
|
||||
|
||||
publish-start-message:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [check-version]
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Send publish start message
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
SLACK_RELEASE_CHANNEL: ${{ vars.SLACK_RELEASE_CHANNEL }}
|
||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
with:
|
||||
script: | # js
|
||||
const { sendPublishStartMessage } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
await sendPublishStartMessage({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: '${{ inputs.version }}',
|
||||
runId: '${{ github.run_id }}',
|
||||
channelName: '${{ vars.SLACK_RELEASE_CHANNEL }}',
|
||||
}).catch(console.error);
|
||||
|
||||
|
||||
download-uberjar:
|
||||
needs: check-version
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -500,6 +528,45 @@ jobs:
|
||||
}
|
||||
});
|
||||
|
||||
trigger-cloud-issues:
|
||||
needs: push-tags
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
script: |
|
||||
github.rest.repos.createDispatchEvent({
|
||||
owner: '${{ github.repository_owner }}',
|
||||
repo: '${{ vars.OPS_REPO }}',
|
||||
event_type: 'create-release-issues',
|
||||
client_payload: {
|
||||
version: '${{ inputs.version }}'
|
||||
}
|
||||
});
|
||||
|
||||
trigger-ee-extra-pr:
|
||||
needs: verify-s3-download
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
script: | # js
|
||||
const version = '${{ inputs.version }}';
|
||||
const enterpriseVersion = version.replace(/^v0\./, "v1.");
|
||||
|
||||
github.rest.repos.createDispatchEvent({
|
||||
owner: '${{ github.repository_owner }}',
|
||||
repo: 'metabase-ee-extra',
|
||||
event_type: 'update-ee-extra-build',
|
||||
client_payload: {
|
||||
version: enterpriseVersion,
|
||||
}
|
||||
});
|
||||
|
||||
draft-release-notes:
|
||||
if: ${{ inputs.skip-release-notes != true }}
|
||||
needs: push-tags
|
||||
@@ -611,6 +678,34 @@ jobs:
|
||||
--distribution-id ${{ vars.AWS_CLOUDFRONT_STATIC_ID }} \
|
||||
--paths "/version-info.json" "/version-info-ee.json"
|
||||
|
||||
publish-complete-message:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [draft-release-notes, verify-docker-pull, verify-s3-download, publish-version-info]
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Send publish complete message
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
SLACK_RELEASE_CHANNEL: ${{ vars.SLACK_RELEASE_CHANNEL }}
|
||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
with:
|
||||
script: | # js
|
||||
const { sendPublishCompleteMessage } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
await sendPublishCompleteMessage({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: '${{ inputs.version }}',
|
||||
runId: '${{ github.run_id }}',
|
||||
channelName: '${{ vars.SLACK_RELEASE_CHANNEL }}',
|
||||
generalChannelName: 'general',
|
||||
}).catch(console.error);
|
||||
|
||||
manage-milestones:
|
||||
permissions: write-all
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
2
.github/workflows/rerun-workflows.yml
vendored
@@ -2,7 +2,7 @@ name: Re-run Flaky Workflows
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [Backend, Driver Tests, E2E Tests, Frontend]
|
||||
workflows: [Backend, Driver Tests, E2E Tests, Frontend, Backend-Cloverage]
|
||||
types: [completed]
|
||||
branches: [master, 'release-x.**', 'backport-**']
|
||||
|
||||
|
||||
252
.github/workflows/tag-for-release.yml
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
name: Release 1a - Tag Release Artifact
|
||||
run-name: Tag ${{ inputs.version }}
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Metabase version (e.g. v0.46.3)'
|
||||
type: string
|
||||
required: true
|
||||
commit:
|
||||
description: 'A full-length commit SHA-1 hash'
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
start-message:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Send build start message
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
SLACK_RELEASE_CHANNEL: ${{ vars.SLACK_RELEASE_CHANNEL }}
|
||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
with:
|
||||
script: | # js
|
||||
const { sendPreReleaseMessage } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
await sendPreReleaseMessage({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: '${{ inputs.version }}',
|
||||
runId: '${{ github.run_id }}',
|
||||
releaseSha: '${{ inputs.commit }}',
|
||||
userName: '${{ github.actor }}',
|
||||
channelName: '${{ vars.SLACK_RELEASE_CHANNEL }}',
|
||||
}).catch(console.error);
|
||||
|
||||
check-version:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
ee: ${{ fromJson(steps.canonical_version.outputs.result).ee }}
|
||||
oss: ${{ fromJson(steps.canonical_version.outputs.result).oss }}
|
||||
steps:
|
||||
- name: Fail early on the incorrect version format
|
||||
if: ${{ !(startsWith(inputs.version,'v0.') || startsWith(inputs.version,'v1.')) }}
|
||||
run: |
|
||||
echo "The version format is invalid!"
|
||||
echo "It must start with either 'v0.' or 'v1.'."
|
||||
echo "Please, try again."
|
||||
exit 1
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get Release Version
|
||||
uses: actions/github-script@v7
|
||||
id: canonical_version
|
||||
with:
|
||||
script: | # js
|
||||
const { isValidVersionString, getCanonicalVersion, hasBeenReleased } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
const version = '${{ inputs.version }}';
|
||||
|
||||
if (!isValidVersionString(version)) {
|
||||
throw new Error("The version format is invalid! It must start with either 'v0.' or 'v1.'.");
|
||||
}
|
||||
|
||||
const versions = {
|
||||
ee: getCanonicalVersion(version, 'ee'),
|
||||
oss: getCanonicalVersion(version, 'oss'),
|
||||
};
|
||||
|
||||
const ossReleased = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.oss,
|
||||
});
|
||||
|
||||
const eeReleased = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.ee,
|
||||
});
|
||||
|
||||
if (ossReleased || eeReleased) {
|
||||
throw new Error("This version has already been released!", version);
|
||||
}
|
||||
|
||||
return versions;
|
||||
|
||||
check-commit:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Check out the code to verify the release branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # IMPORTANT! to get all the branches
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get Release Branch
|
||||
uses: actions/github-script@v7
|
||||
id: release_branch
|
||||
with:
|
||||
result_encoding: string
|
||||
script: | # js
|
||||
const { getReleaseBranch } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const version = '${{ inputs.version }}';
|
||||
const releaseBranch = getReleaseBranch(version);
|
||||
return releaseBranch;
|
||||
- name: Ensure that the specified commit exists in the ${{ steps.release_branch.outputs.result }} release branch
|
||||
run: |
|
||||
RELEASE_BRANCH=${{ steps.release_branch.outputs.result }}
|
||||
git checkout $RELEASE_BRANCH
|
||||
git branch --contains ${{ inputs.commit }} | grep -q $RELEASE_BRANCH \
|
||||
&& echo "Commit found in correct release branch" \
|
||||
|| (echo "Commit not found in correct release branch" && exit 1)
|
||||
|
||||
tag-uberjar-for-release:
|
||||
needs: [check-version, check-commit]
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [oss, ee]
|
||||
env:
|
||||
INTERACTIVE: false
|
||||
steps:
|
||||
- name: Get correct version number
|
||||
run: | # bash
|
||||
if [ '${{matrix.edition}}' == 'ee' ]; then
|
||||
version='${{ needs.check-version.outputs.ee }}'
|
||||
else
|
||||
version='${{ needs.check-version.outputs.oss }}'
|
||||
fi
|
||||
|
||||
echo "VERSION=$version" >> $GITHUB_ENV
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17 # 11 throws an error on jar uf
|
||||
|
||||
- name: Retrieve test build uberjar artifact for ${{ matrix.edition }}
|
||||
id: find_release_artifact
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
result-encoding: string
|
||||
script: | # js
|
||||
const fs = require('fs');
|
||||
|
||||
const artifacts = await github.rest.actions.listArtifactsForRepo({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: `metabase-${{ matrix.edition }}-${{ inputs.commit }}-uberjar`,
|
||||
per_page: 1,
|
||||
});
|
||||
|
||||
if (!artifacts.data?.artifacts?.[0]?.id) {
|
||||
console.warn(`No existing artifacts found for ${{ inputs.commit }}, need to build jar`);
|
||||
|
||||
if ("${{matrix.edition}}" === 'oss') {
|
||||
// only trigger the build job on OSS, otherwise we'll get double builds
|
||||
github.rest.actions.createWorkflowDispatch({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
workflow_id: 'build-for-release.yml',
|
||||
ref: 'refs/heads/master',
|
||||
inputs: {
|
||||
commit: '${{ inputs.commit }}',
|
||||
version: '${{ inputs.version }}',
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
throw new Error('aborting in favor of build script');
|
||||
}
|
||||
|
||||
const artifact_id = artifacts.data.artifacts[0].id;
|
||||
|
||||
const download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: artifact_id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
|
||||
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/mb.zip`, Buffer.from(download.data));
|
||||
- name: Unzip Metabase artifact containing an uberjar
|
||||
run: |
|
||||
unzip mb.zip
|
||||
mv target/uberjar/metabase.jar metabase.jar
|
||||
|
||||
- name: Update version.properties in jar
|
||||
run: | # sh
|
||||
jar xf metabase.jar version.properties
|
||||
echo "Old version.properties:"
|
||||
cat version.properties
|
||||
sed -i "s/^tag=.*/tag=$VERSION/" version.properties
|
||||
echo "\n\nNew version.properties:"
|
||||
cat version.properties
|
||||
echo "\n\nUpdating metabase.jar with new version.properties"
|
||||
jar uf metabase.jar version.properties
|
||||
|
||||
- name: Store commit's SHA-1 hash
|
||||
run: echo ${{ inputs.commit }} > COMMIT-ID
|
||||
shell: bash
|
||||
- name: Calculate SHA256 checksum
|
||||
run: sha256sum ./metabase.jar > SHA256.sum
|
||||
shell: bash
|
||||
- name: Upload JARs as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: metabase-release-${{ matrix.edition }}-${{ inputs.commit }}-uberjar
|
||||
path: |
|
||||
./metabase.jar
|
||||
./COMMIT-ID
|
||||
./SHA256.sum
|
||||
|
||||
trigger-tests:
|
||||
needs: [tag-uberjar-for-release]
|
||||
permissions:
|
||||
actions: write
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: trigger pre-release testing
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
github.rest.actions.createWorkflowDispatch({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
workflow_id: 'pre-release.yml',
|
||||
ref: '${{ github.ref }}',
|
||||
inputs: {
|
||||
commit: '${{ inputs.commit }}',
|
||||
version: '${{ inputs.version }}',
|
||||
}
|
||||
});
|
||||
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
BIN
.loki/reference/chrome_laptop_viz_BarChart_Default.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 11 KiB |
BIN
.loki/reference/chrome_laptop_viz_LineChart_Default.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
BIN
.loki/reference/chrome_laptop_viz_TableInteractive_Default.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
.loki/reference/chrome_laptop_viz_TableSimple_Default.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 71 KiB |
@@ -16,6 +16,9 @@ module.exports = {
|
||||
"@storybook/addon-a11y",
|
||||
],
|
||||
babel: () => {},
|
||||
typescript: {
|
||||
reactDocgen: "react-docgen-typescript-plugin",
|
||||
},
|
||||
webpackFinal: storybookConfig => ({
|
||||
...storybookConfig,
|
||||
plugins: [
|
||||
|
||||
@@ -1,9 +1,57 @@
|
||||
<style>
|
||||
:root {
|
||||
--mb-default-font-family: "Lato";
|
||||
--mb-color-brand: #509ee3;
|
||||
--mb-color-bg-dark: #93a1ab;
|
||||
--mb-color-bg-error: #ed6e6e55;
|
||||
--mb-color-bg-light: #f9fbfc;
|
||||
--mb-color-bg-medium: #edf2f5;
|
||||
--mb-color-bg-night: #42484e;
|
||||
--mb-color-bg-white: #fff;
|
||||
--mb-color-border: #eeecec;
|
||||
--mb-color-brand-alpha-04: rgba(80, 158, 227, 0.04);
|
||||
--mb-color-brand-alpha-88: rgba(80, 158, 227, 0.88);
|
||||
--mb-color-brand-light: #f9fbfc;
|
||||
--mb-color-brand-lighter: #eef6fc;
|
||||
--mb-color-brand: #509ee3;
|
||||
--mb-color-danger: #ed6e6e;
|
||||
--mb-color-error: #ed6e6e;
|
||||
--mb-color-filter: #7172ad;
|
||||
--mb-color-focus: #cbe2f7;
|
||||
--mb-color-shadow: rgba(0, 0, 0, 0.13);
|
||||
--mb-color-success: #84bb4c;
|
||||
--mb-color-summarize: #88bf4d;
|
||||
--mb-color-text-white: #fff;
|
||||
--mb-color-text-dark: #4c5773;
|
||||
--mb-color-text-light: #949aab;
|
||||
--mb-color-text-medium: #696e7b;
|
||||
--mb-color-warning: #f9cf48;
|
||||
|
||||
--mb-color-border-alpha-30: color-mix(
|
||||
in srgb,
|
||||
var(--mb-color-border) 30%,
|
||||
transparent
|
||||
);
|
||||
--mb-color-text-white-alpha-85: color-mix(
|
||||
in srgb,
|
||||
var(--mb-color-text-white) 85%,
|
||||
transparent
|
||||
);
|
||||
--mb-color-bg-black-alpha-60: color-mix(
|
||||
in srgb,
|
||||
var(--mb-color-bg-black) 60%,
|
||||
transparent
|
||||
);
|
||||
--mb-color-bg-white-alpha-15: color-mix(
|
||||
in srgb,
|
||||
var(--mb-color-bg-white) 15%,
|
||||
transparent
|
||||
);
|
||||
|
||||
/*
|
||||
Theming-specific CSS variables.
|
||||
These CSS variables are not part of the core design system colors.
|
||||
**/
|
||||
--mb-color-bg-dashboard: var(--mb-color-bg-white);
|
||||
--mb-color-bg-dashboard-card: var(--mb-color-bg-white);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
"alpha-value-notation": null,
|
||||
"color-function-notation": null,
|
||||
"custom-property-pattern": null,
|
||||
"function-no-unknown": [
|
||||
true,
|
||||
{ "ignoreFunctions": ["color-mod", "alpha", "blackness"] }
|
||||
],
|
||||
"import-notation": "string",
|
||||
"media-feature-range-notation": "prefix",
|
||||
"no-descending-specificity": null,
|
||||
|
||||
16
deps.edn
@@ -76,7 +76,7 @@
|
||||
io.github.eerohele/pp {:git/tag "2024-01-04.60" ; super fast pretty-printing library
|
||||
:git/sha "a428751"
|
||||
:git/url "https://github.com/eerohele/pp"}
|
||||
io.github.metabase/macaw {:mvn/version "0.1.44"} ; Parse native SQL queries
|
||||
io.github.metabase/macaw {:mvn/version "0.1.49"} ; Parse native SQL queries
|
||||
;; The 2.X line of Resilience4j requires Java 17, so we cannot upgrade this dependency until that is our minimum JVM version
|
||||
io.github.resilience4j/resilience4j-retry {:mvn/version "1.7.1" #_ "must be 1.7.1"} ; Support for retrying operations
|
||||
io.prometheus/simpleclient_hotspot {:mvn/version "0.16.0"} ; prometheus jvm collector
|
||||
@@ -665,9 +665,17 @@
|
||||
:extra-paths ["dev/src"]
|
||||
:main-opts ["-m" "dev.liquibase"]}
|
||||
|
||||
;; the following aliases are convenience for running tests against certain parts of the codebase.
|
||||
;;
|
||||
;; clj -X:dev:ee:ee-dev:test:test/mbql
|
||||
;; Migrate CLI:
|
||||
;; clojure -M:migrate <command>
|
||||
;; E.g.
|
||||
;; clojure -M:migrate up ;; migrate up to the latest
|
||||
;; clojure -M:migrate rollback count 2 ;; rollback 2 migrations
|
||||
;; clojure -M:migrate rollback id "v40.00.001" ;; rollback to a specific migration with id
|
||||
;; clojure -M:migrate status ;; print the latest migration id
|
||||
:migrate
|
||||
{:extra-deps {io.github.camsaul/humane-are {:mvn/version "1.0.2"}}
|
||||
:extra-paths ["dev/src"]
|
||||
:main-opts ["-m" "dev.migrate"]}
|
||||
|
||||
;; run tests against MLv2. Very fast since this is almost all ^:parallel
|
||||
:test/mlv2
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
[clojure.test]
|
||||
[dev.debug-qp :as debug-qp]
|
||||
[dev.explain :as dev.explain]
|
||||
[dev.migrate :as dev.migrate]
|
||||
[dev.model-tracking :as model-tracking]
|
||||
[hashp.core :as hashp]
|
||||
[honey.sql :as sql]
|
||||
@@ -68,7 +69,9 @@
|
||||
[metabase.driver :as driver]
|
||||
[metabase.driver.sql-jdbc.connection :as sql-jdbc.conn]
|
||||
[metabase.driver.sql-jdbc.execute :as sql-jdbc.execute]
|
||||
[metabase.email :as email]
|
||||
[metabase.models.database :refer [Database]]
|
||||
[metabase.models.setting :as setting]
|
||||
[metabase.query-processor.compile :as qp.compile]
|
||||
[metabase.query-processor.timezone :as qp.timezone]
|
||||
[metabase.server :as server]
|
||||
@@ -101,6 +104,9 @@
|
||||
pprint-sql]
|
||||
[dev.explain
|
||||
explain-query]
|
||||
[dev.migrate
|
||||
migrate!
|
||||
rollback!]
|
||||
[model-tracking
|
||||
track!
|
||||
untrack!
|
||||
@@ -258,14 +264,6 @@
|
||||
(a/>!! canceled-chan :cancel)
|
||||
(throw e)))))
|
||||
|
||||
(defn migrate!
|
||||
"Run migrations for the Metabase application database. Possible directions are `:up` (default), `:force`, `:down`, and
|
||||
`:release-locks`. When migrating `:down` pass along a version to migrate to (44+)."
|
||||
([]
|
||||
(migrate! :up))
|
||||
([direction & [version]]
|
||||
(mdb/migrate! (mdb/data-source) direction version)))
|
||||
|
||||
(methodical/defmethod t2.connection/do-with-connection :model/Database
|
||||
"Support running arbitrary queries against data warehouse DBs for easy REPL debugging. Only works for SQL+JDBC drivers
|
||||
right now!
|
||||
@@ -390,3 +388,25 @@
|
||||
(when (failed?)
|
||||
(throw (ex-info (format "Test failed after running: `%s`" test)
|
||||
{:test test})))))))
|
||||
|
||||
|
||||
(defn setup-email!
|
||||
"Set up email settings for sending emails from Metabase. This is useful for testing email sending in the REPL."
|
||||
[& settings]
|
||||
(let [settings (merge {:host "localhost"
|
||||
:port 1025
|
||||
:user "metabase"
|
||||
:pass "metabase@secret"
|
||||
:security :none}
|
||||
settings)]
|
||||
(when (::email/error (email/test-smtp-connection settings))
|
||||
(throw (ex-info "Failed to connect to SMTP server" {:settings settings})))
|
||||
(setting/set-many! (update-keys settings
|
||||
{:host :email-smtp-host,
|
||||
:user :email-smtp-username,
|
||||
:pass :email-smtp-password,
|
||||
:port :email-smtp-port,
|
||||
:security :email-smtp-security,
|
||||
:sender-name :email-from-name,
|
||||
:sender :email-from-address,
|
||||
:reply-to :email-reply-to}))))
|
||||
|
||||
103
dev/src/dev/migrate.clj
Normal file
@@ -0,0 +1,103 @@
|
||||
(ns dev.migrate
|
||||
(:gen-class)
|
||||
(:require
|
||||
[metabase.db :as mdb]
|
||||
[metabase.db.liquibase :as liquibase]
|
||||
[metabase.util.malli :as mu]
|
||||
[toucan2.core :as t2])
|
||||
(:import
|
||||
(liquibase Liquibase)))
|
||||
|
||||
(set! *warn-on-reflection* true)
|
||||
|
||||
(defn- latest-migration
|
||||
[]
|
||||
((juxt :id :comments)
|
||||
(t2/query-one {:select [:id :comments]
|
||||
:from [(keyword (liquibase/changelog-table-name (mdb/data-source)))]
|
||||
:order-by [[:orderexecuted :desc]]
|
||||
:limit 1})))
|
||||
(defn migrate!
|
||||
"Run migrations for the Metabase application database. Possible directions are `:up` (default), `:force`, `:down`, and
|
||||
`:release-locks`. When migrating `:down` pass along a version to migrate to (44+)."
|
||||
([]
|
||||
(migrate! :up))
|
||||
;; do we really use this in dev?
|
||||
([direction & [version]]
|
||||
(mdb/migrate! (mdb/data-source) direction version)
|
||||
#_{:clj-kondo/ignore [:discouraged-var]}
|
||||
(println "Migrated up. Latest migration:" (latest-migration))))
|
||||
|
||||
(defn- rollback-n-migrations!
|
||||
[^Integer n]
|
||||
(with-open [conn (.getConnection (mdb/data-source))]
|
||||
(liquibase/with-liquibase [^Liquibase liquibase conn]
|
||||
(liquibase/with-scope-locked liquibase
|
||||
(.rollback liquibase n "")))))
|
||||
|
||||
(defn- migration-since
|
||||
[id]
|
||||
(->> (t2/query-one {:select [[:%count.* :count]]
|
||||
:from [:databasechangelog]
|
||||
:where [:> :orderexecuted {:select [:orderexecuted]
|
||||
:from [:databasechangelog]
|
||||
:where [:like :id (format "%s%%" id)]
|
||||
:order-by [:orderexecuted :desc]
|
||||
:limit 1}]
|
||||
:limit 1})
|
||||
:count
|
||||
;; includes the selected id
|
||||
inc))
|
||||
|
||||
(defn- maybe-parse-long
|
||||
[x]
|
||||
(cond-> x
|
||||
(string? x)
|
||||
parse-long))
|
||||
|
||||
(mu/defn rollback!
|
||||
"Rollback helper, can take a number of migrations to rollback or a specific migration ID(inclusive).
|
||||
|
||||
;; Rollback 2 migrations:
|
||||
(rollback! :count 2)
|
||||
|
||||
;; rollback to \"v50.2024-03-18T16:00:00\" (inclusive)
|
||||
(rollback! :id \"v50.2024-03-18T16:00:00\")"
|
||||
[k :- [:enum :id :count "id" "count"]
|
||||
target]
|
||||
(let [n (case (keyword k)
|
||||
:id (migration-since target)
|
||||
:count (maybe-parse-long target))]
|
||||
(rollback-n-migrations! n)
|
||||
#_{:clj-kondo/ignore [:discouraged-var]}
|
||||
(println (format "Rollbacked %d migrations. Latest migration: %s" n (latest-migration)))))
|
||||
|
||||
(defn migration-status
|
||||
"Print the latest migration ID."
|
||||
[]
|
||||
#_{:clj-kondo/ignore [:discouraged-var]}
|
||||
(println "Current migration:" (latest-migration)))
|
||||
|
||||
(defn -main
|
||||
"Migrations helpers
|
||||
|
||||
Usage:
|
||||
clojure -M:migrate up ;; migrate up to the latest
|
||||
clojure -M:migrate rollback count 2 ;; rollback 2 migrations
|
||||
clojure -M:migrate rollback id \"v40.00.001\" ;; rollback to a specific migration with id
|
||||
clojure -M:migrate status ;; print the latest migration id"
|
||||
|
||||
[& args]
|
||||
(let [[cmd & migration-args] args]
|
||||
(case cmd
|
||||
"rollback"
|
||||
(apply rollback! migration-args)
|
||||
|
||||
"up"
|
||||
(apply migrate! migration-args)
|
||||
|
||||
"status"
|
||||
(migration-status)
|
||||
|
||||
(throw (ex-info "Invalid command" {:command cmd
|
||||
:args args})))))
|
||||
@@ -9,7 +9,6 @@
|
||||
[metabase.email.messages :as messages]
|
||||
[metabase.models :refer [Card]]
|
||||
[metabase.models.card :as card]
|
||||
[metabase.models.user :as user]
|
||||
[metabase.pulse :as pulse]
|
||||
[metabase.pulse.markdown :as markdown]
|
||||
[metabase.pulse.render :as render]
|
||||
@@ -30,11 +29,11 @@
|
||||
(condp
|
||||
#(<= 0 (.indexOf ^String %2 ^String %1))
|
||||
(.toLowerCase (System/getProperty "os.name"))
|
||||
"win" :win
|
||||
"mac" :mac
|
||||
"nix" :unix
|
||||
"nux" :unix
|
||||
nil))
|
||||
"win" :win
|
||||
"mac" :mac
|
||||
"nix" :unix
|
||||
"nux" :unix
|
||||
nil))
|
||||
|
||||
;; taken from https://github.com/aysylu/loom/blob/master/src/loom/io.clj
|
||||
(defn- open
|
||||
@@ -81,16 +80,20 @@
|
||||
nil
|
||||
query-results)))
|
||||
|
||||
(defn open-hiccup-as-html
|
||||
"Take a hiccup data structure, render it as html, then open it in the browser."
|
||||
[hiccup]
|
||||
(let [html-str (hiccup/html hiccup)
|
||||
tmp-file (File/createTempFile "card-html" ".html")]
|
||||
(defn open-html
|
||||
"Take a html string, then open it in the browser."
|
||||
[html-str]
|
||||
(let [tmp-file (File/createTempFile "card-html" ".html")]
|
||||
(with-open [w (io/writer tmp-file)]
|
||||
(.write w ^String html-str))
|
||||
(.deleteOnExit tmp-file)
|
||||
(open tmp-file)))
|
||||
|
||||
(defn open-hiccup-as-html
|
||||
"Take a hiccup data structure, render it as html, then open it in the browser."
|
||||
[hiccup]
|
||||
(open-html (hiccup/html hiccup)))
|
||||
|
||||
(def ^:private execute-dashboard #'pulse/execute-dashboard)
|
||||
|
||||
(defn render-dashboard-to-pngs
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
(ns user
|
||||
(:require
|
||||
[environ.core :as env]
|
||||
[humane-are.core :as humane-are]
|
||||
[mb.hawk.assert-exprs]
|
||||
[metabase.bootstrap]
|
||||
[metabase.test-runner.assert-exprs]
|
||||
[pjstadig.humane-test-output :as humane-test-output]))
|
||||
[metabase.plugins.classloader :as classloader]
|
||||
[metabase.util :as u]))
|
||||
|
||||
;; Initialize Humane Test Output if it's not already initialized. Don't enable humane-test-output when running tests
|
||||
;; from the CLI, it breaks diffs. This uses [[env/env]] rather than [[metabase.config]] so we don't load that namespace
|
||||
;; before we load [[metabase.bootstrap]]
|
||||
(when-not (= (env/env :mb-run-mode) "test")
|
||||
(humane-test-output/activate!))
|
||||
;; Wrap these with ignore-exceptions to reduce the "required" deps of this namespace
|
||||
;; We sometimes need to run cmd stuffs like `clojure -M:migrate rollback n 3` and these
|
||||
;; libraries might not be available in the classpath
|
||||
(u/ignore-exceptions
|
||||
;; make sure stuff like `=?` and what not are loaded
|
||||
(classloader/require 'mb.hawk.assert-exprs))
|
||||
|
||||
;;; Same for https://github.com/camsaul/humane-are
|
||||
(humane-are/install!)
|
||||
(u/ignore-exceptions
|
||||
(classloader/require 'metabase.test-runner.assert-exprs))
|
||||
|
||||
(comment metabase.bootstrap/keep-me
|
||||
;; make sure stuff like `=?` and what not are loaded
|
||||
mb.hawk.assert-exprs/keep-me
|
||||
metabase.test-runner.assert-exprs/keep-me)
|
||||
(u/ignore-exceptions
|
||||
(classloader/require 'humane-are.core)
|
||||
((resolve 'humane-are.core/install!)))
|
||||
|
||||
(u/ignore-exceptions
|
||||
(classloader/require 'pjstadig.humane-test-output)
|
||||
;; Initialize Humane Test Output if it's not already initialized. Don't enable humane-test-output when running tests
|
||||
;; from the CLI, it breaks diffs. This uses [[env/env]] rather than [[metabase.config]] so we don't load that namespace
|
||||
;; before we load [[metabase.bootstrap]]
|
||||
(when-not (= (env/env :mb-run-mode) "test")
|
||||
((resolve 'pjstadig.humane-test-output/activate!))))
|
||||
|
||||
(comment metabase.bootstrap/keep-me)
|
||||
|
||||
(defn dev
|
||||
"Load and switch to the 'dev' namespace."
|
||||
|
||||
@@ -107,6 +107,7 @@ Metabase's reference documentation.
|
||||
|
||||
- [Data modeling overview](./data-modeling/start.md)
|
||||
- [Models](./data-modeling/models.md)
|
||||
- [Model persistence](./data-modeling/model-persistence.md)
|
||||
- [Table metadata admin settings](./data-modeling/metadata-editing.md)
|
||||
- [Field types](./data-modeling/field-types.md)
|
||||
- [Formatting defaults](./data-modeling/formatting.md)
|
||||
|
||||
@@ -62,6 +62,7 @@ Before using actions in production, consider playing around with actions on some
|
||||
- If caching is enabled for the relevant table or model, you may not see the effects of an action in Metabase until Metabase refreshes the data (though you can always manually refresh the data).
|
||||
- When creating records on a table that lacks an automatically generated primary key, you'll need to input an available ID (i.e., an ID not already in use by another record).
|
||||
- You can't "undo" actions. You can, however, create and run an action to recreate a deleted record, or change an updated record back to its original values (provided you know the original values).
|
||||
- Actions are unavailable for public dashboards, and dashboards in [static embeds](../embedding/static-embedding.md).
|
||||
|
||||
## Further reading
|
||||
|
||||
|
||||
@@ -25,22 +25,21 @@ Create keys to authenticate programmatic requests to your Metabase. See [API key
|
||||
|
||||
## API endpoints
|
||||
|
||||
_* indicates endpoints used for features available on [paid plans](https://www.metabase.com/pricing)._
|
||||
|
||||
_\* indicates endpoints used for features available on [Pro and Enterprise](https://www.metabase.com/pricing)._
|
||||
|
||||
- [Action](api/action.md)
|
||||
- [Activity](api/activity.md)
|
||||
- [Advanced config logs*](api/ee/advanced-config-logs.md)
|
||||
- [Advanced permissions application*](api/ee/advanced-permissions-application.md)
|
||||
- [Advanced permissions impersonation*](api/ee/advanced-permissions-impersonation.md)
|
||||
- [Advanced config logs\*](api/ee/advanced-config-logs.md)
|
||||
- [Advanced permissions application\*](api/ee/advanced-permissions-application.md)
|
||||
- [Advanced permissions impersonation\*](api/ee/advanced-permissions-impersonation.md)
|
||||
- [Alert](api/alert.md)
|
||||
- [API key](api/api-key.md)
|
||||
- [Audit app user*](api/ee/audit-app-user.md)
|
||||
- [Audit app user\*](api/ee/audit-app-user.md)
|
||||
- [Automagic dashboards](api/automagic-dashboards.md)
|
||||
- [Bookmark](api/bookmark.md)
|
||||
- [Card](api/card.md)
|
||||
- [Collection](api/collection.md)
|
||||
- [Content verification review*](api/ee/content-verification-review.md)
|
||||
- [Content verification review\*](api/ee/content-verification-review.md)
|
||||
- [Dashboard](api/dashboard.md)
|
||||
- [Database](api/database.md)
|
||||
- [Dataset](api/dataset.md)
|
||||
@@ -52,7 +51,6 @@ _* indicates endpoints used for features available on [paid plans](https://www.m
|
||||
- [LDAP](api/ldap.md)
|
||||
- [Login history](api/login-history.md)
|
||||
- [Metabot](api/metabot.md)
|
||||
- [Metric](api/legacy-metric.md)
|
||||
- [Model index](api/model-index.md)
|
||||
- [Native query snippet](api/native-query-snippet.md)
|
||||
- [Notify](api/notify.md)
|
||||
@@ -63,17 +61,17 @@ _* indicates endpoints used for features available on [paid plans](https://www.m
|
||||
- [Public](api/public.md)
|
||||
- [Pulse](api/pulse.md)
|
||||
- [Revision](api/revision.md)
|
||||
- [Sandbox GTAP*](api/ee/sandbox-gtap.md)
|
||||
- [Sandbox table*](api/ee/sandbox-table.md)
|
||||
- [Sandbox user*](api/ee/sandbox-user.md)
|
||||
- [Sandbox GTAP\*](api/ee/sandbox-gtap.md)
|
||||
- [Sandbox table\*](api/ee/sandbox-table.md)
|
||||
- [Sandbox user\*](api/ee/sandbox-user.md)
|
||||
- [Search](api/search.md)
|
||||
- [Segment](api/segment.md)
|
||||
- [Serialization*](api/ee/serialization.md)
|
||||
- [Serialization\*](api/ee/serialization.md)
|
||||
- [Session](api/session.md)
|
||||
- [Setting](api/setting.md)
|
||||
- [Setup](api/setup.md)
|
||||
- [Slack](api/slack.md)
|
||||
- [SSO*](api/ee/sso.md)
|
||||
- [SSO\*](api/ee/sso.md)
|
||||
- [SSO SAML](api/sso-saml.md)
|
||||
- [Table](api/table.md)
|
||||
- [Task](api/task.md)
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
---
|
||||
title: "Metric"
|
||||
summary: |
|
||||
/api/legacy-metric endpoints.
|
||||
---
|
||||
|
||||
# Metric
|
||||
|
||||
/api/legacy-metric endpoints.
|
||||
|
||||
## `DELETE /api/legacy-metric/:id`
|
||||
|
||||
Archive a Metric. (DEPRECATED -- Just pass updated value of `:archived` to the `PUT` endpoint instead.).
|
||||
|
||||
### PARAMS:
|
||||
|
||||
* **`id`** value must be an integer greater than zero.
|
||||
|
||||
* **`revision_message`** value must be a non-blank string.
|
||||
|
||||
## `GET /api/legacy-metric/`
|
||||
|
||||
Fetch *all* `Metrics`.
|
||||
|
||||
## `GET /api/legacy-metric/:id`
|
||||
|
||||
Fetch `Metric` with ID.
|
||||
|
||||
### PARAMS:
|
||||
|
||||
* **`id`** value must be an integer greater than zero.
|
||||
|
||||
## `GET /api/legacy-metric/:id/related`
|
||||
|
||||
Return related entities.
|
||||
|
||||
### PARAMS:
|
||||
|
||||
* **`id`** value must be an integer greater than zero.
|
||||
|
||||
## `GET /api/legacy-metric/:id/revisions`
|
||||
|
||||
Fetch `Revisions` for `Metric` with ID.
|
||||
|
||||
### PARAMS:
|
||||
|
||||
* **`id`** value must be an integer greater than zero.
|
||||
|
||||
## `POST /api/legacy-metric/`
|
||||
|
||||
Create a new `Metric`.
|
||||
|
||||
### PARAMS:
|
||||
|
||||
* **`name`** value must be a non-blank string.
|
||||
|
||||
* **`description`** nullable string
|
||||
|
||||
* **`table_id`** value must be an integer greater than zero.
|
||||
|
||||
* **`definition`** map
|
||||
|
||||
## `POST /api/legacy-metric/:id/revert`
|
||||
|
||||
Revert a `Metric` to a prior `Revision`.
|
||||
|
||||
### PARAMS:
|
||||
|
||||
* **`id`** value must be an integer greater than zero.
|
||||
|
||||
* **`revision_id`** value must be an integer greater than zero.
|
||||
|
||||
## `PUT /api/legacy-metric/:id`
|
||||
|
||||
Update a `Metric` with ID.
|
||||
|
||||
### PARAMS:
|
||||
|
||||
* **`points_of_interest`** nullable string
|
||||
|
||||
* **`description`** nullable string
|
||||
|
||||
* **`archived`** nullable boolean
|
||||
|
||||
* **`definition`** nullable map
|
||||
|
||||
* **`revision_message`** value must be a non-blank string.
|
||||
|
||||
* **`show_in_getting_started`** nullable boolean
|
||||
|
||||
* **`name`** nullable value must be a non-blank string.
|
||||
|
||||
* **`caveats`** nullable string
|
||||
|
||||
* **`id`** value must be an integer greater than zero.
|
||||
|
||||
* **`how_is_this_calculated`** nullable string
|
||||
|
||||
## `PUT /api/legacy-metric/:id/important_fields`
|
||||
|
||||
Update the important `Fields` for a `Metric` with ID.
|
||||
(This is used for the Getting Started guide).
|
||||
|
||||
You must be a superuser to do this.
|
||||
|
||||
### PARAMS:
|
||||
|
||||
* **`id`** value must be an integer greater than zero.
|
||||
|
||||
* **`important_field_ids`** sequence of value must be an integer greater than zero.
|
||||
|
||||
---
|
||||
|
||||
[<< Back to API index](../api-documentation.md)
|
||||
@@ -33,7 +33,7 @@ Appearance settings are split across different tabs:
|
||||
In the Branding tab, you can configure your Metabase to match your brand visuals and voice.
|
||||
|
||||
- [Color palette](#color-palette)
|
||||
- [user interface colors](#user-interface-colors)
|
||||
- [User interface colors](#user-interface-colors)
|
||||
- [Chart colors](#chart-colors)
|
||||
- [Logo](#logo)
|
||||
- [Font](#font)
|
||||
|
||||
@@ -7,121 +7,115 @@ redirect_from:
|
||||
|
||||
# Caching query results
|
||||
|
||||
If your question results don't change frequently, you may want to store the results in Metabase so that the next time you visit the question, Metabase can retrieve the stored results rather than query the database again.
|
||||
If your question results don't change frequently, you may want to store the results so that the next time anyone visits the question, Metabase can retrieve the stored results rather than query the database again.
|
||||
|
||||
For example, if your data only updates once a day, there's no point in querying the database more than once a day, as they data won't have changed. Returning cached results can be significantly faster, as the database won't have to recompute the results to load your question.
|
||||
For example, if your data only updates once a day, there's no point in querying the database more than once a day, as the data won't have changed. Returning cached results can be significantly faster, as the database won't have to recompute the results to load your question.
|
||||
|
||||
Metabase gives you the ability to automatically cache question results that meet a [minimum query duration](#minimum-query-duration).
|
||||
## Cache invalidation policies
|
||||
|
||||
If your questions share a common model, you can enable [model caching](../data-modeling/models.md#model-caching) instead.
|
||||
These policies determines how long cached results will be stored.
|
||||
|
||||
## Enabling global caching
|
||||
- [Duration](#duration-caching-policy)
|
||||
- [Schedule](#schedule-caching-policy)
|
||||
- [Adaptive](#adaptive-caching-policy)
|
||||
- [Don't cache results](#dont-cache-results)
|
||||
|
||||
1. Go to **Admin settings** > **Caching** (in the sidebar).
|
||||
2. Click the toggle under **Saved Questions**.
|
||||
### Duration caching policy
|
||||
|
||||
Once you've enabled caching, you can choose when and what to cache from your [caching settings](#caching-settings).
|
||||
{% include plans-blockquote.html feature="Duration caching policy" %}
|
||||
|
||||
By default, questions will get cached once their [average execution time](#average-query-execution-time) meets a [minimum query duration](#minimum-query-duration) of 60 seconds.
|
||||
Keep the cache for a number of hours. When someone runs a query, Metabase will first check if it's cached the results. If not, it runs the query and caches the results for as long as you set the duration.
|
||||
|
||||
### Schedule caching policy
|
||||
|
||||
{% include plans-blockquote.html feature="Schedule caching policy" %}
|
||||
|
||||
Pick when to regularly invalidate the cache. Metabase will only store results when people run a query, and it will clear the cached results according to the cadence you set here.
|
||||
|
||||
You can schedule caching to invalidate:
|
||||
|
||||
- Hourly
|
||||
- Daily
|
||||
- Weekly
|
||||
- Monthly
|
||||
|
||||
We do not yet support lunar cycles.
|
||||
|
||||
### Adaptive caching policy
|
||||
|
||||
Use a query’s average execution time to determine how long to cache the query's results.
|
||||
|
||||
- **Minimum query duration**: Metabase will cache this question if it has an average query execution time greater than this many seconds.
|
||||
- **Multiplier**: Metabase will cache questions with an average query execution time greater than this many seconds. For example, if a question takes on average 10 seconds to return results, and you set a multiplier of 100, Metabase will store the cache for 10 x 100 seconds: 1,000 seconds (~16 minutes).
|
||||
|
||||
On [Pro](https://www.metabase.com/product/pro) and [Enterprise](https://www.metabase.com/product/enterprise) plans, you can view querying and caching stats in the [Metabase analytics](../usage-and-performance-tools/usage-analytics.md) collection.
|
||||
|
||||
### Don’t cache results
|
||||
|
||||
Always re-run the query to refresh results.
|
||||
|
||||
## Set caching policies at different levels
|
||||
|
||||
You can set up caching at different levels, from largest to smallest scope. Policies set at more restricted scopes override policies set at larger scopes. So a policy set on a question will take precedence over a dashboard, database, or default policy.
|
||||
|
||||
- [Setting a default caching policy](#default-caching-policy)
|
||||
- [Database caching policy (specific to each connected database)](#database-caching-policy)*
|
||||
- [Dashboard caching](#dashboard-caching-policy)*
|
||||
- [Question caching](#question-caching-policy)*
|
||||
|
||||
_* Denotes [Pro](https://www.metabase.com/product/pro) and [Enterprise](https://www.metabase.com/product/enterprise) features._
|
||||
|
||||
### Default caching policy
|
||||
|
||||

|
||||
|
||||
To set up a default caching policy for your Metabase: Hit Cmd/Ctrl + k to bring up the command palette and search for **Performance**. Or, click through **Gear** settings icon > **Admin settings** > **Performance** > **Database caching settings**.
|
||||
|
||||
Click on the button next to **Default policy**, and select a [cache invalidation policy](#cache-invalidation-policies).
|
||||
|
||||
### Database caching policy
|
||||
|
||||
{% include plans-blockquote.html feature="Database caching" %}
|
||||
|
||||
Same as the default caching policy, though you can set a caching policy for specific databases.
|
||||
|
||||
### Dashboard caching policy
|
||||
|
||||
{% include plans-blockquote.html feature="Dashboard caching" %}
|
||||
|
||||
To set a caching policy for a dashboard, you must have [curate access](../permissions/collections.md#curate-access) to the dashboard's collection.
|
||||
|
||||
1. Go to your dashboard.
|
||||
2. Click on the **info** icon.
|
||||
3. Click **Caching policy**.
|
||||
4. Select the [caching invalidation policy](#cache-invalidation-policies).
|
||||
5. Save your changes.
|
||||
|
||||
### Question caching policy
|
||||
|
||||
{% include plans-blockquote.html feature="Question caching" %}
|
||||
|
||||
To set a caching policy for a question, you must have [curate access](../permissions/collections.md#curate-access) to the question's collection.
|
||||
|
||||
1. Go to your question.
|
||||
2. Click on the **info** icon.
|
||||
3. Click **Caching policy**.
|
||||
4. Select the [caching invalidation policy](#cache-invalidation-policies).
|
||||
5. Save your changes.
|
||||
|
||||
## Clearing the cache
|
||||
|
||||
To clear the cache and refresh the results:
|
||||
|
||||
- **Questions and dashboards**: Vist the item and click through the **Info > Caching policy > Clear cache** (the "Clear cache" button is at the bottom of the sidebar).
|
||||
- **Database**: Click the **Gear** icon and click through **Admin settings** > **Performance** > **Database caching settings**. Select your database and click the **Clear cache** button (at the bottom of the page).
|
||||
|
||||
## Caching location
|
||||
|
||||
If you're self-hosting Metabase, cached question results will be saved to your [application database](../installation-and-operation/configuring-application-database.md).
|
||||
|
||||
If you're using Metabase Cloud, cached question results will be saved to Metabase's servers in the United States.
|
||||
If you're using Metabase Cloud, cached question results will be saved to Metabase's servers in the United States (as our Cloud service manages your application database for you.)
|
||||
|
||||
## Last updated at
|
||||
## Further reading
|
||||
|
||||
Questions that use the cache will display a "last cached at" timestamp in the question's **info** panel.
|
||||
|
||||
## Getting fresh results
|
||||
|
||||
To override a cached question result, re-run the question using the **refresh** button (counterclockwise arrow).
|
||||
|
||||
## Average query execution time
|
||||
|
||||
Your Metabase instance keeps track of how long it takes each question to run. The average query execution time is used in your [caching settings](#caching-settings).
|
||||
|
||||
On [paid plans](https://www.metabase.com/pricing/), you can view statistics about query execution time from your [auditing tools](../usage-and-performance-tools/audit.md).
|
||||
|
||||
## Caching settings
|
||||
|
||||
You can tell Metabase when and what to cache from **Admin settings** > **Caching**:
|
||||
|
||||
- [Minimum query duration](#minimum-query-duration)
|
||||
- [Cache time-to-live (TTL) multiplier](#cache-time-to-live-ttl-multiplier)
|
||||
- [Max cache entry size](#max-cache-entry-size)
|
||||
|
||||
### Minimum query duration
|
||||
|
||||
Metabase uses this number to decide whether a question will be cached or not.
|
||||
|
||||
Choose a duration (in seconds) that will trigger the cache. For example, you'd enter "60" if you want to cache all questions that take longer than 1 minute to load ([on average](#average-query-execution-time)).
|
||||
|
||||
### Cache time-to-live (TTL) multiplier
|
||||
|
||||
The TTL multiplier tells Metabase how long to persist a cached question result:
|
||||
|
||||
> Cache lifetime per question = TTL multiplier x [average execution time](#average-query-execution-time) per question
|
||||
|
||||
For example, if you enter a TTL multiplier of 10, a question that takes 5 seconds on average will be cached for 50 seconds. A question that takes 10 minutes will be cached for 100 minutes. This way, each question's cache lifetime is proportional to that question's execution time.
|
||||
|
||||
### Max cache entry size
|
||||
|
||||
To prevent cached results from taking up too much space on your server, you can set the maximum size of the cache (per question) in kilobytes.
|
||||
|
||||
## Advanced caching controls
|
||||
|
||||
{% include plans-blockquote.html feature="Advanced caching controls" %}
|
||||
|
||||
All Metabase editions include global caching controls. On [paid plans](https://www.metabase.com/pricing/), you can override your global [time-to-live (TTL) setting](#cache-time-to-live-ttl-multiplier) to set different cache lifetimes for specific databases, questions, or dashboards.
|
||||
|
||||
### Caching per database
|
||||
|
||||
This setting tells Metabase how long to keep the cached results from a specific database.
|
||||
|
||||
1. Make sure [caching is enabled](#enabling-global-caching).
|
||||
2. Go to **Admin settings** > **Databases** and select your database.
|
||||
3. Open **Advanced options** and find the **Default result cache duration**.
|
||||
4. Click **Custom** and enter a cache duration in hours.
|
||||
|
||||
The cache duration setting is useful for databases that take longer to query, or databases that are kept up to date on a special cadence.
|
||||
|
||||
This setting will override your [global cache duration](#cache-time-to-live-ttl-multiplier).
|
||||
|
||||
### Caching per question
|
||||
|
||||
You can tell Metabase how long to keep the cached results for specific questions. You'll only find these cache settings on questions that exceed the [minimum query duration](#minimum-query-duration).
|
||||
|
||||
1. Make sure [caching is enabled](#enabling-global-caching).
|
||||
2. Go to your question.
|
||||
3. Click on the **info** icon.
|
||||
4. Click **Cache configuration**.
|
||||
5. Enter a cache duration in hours.
|
||||
6. Click **Save changes**.
|
||||
|
||||
You can use this setting to update questions on the same cadence as your data. For example, if your data gets updated daily, you can set the **Cache configuration** to 24 hours.
|
||||
|
||||
If set, your question cache duration will override the:
|
||||
|
||||
- [global cache duration](#cache-time-to-live-ttl-multiplier)
|
||||
- [database cache duration](#caching-per-database)
|
||||
|
||||
### Caching per dashboard
|
||||
|
||||
You can tell Metabase how long to keep the cached results for each of the questions on a dashboard.
|
||||
|
||||
1. Make sure [caching is enabled](#enabling-global-caching).
|
||||
2. Go to your dashboard.
|
||||
3. Click on the **info** icon.
|
||||
4. Click **Cache configuration**.
|
||||
5. Enter a cache duration in hours.
|
||||
6. Click **Save changes**.
|
||||
|
||||
> This setting won't cache the entire dashboard at once. The dashboard cache duration will only apply to questions that exceed the [minimum query duration](#minimum-query-duration).
|
||||
|
||||
If set, your dashboard cache duration will override the:
|
||||
|
||||
- [global cache duration](#cache-time-to-live-ttl-multiplier)
|
||||
- [database cache duration](#caching-per-database)
|
||||
- [question cache duration](#caching-per-question)
|
||||
- [Model persistence](../data-modeling/model-persistence.md)
|
||||
|
||||
@@ -6,7 +6,7 @@ title: "Configuration file"
|
||||
|
||||
{% include plans-blockquote.html feature="Loading from a configuration file" self-hosted-only="true" %}
|
||||
|
||||
On some paid, self-hosted plans, Metabase supports initialization on launch from a config file named `config.yml`. The config file should be located at:
|
||||
On self-hosted Pro and Enterprise plans, Metabase supports initialization on launch from a config file named `config.yml`. The config file should be located at:
|
||||
|
||||
- The current directory (the directory where the running Metabase JAR is located).
|
||||
- The path specified by the `MB_CONFIG_FILE_PATH` [environment variable](./environment-variables.md).
|
||||
@@ -92,9 +92,45 @@ config:
|
||||
|
||||
To determine which keys you can specify for a database, check out the fields available in Metabase itself for the database that you want to add.
|
||||
|
||||
### Setting up uploads on a database
|
||||
|
||||
You can also configure [uploads](../databases/uploads.md) in the config file with the following settings:
|
||||
|
||||
- `uploads_enabled`: Boolean
|
||||
- `uploads_schema_name`: String
|
||||
- `uploads_table_prefix`: String
|
||||
|
||||
Here's an example:
|
||||
|
||||
```
|
||||
{% raw %}
|
||||
version: 1
|
||||
config:
|
||||
users:
|
||||
- first_name: Cam
|
||||
last_name: Era
|
||||
password: 2cans3cans4cans
|
||||
email: cam@example.com
|
||||
databases:
|
||||
- name: test-data (Postgres)
|
||||
engine: postgres
|
||||
details:
|
||||
host: localhost
|
||||
port: 5432
|
||||
user: dbuser
|
||||
password: "{{ env POSTGRES_TEST_DATA_PASSWORD }}"
|
||||
dbname: test-data
|
||||
uploads_enabled: true
|
||||
uploads_schema_name: uploads
|
||||
uploads_table_prefix: uploads_
|
||||
{% endraw %}
|
||||
```
|
||||
|
||||
See [Uploads](../databases/uploads.md).
|
||||
|
||||
## Referring to environment variables in the `config.yml`
|
||||
|
||||
As shown in the Databases example above, environment variables can be specified with `{% raw %}{{ template-tags }}{% endraw %}` like `{% raw %}{{ env POSTGRES_TEST_DATA_PASSWORD }}{% endraw %}` or `{% raw %}[[options {{template-tags}}]]{% endraw %}`.
|
||||
As shown in the Databases examples above, environment variables can be specified with `{% raw %}{{ template-tags }}{% endraw %}` like `{% raw %}{{ env POSTGRES_TEST_DATA_PASSWORD }}{% endraw %}` or `{% raw %}[[options {{template-tags}}]]{% endraw %}`.
|
||||
|
||||
Metabase doesn't support recursive expansion, so if one of your environment variables references _another_ environment variable, you're going to have a bad time.
|
||||
|
||||
@@ -154,7 +190,6 @@ check-for-updates
|
||||
experimental-enable-actions
|
||||
persisted-model-refresh-cron-schedule
|
||||
email-smtp-host
|
||||
enable-query-caching
|
||||
email-smtp-username
|
||||
start-of-week
|
||||
email-smtp-password
|
||||
@@ -183,11 +218,11 @@ site-url
|
||||
site-name
|
||||
```
|
||||
|
||||
But you can set any of the Admin settings with the config file. Check out the list of [environment variable](./config-file.md) to see what you can configure.
|
||||
But you can set any of the Admin settings with the config file. Check out the list of [environment variable](./environment-variables.md) to see what you can configure (though note that not all environment variables can be set via the config file.)
|
||||
|
||||
## Loading a new Metabase from a config file
|
||||
|
||||
Since loading from a config file is a paid feature: for new installations, you'll need to supply Metabase with a token using the `MB_PREMIUM_EMBEDDING_TOKEN` environment variable.
|
||||
Since loading from a config file is a Pro/Enterprise feature: for new installations, you'll need to supply Metabase with a token using the `MB_PREMIUM_EMBEDDING_TOKEN` environment variable.
|
||||
|
||||
```
|
||||
MB_PREMIUM_EMBEDDING_TOKEN="[your token]" java -jar metabase.jar
|
||||
|
||||
@@ -36,4 +36,4 @@ If you have an SSL certificate and would prefer to have Metabase run over HTTPS
|
||||
|
||||
Be sure to replace `path/to/keystore.jks` and `storepass` with the correct path to and password for your [Java KeyStore](https://www.digitalocean.com/community/tutorials/java-keytool-essentials-working-with-java-keystores). With the above settings applied you will be running Metabase on port 8443 over HTTPS using the supplied certificate.
|
||||
|
||||
No idea how to generate a Java KeyStore yourself? This is sort of an advanced topic, but if you're feeling froggy you can read more about how to configure SSL in Jetty [in their own documentation](https://www.eclipse.org/jetty/documentation/jetty-9/index.html#configuring-ssl). Otherwise, you'll probably find it easiest to handle SSL termination outside of Metabase.
|
||||
No idea how to generate a Java KeyStore yourself? This is sort of an advanced topic, but if you're feeling froggy you can read more about how to configure SSL in Jetty [in their own documentation](https://jetty.org/docs/jetty/12/operations-guide/keystore/index.html). Otherwise, you'll probably find it easiest to handle SSL termination outside of Metabase.
|
||||
|
||||
@@ -128,4 +128,4 @@ People who are sandboxed won't see suggestions.
|
||||
- [Dashboard subscriptions](../dashboards/subscriptions.md)
|
||||
- [Notification permissions](../permissions/notifications.md)
|
||||
- [Setting up Slack](./slack.md)
|
||||
- [Auditing Metabase](../usage-and-performance-tools/audit.md)
|
||||
- [Usage Analytics](../usage-and-performance-tools/usage-analytics.md)
|
||||
|
||||
@@ -9,7 +9,7 @@ redirect_from:
|
||||
|
||||
{% include plans-blockquote.html feature="Customizable font" %}
|
||||
|
||||
On paid plans, you can customize the font Metabase uses (the default is [Lato](https://fonts.google.com/specimen/Lato)). You can choose from a curated set of Google Fonts that accommodate the regular, bold, and heavy font weights that Metabase relies on for its various UI elements.
|
||||
On Pro and Enterprise plans, you can customize the font Metabase uses (the default is [Lato](https://fonts.google.com/specimen/Lato)). You can choose from a curated set of Google Fonts that accommodate the regular, bold, and heavy font weights that Metabase relies on for its various UI elements.
|
||||
|
||||
## Included fonts
|
||||
|
||||
@@ -93,7 +93,6 @@ For latin text, we'd copy the relevant src URLs for each style, in this case:
|
||||
- For 400: [https://fonts.gstatic.com/s/robotomono/v21/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0me8iUI0.woff2](https://fonts.gstatic.com/s/robotomono/v21/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0me8iUI0.woff2)
|
||||
- For 700: [https://fonts.gstatic.com/s/robotomono/v21/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0me8iUI0.woff2](https://fonts.gstatic.com/s/robotomono/v21/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0me8iUI0.woff2)
|
||||
|
||||
|
||||
And paste those URLS in the relevant input fields in **Admin settings** > **Settings** > **Appearance** > **Font** section where it says "Tell us where to find the file for each font weight. You don’t need to include all of them, but it’ll look better if you do."
|
||||
|
||||
## Hosting fonts on GitHub
|
||||
|
||||
BIN
docs/configuring-metabase/images/data-caching-settings.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
@@ -56,6 +56,12 @@ Now that you have your database info you can connect to your database. Sweet, sw
|
||||
|
||||
For more on connecting to databases, see [Adding and managing databases](../databases/connecting.md).
|
||||
|
||||
## Activate your license
|
||||
|
||||
If you're self-hosting Metabase on the [Pro](https://www.metabase.com/product/pro) or [Enterprise](https://www.metabase.com/product/enterprise) plan, Metabase will prompt you for your license. This step is just a convenience. You don't need to enter your license here; you can [activate your license](../paid-features/activating-the-enterprise-edition.md) at any time. Just know that all of your Pro and Enterprise features won't work until you've activated your license.
|
||||
|
||||
If you're running Pro on [Metabase Cloud](https://www.metabase.com/cloud), we'll handle this step for you. Your Pro features should already be available.
|
||||
|
||||
## Usage data preferences
|
||||
|
||||
One last quick thing that you’ll have to decide is if it’s okay for us to collect some anonymous info about how you use the product — it helps us make Metabase better. Like the box says:
|
||||
|
||||
@@ -91,4 +91,4 @@ Once your Metabase app is added to the private channel, you'll need to type out
|
||||
- [Dashboard subscriptions](../dashboards/subscriptions.md)
|
||||
- [Notification permissions](../permissions/notifications.md)
|
||||
- [Setting up email](./email.md)
|
||||
- [Auditing Metabase](../usage-and-performance-tools/audit.md)
|
||||
- [Usage analytics](../usage-and-performance-tools/usage-analytics.md)
|
||||
|
||||
@@ -26,7 +26,7 @@ Configure Metabase on launch via environment variables.
|
||||
|
||||
## [Configuration file](./config-file.md)
|
||||
|
||||
On self-hosted paid plans, you can configure Metabase via a configuration file.
|
||||
On self-hosted Pro and Enterprise plans, you can configure Metabase via a configuration file.
|
||||
|
||||
## [Metabase logs configuration](./log-configuration.md)
|
||||
|
||||
|
||||
@@ -34,14 +34,13 @@ You can select from a variety of handsome buttons:
|
||||
|
||||
For most actions, when people click on a button, they'll be prompted to input values in the fields defined by that action.
|
||||
|
||||
|
||||
Many types of actions rely on knowing the entity IDs for the model to determine which records to update or delete. To have people select the ID for the action, you'll need to:
|
||||
|
||||
1. Click on the pencil icon to edit the dashboard.
|
||||
2. Add an action to the dashboard (if you haven't already).
|
||||
2. [Add a filter](./filters.md) to a dashboard, wire it up to any cards that you want to, and click **Done** in the bottom of the sidebar.
|
||||
3. Hover over the action button and click on the **gear** icon, and select **Change action**.
|
||||
4. Click on the field's dropdown to select where the action should get it's value. Here you can select "Ask the user" or have it automatically populated by a dashboard filter. In this case, we'll select our "ID" filter.
|
||||
3. [Add a filter](./filters.md) to a dashboard, wire it up to any cards that you want to, and click **Done** in the bottom of the sidebar.
|
||||
4. Hover over the action button and click on the **gear** icon, and select **Change action**.
|
||||
5. Click on the field's dropdown to select where the action should get it's value. Here you can select "Ask the user" or have it automatically populated by a dashboard filter. In this case, we'll select our "ID" filter.
|
||||
|
||||

|
||||
|
||||
@@ -51,7 +50,12 @@ If you also wire that filter up to a card with a model on the dashboard, you can
|
||||
|
||||
You can add as many buttons as you want, and wire them up to one or more filters.
|
||||
|
||||
## Actions are unavailable for public dashboards and dashboards in static embeds
|
||||
|
||||
While you can add actions to dashboards and use them in your Metabase, actions won't work on dashboards accessed via [public links](./introduction.md#sharing-dashboards-with-public-links), or dashboards in static embeds.
|
||||
|
||||
If you want people outside of your Metabase to use an action, you can create a [public form for an action](../actions/custom.md#make-public), or expose actions via [interactive embedding](../embedding/interactive-embedding.md).
|
||||
|
||||
## Further reading
|
||||
|
||||
- [Actions](../actions/start.md)
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ Combining fullscreen mode and auto refresh is a great way to keep your team in s
|
||||
|
||||
{% include plans-blockquote.html feature="Caching dashboard results" %}
|
||||
|
||||
See [Caching per dashboard](../configuring-metabase/caching.md#caching-per-dashboard).
|
||||
See [Caching per dashboard](../configuring-metabase/caching.md#dashboard-caching-policy).
|
||||
|
||||
## Sharing dashboards with public links
|
||||
|
||||
|
||||
@@ -106,9 +106,9 @@ To remove a subscription from a dashboard, select the subscription you'd like to
|
||||
|
||||
## Viewing existing dashboard subscriptions
|
||||
|
||||
{% include plans-blockquote.html feature="Audit logs" %}
|
||||
{% include plans-blockquote.html feature="Usage analytics" %}
|
||||
|
||||
To view a list of all alerts and dashboard subscriptions that people have set up in your Metabase, click on the **gear** icon in the upper right and select **Admin settings** > **Audit** > **Subscriptions & Alerts**. See [Audit logs](../usage-and-performance-tools/audit.md).
|
||||
You can view a list of all alerts and dashboard subscriptions that people have set up in your Metabase in **Metabase analytics** collection. See [Usage analytics](../usage-and-performance-tools/usage-analytics.md).
|
||||
|
||||
## Customize filter values for each dashboard subscription
|
||||
|
||||
@@ -135,4 +135,4 @@ See [Notification permissions](../permissions/notifications.md).
|
||||
- [Alerts](../questions/sharing/alerts.md)
|
||||
- [Setting up email](../configuring-metabase/email.md)
|
||||
- [Setting up Slack](../configuring-metabase/slack.md)
|
||||
- [Auditing Metabase](../usage-and-performance-tools/audit.md)
|
||||
- [Usage analytics](../usage-and-performance-tools/usage-analytics.md)
|
||||
|
||||
|
Before Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 97 KiB |
@@ -61,3 +61,4 @@ For example, if you upload a CSV with JSON in it, you might need to update the d
|
||||
|
||||
- [PostgreSQL](../databases/connections/postgresql.md)
|
||||
- [MySQL](../databases/connections/mysql.md)
|
||||
- [Druid (JDBC)](../databases/connections/druid.md)
|
||||
|
||||
73
docs/data-modeling/model-persistence.md
Normal file
@@ -0,0 +1,73 @@
|
||||
---
|
||||
title: Model persistence
|
||||
---
|
||||
|
||||
# Model persistence
|
||||
|
||||
> Currently available for PostgreSQL, MySQL, and Redshift.
|
||||
|
||||
Metabase can persist the results of your models so that your models (and the questions based on those models) load faster.
|
||||
|
||||
Metabase will store model results in tables in a bespoke schema in your data warehouse (not the Metabase application database). When people ask questions based on your models, Metabase will use the tables with the stored results instead of re-running the model's query.
|
||||
|
||||
> Model persistence doesn't work with [data sandboxing](../permissions/data-sandboxes.md).
|
||||
|
||||
## Turn on model persistence in Metabase
|
||||
|
||||
To persist models for faster loading, you'll need to turn on model persistence for:
|
||||
|
||||
1. [Your Metabase](#turn-on-model-persistence-for-your-metabase)
|
||||
2. [Individual databases](#turn-on-model-persistence-for-each-database)
|
||||
3. [(Optional) individual models](#turn-on-model-persistence-for-individual-models)
|
||||
|
||||
### Turn on model persistence for your Metabase
|
||||
|
||||
To turn on model persistence for your Metabase, go to **Admin settings** > **Performance** > **Model persistence**.
|
||||
|
||||
You can set models to refresh based on one of the default frequencies (every 1 hour, 2 hours, etc.), or select the **Custom** option to use [cron syntax](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) to specify your own update frequency.
|
||||
|
||||
The cron scheduler uses the [Report Timezone](../configuring-metabase/localization.md#report-timezone) if selected. Otherwise the scheduler will use the System Timezone (which defaults to GMT in [Metabase Cloud](https://www.metabase.com/cloud)).
|
||||
|
||||
We recommend scheduling your models to refresh on a frequency that makes sense with how often your source tables update with new data.
|
||||
|
||||
If someone [changes the query definition of a model](./models.md#edit-a-models-query), any question based on that model will re-run the model's query until the next scheduled model refresh.
|
||||
|
||||
## Turn on model persistence for each database
|
||||
|
||||
Once you've turned on model persistence for your Metabase, you'll need to set it up for each specific database, as Metabase will need to create a schema in your data warehouse to store the persisted models.
|
||||
|
||||
1. Go to **Admin settings** > **Databases** > [your database] > **Turn model persistence on**. If the credentials you've given Metabase to connect to your database are permissive, Metabase should do all the work for you: Metabase will check if the schema already exists, or otherwise attempt to create it. If the connection's credentials _lack_ the necessary permissions to create the schema in your database, you'll need to create the schema in the database yourself.
|
||||
|
||||
2. To manually create the schema in your data warehouse, click on the **info icon** to get the schema name.
|
||||
|
||||
3. Create the schema in your database---make sure you use the exact schema name from step 1. For example, if you're running PostgreSQL as your data warehouse, you'd create the schema by running `CREATE SCHEMA IF NOT EXISTS schema_name`, with `schema_name` being whatever Metabase showed you in the info icon.
|
||||
|
||||
4. Ensure that the credentials Metabase uses to connect to your data warehouse can manage and write to that schema.
|
||||
|
||||
## Turn on model persistence for individual models
|
||||
|
||||
{% include plans-blockquote.html feature="Individual model persistence" %}
|
||||
|
||||
You can also toggle persistence on or off for individual models. When viewing a model, click on the **...** in the upper right and select **Turn model persistence on/off** (you'll need [Curate access](../permissions/collections.md#curate-access) to the model's collection to do this).
|
||||
|
||||
Toggling persistence for individual models is useful for models with data that updates at different frequencies than the schedule you set for other models in that database, or for models that are used more or less than other models in that database.
|
||||
|
||||
## Refreshing a model's persisted results
|
||||
|
||||
To refresh a model's results, go to the model and click on the **i** info icon. In the info sidebar that opens, you'll see a note about when Metabase last refreshed the model's results, and an icon to refresh the results.
|
||||
|
||||
## View model persistence logs
|
||||
|
||||
You can view the logs for model persistence by clicking on the **gear** icon in the upper right and selecting **Admin settings** > **Tools** > **Model caching logs**. See [Admin tools](../usage-and-performance-tools/tools.md).
|
||||
|
||||
## Difference between persisted models and caching
|
||||
|
||||
Persisted models differ from [cached results](../configuring-metabase/caching.md):
|
||||
|
||||
- **Models are persisted in your data warehouse; cached results are stored in the application database**. Metabase stores cached results in its application database. Metabase persists models in your connected data warehouse as tables.
|
||||
- **Metabase refreshes model results and invalidates cached results**. Metabase will refresh results of models according to the schedule you set. That is, Metabase will re-run the model's query and store the results in your data warehouse. For cached results of saved questions and dashboards, Metabase won't run the queries automatically; it will cache results when people view the question or dashboard, and invalidate the cached results according to the caching policy you set.
|
||||
|
||||
## Further reading
|
||||
|
||||
- [Models](./models.md)
|
||||
- [Caching policies](../configuring-metabase/caching.md)
|
||||
@@ -14,6 +14,7 @@ Models:
|
||||
- Show up higher in search results and get highlighted when other users start new questions to promote reuse.
|
||||
- Live in collections to keep them separate from messy database schemas.
|
||||
- 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].
|
||||
|
||||
@@ -23,7 +24,7 @@ You can use models to:
|
||||
|
||||
- Create, uh, models, with model here meaning an intuitive description of some concept in your business that you codify as a set of columns. An example model could be a "customer", which is a table that pulls together customer information from multiple tables and adds computed columns, like adding a lifetime value (LTV) column. This model represents the [measures and dimensions][measures-dimensions] that you think are relevant to your understanding of your customers.
|
||||
- Let people explore the results of SQL queries with the drill-through menu and query builder (provided you [set the column types](#column-type)).
|
||||
- Create summary tables that aggregate data from multiple tables.
|
||||
- Create summary tables that pull in or aggregate data from multiple tables.
|
||||
- Clean up tables with unnecessary columns and rows filtered out.
|
||||
|
||||
The idea with models is to give other people a good "starting point table" that makes it easier to answer any questions they have about the subject being modeled.
|
||||
@@ -171,59 +172,9 @@ See [History](../exploration-and-organization/history.md).
|
||||
|
||||
Just like with a question, admins can verify models. Verifying a model will give it a check mark to let others know an admin vetted the model. If anyone makes any changes to the model, the check mark will disappear. An admin will have to verify the question again to restore the check mark.
|
||||
|
||||
## Model caching
|
||||
## Model persistence
|
||||
|
||||
_Currently available for PostgreSQL, MySQL, and Redshift_.
|
||||
|
||||
Metabase can cache the results of your models so that the models load faster. Metabase caches models by creating tables in a bespoke schema in your data warehouse, and saves the results of the queries that underlie your models in those tables. When people ask questions based on your models, Metabase will substitute those cached results in place of running the model's query.
|
||||
|
||||
To set up model caching:
|
||||
|
||||
1. [Enable model caching in Metabase](#enable-model-caching-in-metabase).
|
||||
2. [Create a schema to store cached models](#create-a-schema-to-store-cached-models).
|
||||
|
||||
> Model caching doesn't work with [data sandboxing](../permissions/data-sandboxes.md).
|
||||
|
||||
### Enable model caching in Metabase
|
||||
|
||||
Go to **Admin settings** > **Settings** > **Caching** > **Models** to turn the feature on.
|
||||
|
||||

|
||||
|
||||
You can set models to refresh based on one of the default frequencies, or select the **Custom** option to use [cron syntax](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) to specify your own caching update frequency. We recommend scheduling the cache to refresh on a frequency that makes sense with how often your source tables update with new data. The cron scheduler uses the [Report Timezone](../configuring-metabase/localization.md#report-timezone) if selected and otherwise uses the System Timezone (which defaults to GMT in Metabase Cloud).
|
||||
|
||||
If someone [changes the query definition of a model](#edit-a-models-query), any question based on that model will skip the cache until the next cache refresh.
|
||||
|
||||
### Create a schema to store cached models
|
||||
|
||||
Go to **Admin settings** > **Databases** > your database > **Turn model caching on**.
|
||||
|
||||

|
||||
|
||||
If the credentials you've given Metabase to connect to your database are permissive, Metabase should do all the work for you: Metabase will check if the schema exists, or otherwise attempt to create it.
|
||||
|
||||
If the connection's credentials lack the necessary permissions to create the schema in your database, you'll need to create the schema in the database yourself:
|
||||
|
||||
1. Click on the **info icon** to get the schema name.
|
||||
|
||||
> In the above image, the schema name is "metabase_cache_134ba_7", but your schema name will differ.
|
||||
|
||||
2. Create the schema in your database---make sure you use the exact schema name from step 1.
|
||||
3. Ensure that the credentials Metabase uses can manage and write to that schema.
|
||||
|
||||
### Refreshing a model's cached results
|
||||
|
||||
To refresh a model's cached results, go to the model and click on the **i** info icon. In the info sidebar that opens, you'll see a note about when Metabase last refreshed the model's cache, and an icon to refresh the cache.
|
||||
|
||||
### View model caching logs
|
||||
|
||||
You can view the logs for model caching by clicking on the **gear** icon in the upper right and selecting **Admin settings** > **Tools** > **Model caching logs**. See [Admin tools](../usage-and-performance-tools/tools.md).
|
||||
|
||||
### Caching individual models
|
||||
|
||||
{% include plans-blockquote.html feature="Caching individual models" %}
|
||||
|
||||
On some paid plans, you can also toggle caching on or off for individual models. When viewing a model, click on the **...** in the upper right and select **Turn model caching on/off**.
|
||||
See [Model persistence](./model-persistence.md)
|
||||
|
||||
## Further reading
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@ Metabase provides tools for organizing your data and making it easier for people
|
||||
|
||||
Models curate data from another table or tables from the same database to anticipate the kinds of questions people will ask of the data. You can think of them as derived tables, or a special kind of saved question meant to be used as the starting point for new questions.
|
||||
|
||||
## [Model persistence](./model-persistence.md)
|
||||
|
||||
Persist model results for faster loading times.
|
||||
|
||||
## [Table metadata admin settings](./metadata-editing.md)
|
||||
|
||||
Guide people to the right data by adding display names, hiding outdated tables, configuring filter types, and more.
|
||||
|
||||