Compare commits
392 Commits
python-sec
...
52-e2e-tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c6ce9681f | ||
|
|
149a9b1666 | ||
|
|
fd887f23f8 | ||
|
|
5aeb9b6f83 | ||
|
|
955fa8ad27 | ||
|
|
1c3df30d86 | ||
|
|
13a2547fab | ||
|
|
5a8b6c6c5d | ||
|
|
ddbc480176 | ||
|
|
536ace8b9c | ||
|
|
f7f277fa3a | ||
|
|
754cf8ed12 | ||
|
|
986d532280 | ||
|
|
d1a5765613 | ||
|
|
84c3067d71 | ||
|
|
3c764ab2f4 | ||
|
|
b19cec43b0 | ||
|
|
2de7e5c735 | ||
|
|
c496b8f926 | ||
|
|
d127102df9 | ||
|
|
014f535a11 | ||
|
|
1a50f174fa | ||
|
|
b795acf008 | ||
|
|
ec748bae87 | ||
|
|
13b3f47296 | ||
|
|
b5356cc97b | ||
|
|
198be6360e | ||
|
|
7f821ff352 | ||
|
|
524c8f817c | ||
|
|
85bc61ff3e | ||
|
|
4085da97da | ||
|
|
8c3f31813b | ||
|
|
125e856a9e | ||
|
|
9c08bb5b5b | ||
|
|
ca8c811fa5 | ||
|
|
2904410d6f | ||
|
|
84e46f8b52 | ||
|
|
eca95f9f88 | ||
|
|
6d8e4da60e | ||
|
|
d817b1d6b5 | ||
|
|
87bbdc199e | ||
|
|
44457ce71d | ||
|
|
0c28c43481 | ||
|
|
073f6ed20b | ||
|
|
32bbf25f25 | ||
|
|
70f581e84c | ||
|
|
f5d42c0ed9 | ||
|
|
7540f257e2 | ||
|
|
044927fdea | ||
|
|
8c1a0ce978 | ||
|
|
dd6c1b383c | ||
|
|
8af929eac5 | ||
|
|
5cb2f31949 | ||
|
|
8104261230 | ||
|
|
751091a69c | ||
|
|
b6b0b59a6e | ||
|
|
94678090d6 | ||
|
|
6ff2ac92d0 | ||
|
|
e18ec8c425 | ||
|
|
dcb19b094b | ||
|
|
ea4d7edd59 | ||
|
|
9c291cec8c | ||
|
|
2128c42178 | ||
|
|
2935c824b2 | ||
|
|
5ddf601f2b | ||
|
|
fead0b0da8 | ||
|
|
e2a6a972d2 | ||
|
|
b561470e24 | ||
|
|
5e12f48c85 | ||
|
|
3376cedf29 | ||
|
|
ded92218fc | ||
|
|
42545547ba | ||
|
|
e8ebe5eb96 | ||
|
|
3a54f9ac5d | ||
|
|
7387d4aedd | ||
|
|
c6c59b6148 | ||
|
|
612fce943f | ||
|
|
ea1383d476 | ||
|
|
ce274b7e3f | ||
|
|
eeb6b23040 | ||
|
|
78dcdb7048 | ||
|
|
74b8afc77d | ||
|
|
53cd787f14 | ||
|
|
23aad0b023 | ||
|
|
1a9cb727b9 | ||
|
|
c705839d54 | ||
|
|
ee9d83e1b2 | ||
|
|
d8160ceee4 | ||
|
|
49b41aeebd | ||
|
|
61e6392889 | ||
|
|
8da74f2a2c | ||
|
|
103e4ea17f | ||
|
|
15ffab7ce1 | ||
|
|
e5b2155be7 | ||
|
|
f991a31f78 | ||
|
|
900854cda9 | ||
|
|
43ca74b739 | ||
|
|
bb6db86f3d | ||
|
|
47c849e928 | ||
|
|
ef5fbaa64a | ||
|
|
e85b71b889 | ||
|
|
c1bb251b98 | ||
|
|
c025d14dd8 | ||
|
|
51ee326c80 | ||
|
|
913bccff53 | ||
|
|
846f59d7a1 | ||
|
|
bcfe824f21 | ||
|
|
07cbbb19a9 | ||
|
|
abfc819d6f | ||
|
|
593a73ad49 | ||
|
|
f5a6fe5bd7 | ||
|
|
16faa91c76 | ||
|
|
db85e4751c | ||
|
|
66ceea21fb | ||
|
|
ff6a641345 | ||
|
|
5b9361a321 | ||
|
|
e6329a6c62 | ||
|
|
3b32e844b5 | ||
|
|
7a8c415e2b | ||
|
|
e7741933ad | ||
|
|
37a5031744 | ||
|
|
ae2c0b9064 | ||
|
|
db5213ebf2 | ||
|
|
f6039a8b27 | ||
|
|
0a5091e9b7 | ||
|
|
57a2704ecc | ||
|
|
abdb35cd46 | ||
|
|
4749f6127b | ||
|
|
9e5c80a02c | ||
|
|
31445dbf36 | ||
|
|
1c1c5c73c6 | ||
|
|
ad08889c49 | ||
|
|
7746127c36 | ||
|
|
8945237d64 | ||
|
|
db62b93d77 | ||
|
|
e6cdbbc9ed | ||
|
|
cc77eeb655 | ||
|
|
e03d60b58d | ||
|
|
425b0d57aa | ||
|
|
f300cad7a7 | ||
|
|
0ab4227609 | ||
|
|
0368036c27 | ||
|
|
d70c78f321 | ||
|
|
2c21568f06 | ||
|
|
6d36ae40ab | ||
|
|
2d4e621699 | ||
|
|
d8ef748f8b | ||
|
|
c9794736c5 | ||
|
|
865d4c2efe | ||
|
|
35495470d6 | ||
|
|
c9da3ba457 | ||
|
|
17a4842e9e | ||
|
|
70889998f8 | ||
|
|
115319e957 | ||
|
|
8ec7f12861 | ||
|
|
047e7bc43d | ||
|
|
e51badb8d1 | ||
|
|
722e7cbcf5 | ||
|
|
10295f4d0f | ||
|
|
d99dca5857 | ||
|
|
3efebabbd4 | ||
|
|
aed2acff36 | ||
|
|
ed4a7bf795 | ||
|
|
b5e537b56b | ||
|
|
5086e9d547 | ||
|
|
3e0a25dbd5 | ||
|
|
2f8c560ddd | ||
|
|
97e8cae76b | ||
|
|
355ba93c08 | ||
|
|
2f6f878b43 | ||
|
|
68b2f66dca | ||
|
|
38f63e4ab7 | ||
|
|
4dcb015dc9 | ||
|
|
8ad2516b8e | ||
|
|
1e8a62de75 | ||
|
|
22b0535c3c | ||
|
|
cbcbc23740 | ||
|
|
7481fbd341 | ||
|
|
f4e04450ed | ||
|
|
e3f81d8275 | ||
|
|
a153392382 | ||
|
|
4005c0a734 | ||
|
|
de9424e1c9 | ||
|
|
23696368f3 | ||
|
|
0cb7dbf187 | ||
|
|
0d358d4fa3 | ||
|
|
c05667343f | ||
|
|
9e89e4a16f | ||
|
|
c1d70d364f | ||
|
|
c2f9e583c5 | ||
|
|
d0e4983bf1 | ||
|
|
a0c22c1da3 | ||
|
|
8b34ce545f | ||
|
|
7c859a25bf | ||
|
|
80581e5b3f | ||
|
|
e7154f61ec | ||
|
|
79f23e5374 | ||
|
|
c32541004c | ||
|
|
2149fabcec | ||
|
|
0db4403866 | ||
|
|
b926fa2e65 | ||
|
|
ab954c5a47 | ||
|
|
d0220ff31b | ||
|
|
3bb077b92e | ||
|
|
13d29702d5 | ||
|
|
f229c492e0 | ||
|
|
aa73307807 | ||
|
|
c7330a1245 | ||
|
|
a3da18604a | ||
|
|
df5ab529bf | ||
|
|
ef5c82a27c | ||
|
|
49fa2feada | ||
|
|
79b2b15885 | ||
|
|
ed5fe91bf0 | ||
|
|
36cc34b02d | ||
|
|
6af3f9e5c3 | ||
|
|
b858a42c22 | ||
|
|
77e4a6dcb6 | ||
|
|
52b2b0fdfb | ||
|
|
d3756e7e2f | ||
|
|
1d398435a5 | ||
|
|
94aa8fde52 | ||
|
|
1540d83e19 | ||
|
|
a82db08236 | ||
|
|
cf33d59a6b | ||
|
|
9c0c5ad32d | ||
|
|
594e80a5c8 | ||
|
|
135bbbc166 | ||
|
|
34f019e07c | ||
|
|
4476971f5a | ||
|
|
a1525c7348 | ||
|
|
6f76bb6288 | ||
|
|
155b7f92ba | ||
|
|
44d0439f37 | ||
|
|
aa77297ea2 | ||
|
|
0ec00d015b | ||
|
|
7d7978c274 | ||
|
|
fcbcab8ccc | ||
|
|
af0256d44f | ||
|
|
19065579d9 | ||
|
|
6c05340d04 | ||
|
|
ff3a249260 | ||
|
|
871cabb15a | ||
|
|
9b768f1d44 | ||
|
|
4e625d8a4b | ||
|
|
00874044a3 | ||
|
|
7d88901955 | ||
|
|
bac63b6e77 | ||
|
|
2db7312aaa | ||
|
|
8dca3ea88c | ||
|
|
109ba1a8b5 | ||
|
|
219e591555 | ||
|
|
b7860f0011 | ||
|
|
dd5ad8410a | ||
|
|
178164d942 | ||
|
|
b65981a8fa | ||
|
|
125f512df8 | ||
|
|
98c93fdb12 | ||
|
|
37bb29eb78 | ||
|
|
bd09c2ab5b | ||
|
|
5f37af834f | ||
|
|
11ccfdb191 | ||
|
|
095d521010 | ||
|
|
46ad314535 | ||
|
|
f18b63e49b | ||
|
|
186fcd9d17 | ||
|
|
c15a51f210 | ||
|
|
8ea66a3867 | ||
|
|
34657a48c8 | ||
|
|
1e275b9e49 | ||
|
|
1563e743fe | ||
|
|
8cd877ec83 | ||
|
|
3837ed899d | ||
|
|
a852d1600b | ||
|
|
68a464e477 | ||
|
|
21f5cb7bdd | ||
|
|
4114de8eba | ||
|
|
c84aaa0100 | ||
|
|
8c17699aa6 | ||
|
|
63833f46c1 | ||
|
|
9b0b0cff8b | ||
|
|
9930ed8a4f | ||
|
|
489986cfa9 | ||
|
|
78d155bcda | ||
|
|
909441411b | ||
|
|
629b7939a2 | ||
|
|
f5f7d4d1df | ||
|
|
3cc3235615 | ||
|
|
eac6e3b646 | ||
|
|
3a985c3114 | ||
|
|
35a4c284f9 | ||
|
|
b1bcbda7f7 | ||
|
|
3d69c2bcbc | ||
|
|
32effb1fde | ||
|
|
d3a75e4ef0 | ||
|
|
20c3e508a2 | ||
|
|
93a8ab510c | ||
|
|
4bff8d42d8 | ||
|
|
394e424bf9 | ||
|
|
c086571821 | ||
|
|
1f1c61f55f | ||
|
|
ed4abaad6f | ||
|
|
bcb8c01eda | ||
|
|
5fd36b241d | ||
|
|
1cc98bca6c | ||
|
|
278e0822ae | ||
|
|
f387892cbc | ||
|
|
6aad0b854f | ||
|
|
4bbc92122c | ||
|
|
fbea05994a | ||
|
|
c12c23d9df | ||
|
|
dd36c4db4b | ||
|
|
109479dad5 | ||
|
|
40c08c31bb | ||
|
|
1d9a3d049d | ||
|
|
028a836e82 | ||
|
|
80ccaeb237 | ||
|
|
9787d0f088 | ||
|
|
dfbda37934 | ||
|
|
28b4824e47 | ||
|
|
d3cd56608a | ||
|
|
ba9f08dd5b | ||
|
|
5bc320bbe7 | ||
|
|
30c04a1dcc | ||
|
|
ec681fc0bc | ||
|
|
3e0978ad62 | ||
|
|
af09c0199d | ||
|
|
73afba4194 | ||
|
|
24c55f8a40 | ||
|
|
e48212bc34 | ||
|
|
0f55159339 | ||
|
|
22373dcd51 | ||
|
|
c2a70fa7c4 | ||
|
|
dc9440faad | ||
|
|
46304b1b05 | ||
|
|
9a7119d5af | ||
|
|
e8a06bc519 | ||
|
|
005ee61971 | ||
|
|
401c471eb6 | ||
|
|
7a44bedfe6 | ||
|
|
d8adb55990 | ||
|
|
bffe2cb02f | ||
|
|
ad202c8bf3 | ||
|
|
bd4b9c63fa | ||
|
|
e8c63c322c | ||
|
|
1d19852bab | ||
|
|
132bb1a268 | ||
|
|
5fcad73c9f | ||
|
|
568aa2bcc7 | ||
|
|
9759a153a0 | ||
|
|
768788653f | ||
|
|
e3f75b124e | ||
|
|
0e033e4ab7 | ||
|
|
99a90504da | ||
|
|
2ead76eda9 | ||
|
|
1cc75c84f0 | ||
|
|
e9dc7f4d48 | ||
|
|
bba6486a13 | ||
|
|
63414a34a1 | ||
|
|
308e1e6e22 | ||
|
|
83eb6cb980 | ||
|
|
017fbe9a2f | ||
|
|
a784851a82 | ||
|
|
1d917bc519 | ||
|
|
ba244567a7 | ||
|
|
5db31666e2 | ||
|
|
65559cbc68 | ||
|
|
51b66b3e2e | ||
|
|
f581fe5645 | ||
|
|
08fc48e9ea | ||
|
|
ebea9a221d | ||
|
|
331a887c87 | ||
|
|
a4a2a0017c | ||
|
|
21de14c27b | ||
|
|
c8296d4779 | ||
|
|
803732fe18 | ||
|
|
9af0d46dda | ||
|
|
8ae59fc04b | ||
|
|
793f81809d | ||
|
|
3bce97fb01 | ||
|
|
ce1db0bab6 | ||
|
|
0aa4246b90 | ||
|
|
0617f36829 | ||
|
|
125ce1acbf | ||
|
|
0adadc9ad1 | ||
|
|
77b70d05a2 | ||
|
|
0341bf3e33 | ||
|
|
df24b09171 | ||
|
|
885905ebe5 | ||
|
|
e56676bdd8 | ||
|
|
127ab0be5d | ||
|
|
6a1de543ac |
@@ -128,10 +128,12 @@
|
||||
clojure.core.async/to-chan!
|
||||
clojure.core.async/to-chan!!
|
||||
metabase.channel.core/send!
|
||||
metabase.models.notification/create-notification!
|
||||
metabase.driver.sql-jdbc.execute/execute-prepared-statement!
|
||||
metabase.models.notification/create-notification!
|
||||
metabase.pulse.send/send-pulse!
|
||||
metabase.query-processor.store/store-database!
|
||||
;; Safe in tests, where we typically use a private, temporary index per thread.
|
||||
metabase.search.core/reindex!
|
||||
metabase.util/run-count!
|
||||
next.jdbc/execute!}}
|
||||
|
||||
@@ -342,9 +344,8 @@
|
||||
metabase.query-analysis.failure-map}
|
||||
metabase.related #{metabase.related}
|
||||
metabase.sample-data #{metabase.sample-data}
|
||||
metabase.search #{metabase.search
|
||||
;; deprecating naked metabase.search namespace in favor of this.
|
||||
metabase.search.core
|
||||
metabase.search #{metabase.search.core
|
||||
;; Need to expose this submodule, to break circular dependencies with models.
|
||||
metabase.search.spec}
|
||||
metabase.server #{metabase.server
|
||||
metabase.server.handler
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
database-enable-actions
|
||||
deprecation-notice-version
|
||||
dismissed-custom-dashboard-toast
|
||||
dismissed-onboarding-sidebar-link
|
||||
email-configured?
|
||||
email-from-address
|
||||
email-from-name
|
||||
@@ -161,6 +162,7 @@
|
||||
token-features
|
||||
token-status
|
||||
toucan-name
|
||||
trial-banner-dismissal-timestamp
|
||||
uncached-setting
|
||||
user-visibility
|
||||
version
|
||||
|
||||
2
.github/actions/build-e2e-matrix/action.yml
vendored
@@ -35,6 +35,7 @@ runs:
|
||||
["dashboard-cards", {} ],
|
||||
["dashboard-filters", {} ],
|
||||
["dashboard-filters-2", {} ],
|
||||
["dashboard-filters-matrix", {} ],
|
||||
["embedding", {} ],
|
||||
["embedding-sdk", { context: "embedding-sdk" } ],
|
||||
["filters", {} ],
|
||||
@@ -51,6 +52,7 @@ runs:
|
||||
["question-reproductions", {} ],
|
||||
["search", {}],
|
||||
["sharing", {} ],
|
||||
["stats", {} ],
|
||||
["visualizations-charts", {} ],
|
||||
["visualizations-tabular", {} ],
|
||||
["oss-subset", { edition: 'oss', context: "special" } ],
|
||||
|
||||
@@ -90,7 +90,7 @@ runs:
|
||||
|
||||
if ${{ inputs.webhook }}; then
|
||||
echo -e "${Y}Starting webhook test container..." &&
|
||||
docker run -d -p 9080:8080/tcp tarampampam/webhook-tester serve --create-session 00000000-0000-0000-0000-000000000000 &&
|
||||
docker run -d -p 9080:8080/tcp tarampampam/webhook-tester:1.1.0 serve --create-session 00000000-0000-0000-0000-000000000000 &&
|
||||
while ! nc -z localhost 9080; do sleep 1; done &&
|
||||
echo -e "${G}Webhook tester is up and running!"
|
||||
fi
|
||||
|
||||
4
.github/auto_request_review.yml
vendored
@@ -5,9 +5,9 @@
|
||||
files:
|
||||
# migrations related files
|
||||
'resources/migrations/**':
|
||||
- team:core-backend-components
|
||||
- team:core-workflows
|
||||
'src/metabase/db/custom_migrations.clj':
|
||||
- team:core-backend-components
|
||||
- team:core-workflows
|
||||
|
||||
options:
|
||||
ignore_draft: true
|
||||
|
||||
17
.github/team.json
vendored
@@ -12,7 +12,9 @@
|
||||
"metamben",
|
||||
"lbrdnk",
|
||||
"appleby",
|
||||
"uladzimirdev"
|
||||
"uladzimirdev",
|
||||
"wzimrin",
|
||||
"ericnormand"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -24,16 +26,18 @@
|
||||
"name": "Embedding",
|
||||
"label": ".Team/Embedding",
|
||||
"projectUrl": "https://github.com/orgs/metabase/projects/88/views/1",
|
||||
"members": ["WiNloSt", "deniskaber", "oisincoveney", "npretto", "heypoom"]
|
||||
"members": ["WiNloSt", "oisincoveney", "npretto", "heypoom"]
|
||||
},
|
||||
{
|
||||
"name": "BEC",
|
||||
"label": ".Team/BackendComponents",
|
||||
"name": "Workflows",
|
||||
"label": ".Team/Workflows",
|
||||
"projectUrl": "https://github.com/orgs/metabase/projects/50/views/1",
|
||||
"members": [
|
||||
"qnkhuat",
|
||||
"piranha",
|
||||
"crisptrutski"
|
||||
"crisptrutski",
|
||||
"deniskaber",
|
||||
"wotbrew"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -56,7 +60,8 @@
|
||||
"alxnddr",
|
||||
"kulyk",
|
||||
"adam-james-v",
|
||||
"tsplude"
|
||||
"tsplude",
|
||||
"lorem--ipsum"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
5
.github/workflows/backend.yml
vendored
@@ -154,6 +154,7 @@ jobs:
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: be-tests
|
||||
java-version: "${{ matrix.java-version }}"
|
||||
# Depending on which files changed, we might either have to build static-viz
|
||||
# from scratch or download the previously built artifact
|
||||
- name: Build static-viz frontend
|
||||
@@ -194,9 +195,9 @@ jobs:
|
||||
fail-on-error: false
|
||||
|
||||
be-tests-stub:
|
||||
needs: [be-tests]
|
||||
needs: [files-changed, static-viz-files-changed, be-tests]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
always() &&
|
||||
github.event.pull_request.draft == false && needs.be-tests.result == 'skipped'
|
||||
runs-on: ubuntu-22.04
|
||||
name: be-tests-java-${{ matrix.java-version }}-${{ matrix.edition }}
|
||||
|
||||
18
.github/workflows/doc-md-links.yml
vendored
@@ -1,18 +0,0 @@
|
||||
name: Lint doc Markdown links
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- docs/**
|
||||
pull_request:
|
||||
paths:
|
||||
- docs/**
|
||||
jobs:
|
||||
markdown-link-check:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Lint doc links
|
||||
run: yarn run docs-lint-links
|
||||
5
.github/workflows/drivers.yml
vendored
@@ -144,13 +144,16 @@ jobs:
|
||||
MB_DATABRICKS_TEST_HTTP_PATH: ${{ secrets.MB_DATABRICKS_JDBC_TEST_HTTP_PATH }}
|
||||
MB_DATABRICKS_TEST_TOKEN: ${{ secrets.MB_DATABRICKS_JDBC_TEST_TOKEN }}
|
||||
MB_DATABRICKS_TEST_CATALOG: 'metabase_ci'
|
||||
MB_DATABRICKS_TEST_CLIENT_ID: ${{ secrets.MB_DATABRICKS_JDBC_TEST_CLIENT_ID }}
|
||||
MB_DATABRICKS_TEST_OAUTH_SECRET: ${{ secrets.MB_DATABRICKS_JDBC_TEST_OAUTH_SECRET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test Databricks driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-databricks-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
|
||||
250
.github/workflows/e2e-component-tests-embedding-sdk-cross-version.yml
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
name: E2E Cross-version Component Tests for Embedding SDK
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "release-**"
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
branches:
|
||||
- "release-**"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
e2e_all: ${{ steps.changes.outputs.e2e_all }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test which files changed
|
||||
uses: dorny/paths-filter@v3.0.0
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
# if this is a test on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
if: |
|
||||
!cancelled()
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
|
||||
node_version: ${{ fromJson(steps.dependencies.outputs.result).node_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get build dependencies
|
||||
uses: actions/github-script@v7
|
||||
id: dependencies
|
||||
with:
|
||||
script: | # js
|
||||
const {
|
||||
getBuildRequirements,
|
||||
getVersionFromReleaseBranch,
|
||||
} = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const targetBranchName = '${{ github.base_ref || github.ref }}';
|
||||
|
||||
const version = getVersionFromReleaseBranch(targetBranchName);
|
||||
const requirements = getBuildRequirements(version);
|
||||
|
||||
return {
|
||||
java_version: requirements.java,
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
build:
|
||||
needs: [files-changed, get-build-requirements]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
INTERACTIVE: false
|
||||
# make sure that builds on release branches get licenses, because we use them for releases
|
||||
SKIP_LICENSES: ${{ github.event_name == 'pull_request' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
with:
|
||||
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: uberjar
|
||||
java-version: "${{ needs.get-build-requirements.outputs.java_version || 11 }}"
|
||||
|
||||
- name: Build uberjar with ./bin/build.sh
|
||||
run: ./bin/build.sh
|
||||
|
||||
- name: Prepare uberjar artifact
|
||||
uses: ./.github/actions/prepare-uberjar-artifact
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
resolve-sdk-version:
|
||||
if: |
|
||||
!cancelled()
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
sdk_version: ${{ fromJson(steps.dependencies.outputs.result).sdk_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get latest SDK release for this branch
|
||||
uses: actions/github-script@v7
|
||||
id: dependencies
|
||||
with:
|
||||
script: | # js
|
||||
const { getSdkVersionFromReleaseBranchName } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const branchName = '${{ github.base_ref || github.ref }}';
|
||||
|
||||
const sdk_version = await getSdkVersionFromReleaseBranchName({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
branchName,
|
||||
});
|
||||
|
||||
return {
|
||||
sdk_version,
|
||||
};
|
||||
|
||||
e2e-tests:
|
||||
needs: [get-build-requirements, build, resolve-sdk-version]
|
||||
if: |
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
name: e2e-tests-embedding-sdk
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
DISPLAY: ""
|
||||
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
|
||||
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
|
||||
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
|
||||
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
|
||||
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
|
||||
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
|
||||
TZ: US/Pacific # to make node match the instance tz
|
||||
CYPRESS_CI: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Docker containers
|
||||
uses: ./.github/actions/e2e-prepare-containers
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Needed to omit newly added tests for functionality that is not yet released
|
||||
- name: Sparse checkout tests from SDK release commit
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: embedding-sdk-${{ needs.resolve-sdk-version.outputs.sdk_version }}
|
||||
path: sdk-release-e2e
|
||||
sparse-checkout: e2e
|
||||
|
||||
- name: Move tests from the release commit into the repo
|
||||
run: |
|
||||
rm -rf ./e2e/support/helpers/*
|
||||
mv ./sdk-release-e2e/e2e/support/helpers/* ./e2e/support/helpers
|
||||
rm -rf ./e2e/test-component/*
|
||||
mv ./sdk-release-e2e/e2e/test-component/* ./e2e/test-component
|
||||
shell: bash
|
||||
|
||||
- name: Retrieve uberjar artifact for ee
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
- name: Get the version info
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar version.properties
|
||||
mv version.properties resources/
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
|
||||
- name: Prepare JDK ${{ needs.get-build-requirements.outputs.java_version || 11 }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ needs.get-build-requirements.outputs.java_version || 11 }}
|
||||
distribution: "temurin"
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
|
||||
- name: Install Embedding SDK package v${{ needs.resolve-sdk-version.outputs.sdk_version }}
|
||||
run: yarn add @metabase/embedding-sdk-react@${{ needs.resolve-sdk-version.outputs.sdk_version }}
|
||||
|
||||
- name: Run E2E tests for Embedding SDK
|
||||
run: yarn run test-cypress-run-component-sdk --browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit
|
||||
output-name: e2e-embedding-sdk
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
- name: Upload Cypress Artifacts upon failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: cypress-recording-embedding-sdk-cross-version
|
||||
path: |
|
||||
./cypress
|
||||
./logs/test.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Publish Summary
|
||||
if: failure()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | #js
|
||||
const {
|
||||
parseReport,
|
||||
formatSummary
|
||||
} = require("./.github/scripts/handle-mochawesome-report.js");
|
||||
|
||||
const report = parseReport();
|
||||
const summary = formatSummary(report);
|
||||
|
||||
await core.summary.addRaw(summary).write();
|
||||
|
||||
e2e-tests-skipped-stub:
|
||||
needs: [e2e-tests]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.e2e-tests.result == 'skipped'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
name: e2e-component-tests-embedding-sdk-cross-version
|
||||
steps:
|
||||
- run: |
|
||||
echo "Didn't run due to conditional filtering"
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
get-build-requirements:
|
||||
if: |
|
||||
!cancelled() &&
|
||||
contains(github.ref, 'release-x')
|
||||
contains(github.base_ref || github.ref, 'release-x')
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
getBuildRequirements,
|
||||
getVersionFromReleaseBranch,
|
||||
} = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const targetBranchName = '${{ github.base_ref }}';
|
||||
const targetBranchName = '${{ github.base_ref || github.ref }}';
|
||||
|
||||
const version = getVersionFromReleaseBranch(targetBranchName);
|
||||
const requirements = getBuildRequirements(version);
|
||||
|
||||
97
.github/workflows/e2e-matrix-builder.yml
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
name: E2E Matrix Builder
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
chunks:
|
||||
required: true
|
||||
type: number
|
||||
default: 30
|
||||
outputs:
|
||||
matrix:
|
||||
value: ${{ jobs.build-matrix.outputs.matrix }}
|
||||
|
||||
jobs:
|
||||
build-matrix:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
matrix: ${{ steps.matrix.outputs.config }}
|
||||
steps:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '20.x'
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: e2e
|
||||
- name: get test file names
|
||||
id: test-files
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::set-output name=filenames::$(find e2e/test/scenarios -name '*.cy.spec.*' | tr '\n' ',')"
|
||||
- uses: actions/github-script@v7
|
||||
id: matrix
|
||||
with:
|
||||
script: | # js
|
||||
const chunk = (arr, size) => {
|
||||
const chunks = [];
|
||||
const n = Math.ceil(arr.length / size);
|
||||
for (let i = 0; i < n; i++) {
|
||||
chunks.push(arr.slice(i * size, (i + 1) * size));
|
||||
}
|
||||
return chunks;
|
||||
};
|
||||
|
||||
const java = 21;
|
||||
const defaultRunner = "ubuntu-22.04";
|
||||
|
||||
// these are special and shouldn't be chunked out arbitrarily
|
||||
const blacklist = [
|
||||
"/embedding-sdk/",
|
||||
"/cross-version/"
|
||||
];
|
||||
|
||||
const defaultOptions = {
|
||||
"java-version": java,
|
||||
runner: defaultRunner,
|
||||
specs: "./e2e/test/scenarios/**/*.cy.spec.*",
|
||||
edition: "ee",
|
||||
};
|
||||
|
||||
const specialTests = [
|
||||
{ name: "embedding-sdk", specs: "./e2e/test/scenarios/embedding-sdk/**.cy.spec.*" },
|
||||
{ name: "oss-subset", edition: 'oss', tags: "@OSS" },
|
||||
{ name: "slow", tags: "@slow+-@flaky" },
|
||||
{ name: "mongo", tags: "@mongo" },
|
||||
];
|
||||
|
||||
const fileNames = "${{ steps.test-files.outputs.filenames }}"
|
||||
.split(",")
|
||||
.filter(Boolean)
|
||||
.filter(testPath => !blacklist.some(blacklisted => testPath.includes(blacklisted)));
|
||||
|
||||
const fileCount = fileNames.length;
|
||||
|
||||
// subtract the special tests since they all get their own runners
|
||||
const chunkSize = fileCount / (Number('${{ inputs.chunks }}') - specialTests.length);
|
||||
|
||||
|
||||
|
||||
const chunkedFiles = chunk(fileNames, chunkSize);
|
||||
|
||||
const regularTests = chunkedFiles.map((files, index) => ({
|
||||
name: `e2e-group-${index + 1}`,
|
||||
specs: files.join(","),
|
||||
tags: '',
|
||||
}));
|
||||
|
||||
const testSets = [...regularTests, ...specialTests];
|
||||
|
||||
const config = testSets.map((options) => ({
|
||||
...defaultOptions,
|
||||
...options,
|
||||
}));
|
||||
|
||||
console.log("matrix config", config);
|
||||
|
||||
core.setOutput("config", JSON.stringify({ include: config }));
|
||||
155
.github/workflows/e2e-test.yml
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
name: E2E Test
|
||||
run-name: E2E Test - ${{ inputs.name }}
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
name:
|
||||
required: true
|
||||
type: string
|
||||
edition: # oss | ee
|
||||
required: false
|
||||
type: string
|
||||
default: ee
|
||||
specs:
|
||||
required: false
|
||||
default: ./e2e/test/scenarios/**/*.cy.spec.*
|
||||
type: string
|
||||
tags:
|
||||
required: false
|
||||
type: string
|
||||
runner:
|
||||
required: false
|
||||
type: string
|
||||
default: ubuntu-22.04
|
||||
|
||||
jobs:
|
||||
e2e-tests:
|
||||
runs-on: ${{ inputs.runner }}
|
||||
timeout-minutes: 45
|
||||
name: e2e-tests-${{ inputs.name }}-${{ inputs.edition }}
|
||||
env:
|
||||
MB_EDITION: ${{ inputs.edition }}
|
||||
DISPLAY: ""
|
||||
QA_DB_ENABLED: true
|
||||
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
HASH: ${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
|
||||
JOB_NAME: ${{ inputs.name }}
|
||||
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
|
||||
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
|
||||
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
|
||||
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
|
||||
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
|
||||
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
|
||||
MB_SNOWPLOW_AVAILABLE: true
|
||||
MB_SNOWPLOW_URL: "http://localhost:9090" # Snowplow micro
|
||||
TZ: US/Pacific # to make node match the instance tz
|
||||
CYPRESS_CI: true
|
||||
CYPRESS_QA_DB_MONGO: ${{ inputs.name == 'mongo' }}
|
||||
CYPRESS_IS_EMBEDDING_SDK: ${{ inputs.name == 'embedding-sdk' }}
|
||||
mongo: ${{ inputs.name == 'mongo' }}
|
||||
postgres: ${{ inputs.name != 'mongo' }}
|
||||
mysql: ${{ inputs.name != 'mongo' }}
|
||||
openldap: ${{ contains(inputs.specs, 'ldap') }}
|
||||
maildev: true
|
||||
webhook: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Docker containers
|
||||
uses: ./.github/actions/e2e-prepare-containers
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
maildev: true
|
||||
openldap: ${{ env.openldap }}
|
||||
postgres: ${{ env.postgres }}
|
||||
mysql: ${{ env.mysql }}
|
||||
mongo: ${{ env.mongo }}
|
||||
webhook: ${{ env.webhook }}
|
||||
|
||||
- name: Run Embedding SDK Storybook
|
||||
if: inputs.name == 'embedding-sdk'
|
||||
uses: ./.github/actions/run-embedding-sdk-storybook
|
||||
|
||||
- name: Retrieve uberjar artifact for ${{ inputs.edition }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-${{ inputs.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
- name: Get the version info
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar version.properties
|
||||
mv version.properties resources/
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
|
||||
- name: Prepare JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 21
|
||||
distribution: "temurin"
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
|
||||
- name: Run Snowplow micro
|
||||
uses: ./.github/actions/run-snowplow-micro
|
||||
|
||||
- name: Run EE Cypress tests on ${{ inputs.name }}
|
||||
if: ${{ !inputs.tags }}
|
||||
shell: bash
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="-@slow+-@mongo+-@flaky+-@OSS --@quarantine",grepOmitFiltered=true \
|
||||
--spec '${{ inputs.specs }}' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run Tagged EE Cypress tests on ${{ inputs.name }}
|
||||
if: ${{ inputs.tags }}
|
||||
shell: bash
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="${{inputs.tags}} --@quarantine",grepOmitFiltered=true \
|
||||
--spec '${{ inputs.specs }}' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit
|
||||
output-name: e2e-${{ inputs.name }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
- name: Upload Cypress Artifacts upon failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: cypress-recording-${{ inputs.name }}-${{ inputs.edition }}
|
||||
path: |
|
||||
./cypress
|
||||
./logs/test.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Publish Summary
|
||||
if: failure()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | #js
|
||||
const {
|
||||
parseReport,
|
||||
formatSummary
|
||||
} = require("./.github/scripts/handle-mochawesome-report.js");
|
||||
|
||||
const report = parseReport();
|
||||
const summary = formatSummary(report);
|
||||
|
||||
await core.summary.addRaw(summary).write();
|
||||
252
.github/workflows/e2e-tests.yml
vendored
@@ -29,15 +29,9 @@ jobs:
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
e2e-matrix-builder:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
matrix: ${{ steps.e2e-matrix.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Generate matrix for E2E tests
|
||||
id: e2e-matrix
|
||||
uses: ./.github/actions/build-e2e-matrix
|
||||
uses: ./.github/workflows/e2e-matrix-builder.yml
|
||||
with:
|
||||
chunks: 50
|
||||
|
||||
# if this is a test on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
@@ -70,12 +64,12 @@ jobs:
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
|
||||
build:
|
||||
needs: [files-changed, e2e-matrix-builder, get-build-requirements]
|
||||
needs: [files-changed, get-build-requirements]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
github.event.pull_request.draft == false &&
|
||||
needs.e2e-matrix-builder.result == 'success' &&
|
||||
needs.files-changed.outputs.e2e_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 25
|
||||
@@ -107,180 +101,90 @@ jobs:
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
reset-e2e-test-comment:
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Remove test results comment
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const { owner, repo } = context.repo;
|
||||
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: context.issue.number,
|
||||
}).catch(console.error);
|
||||
|
||||
if (!comments) {
|
||||
return;
|
||||
}
|
||||
|
||||
const comment = comments.find((comment) => comment.body.includes('## e2e tests failed on '));
|
||||
|
||||
if (comment) {
|
||||
await github.rest.issues.deleteComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: comment.id,
|
||||
});
|
||||
}
|
||||
|
||||
e2e-tests:
|
||||
name: ${{ matrix.name }}-${{ matrix.edition }}
|
||||
uses: ./.github/workflows/e2e-test.yml
|
||||
needs: [build, e2e-matrix-builder]
|
||||
if: |
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 45
|
||||
name: e2e-tests-${{ matrix.name }}-${{ matrix.edition }}
|
||||
env:
|
||||
MB_EDITION: ${{ matrix.edition }}
|
||||
DISPLAY: ""
|
||||
QA_DB_ENABLED: true
|
||||
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
|
||||
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
|
||||
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
|
||||
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
|
||||
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
|
||||
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
|
||||
MB_SNOWPLOW_AVAILABLE: true
|
||||
MB_SNOWPLOW_URL: "http://localhost:9090" # Snowplow micro
|
||||
TZ: US/Pacific # to make node match the instance tz
|
||||
CYPRESS_CI: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJSON(needs.e2e-matrix-builder.outputs.matrix) }}
|
||||
matrix: ${{ fromJson(needs.e2e-matrix-builder.outputs.matrix) }}
|
||||
secrets: inherit
|
||||
with:
|
||||
name: ${{ matrix.name }}
|
||||
edition: ${{ matrix.edition }}
|
||||
specs: ${{ matrix.specs }}
|
||||
tags: ${{ matrix.tags }}
|
||||
runner: ${{ matrix.runner }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Docker containers
|
||||
uses: ./.github/actions/e2e-prepare-containers
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
maildev: true
|
||||
openldap: ${{ startsWith(matrix.name, 'admin') }}
|
||||
postgres: ${{ matrix.name != 'mongo'}}
|
||||
mysql: ${{ matrix.name != 'mongo'}}
|
||||
mongo: ${{ matrix.name == 'mongo'}}
|
||||
webhook: true
|
||||
|
||||
- name: Retrieve uberjar artifact for ${{ matrix.edition }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
- name: Get the version info
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar version.properties
|
||||
mv version.properties resources/
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
|
||||
- name: Prepare JDK ${{ matrix.java-version }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ matrix.java-version }}
|
||||
distribution: "temurin"
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
|
||||
- name: Run Snowplow micro
|
||||
uses: ./.github/actions/run-snowplow-micro
|
||||
|
||||
- name: Run OSS-specific Cypress tests
|
||||
if: matrix.edition == 'oss' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags=@OSS,grepOmitFiltered=true \
|
||||
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run slow and resource-intensive Cypress tests
|
||||
if: matrix.name == 'slow' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="@slow",grepOmitFiltered=true \
|
||||
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run Flaky Cypress tests
|
||||
if: matrix.name == 'flaky' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="@flaky --@quarantine",grepOmitFiltered=true \
|
||||
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run EE Cypress tests on ${{ matrix.name }}
|
||||
if: matrix.context == 'folder' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="-@slow+-@mongo+-@flaky --@quarantine",grepOmitFiltered=true \
|
||||
--folder ${{ matrix.name }} \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run E2E tests that depend on Mongo
|
||||
if: matrix.name == 'mongo'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="@mongo --@quarantine",grepOmitFiltered=true \
|
||||
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
env:
|
||||
CYPRESS_QA_DB_MONGO: true
|
||||
|
||||
- name: Run Embedding SDK Storybook
|
||||
if: matrix.context == 'embedding-sdk' && github.event_name != 'schedule'
|
||||
uses: ./.github/actions/run-embedding-sdk-storybook
|
||||
|
||||
- name: Run E2E tests for Embedding SDK
|
||||
if: matrix.context == 'embedding-sdk' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="-@slow+-@flaky --@quarantine",grepOmitFiltered=true \
|
||||
--folder 'embedding-sdk' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
env:
|
||||
CYPRESS_IS_EMBEDDING_SDK: true
|
||||
shell: bash
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit
|
||||
output-name: e2e-${{ matrix.name }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
- name: Upload Cypress Artifacts upon failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: cypress-recording-${{ matrix.name }}-${{ matrix.edition }}
|
||||
path: |
|
||||
./cypress
|
||||
./logs/test.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Publish Summary
|
||||
if: failure()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | #js
|
||||
const {
|
||||
parseReport,
|
||||
formatSummary
|
||||
} = require("./.github/scripts/handle-mochawesome-report.js");
|
||||
|
||||
const report = parseReport();
|
||||
const summary = formatSummary(report);
|
||||
|
||||
await core.summary.addRaw(summary).write();
|
||||
|
||||
e2e-tests-skipped-stub:
|
||||
needs: [e2e-tests, e2e-matrix-builder]
|
||||
# run this separately to make it non-blocking
|
||||
flaky-e2e-tests:
|
||||
name: Flaky e2e Tests
|
||||
uses: ./.github/workflows/e2e-test.yml
|
||||
needs: build
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.e2e-tests.result == 'skipped'
|
||||
runs-on: ${{ matrix.runner }}
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
secrets: inherit
|
||||
with:
|
||||
name: Flaky
|
||||
tags: "@flaky"
|
||||
|
||||
e2e-tests-result:
|
||||
needs: [e2e-tests, flaky-e2e-tests]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
name: e2e-tests-${{ matrix.name }}-${{ matrix.edition }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJSON(needs.e2e-matrix-builder.outputs.matrix) }}
|
||||
name: e2e-tests-result
|
||||
if: always() && !cancelled()
|
||||
env:
|
||||
E2E_TESTS_RESULT: ${{ needs.e2e-tests.result }}
|
||||
FLAKY_E2E_TESTS_RESULT: ${{ needs.flaky-e2e-tests.result }}
|
||||
steps:
|
||||
- run: |
|
||||
- name: Stub
|
||||
if: ${{ needs.e2e-tests.result == 'skipped' }}
|
||||
run: |
|
||||
echo "Didn't run due to conditional filtering"
|
||||
- name: Test results
|
||||
if: ${{ needs.e2e-tests.result != 'skipped' }}
|
||||
run: | # sh
|
||||
echo "E2E Tests: ${{ needs.e2e-tests.result }}"
|
||||
echo "Flaky E2E Tests: ${{ needs.flaky-e2e-tests.result }}"
|
||||
|
||||
if [ "${{ needs.e2e-tests.result }}" != "success" ]; then
|
||||
echo "E2E Tests failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pr-env:
|
||||
needs: [build]
|
||||
|
||||
40
.github/workflows/frontend.yml
vendored
@@ -123,3 +123,43 @@ jobs:
|
||||
m2-cache-key: "cljs"
|
||||
- name: Run frontend timezones tests
|
||||
run: yarn run test-timezones
|
||||
|
||||
fe-tests-result:
|
||||
needs:
|
||||
- fe-lint
|
||||
- fe-type-check
|
||||
- fe-tests-unit
|
||||
- fe-tests-timezones
|
||||
if: always() && !cancelled()
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
env:
|
||||
needs: ${{ toJson(needs) }}
|
||||
steps:
|
||||
- name: Check frontend job status
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
needs: ${{ toJson(needs) }}
|
||||
with:
|
||||
script: | # js
|
||||
const needs = JSON.parse(process.env.needs);
|
||||
const jobs = Object.entries(needs).map(
|
||||
([jobName, jobValues]) => ({
|
||||
name: jobName,
|
||||
result: jobValues.result
|
||||
}));
|
||||
|
||||
// are all jobs skipped or successful?
|
||||
if (jobs.every(job => (job.result === 'skipped' || job.result === 'success'))) {
|
||||
console.log('All jobs are skipped or successful');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// otherwise, something failed
|
||||
console.log('Some frontend jobs failed');
|
||||
jobs.forEach((job) => {
|
||||
if (job.result !== 'success') {
|
||||
console.log(`${job.name} - ${job.result}`);
|
||||
}
|
||||
});
|
||||
process.exit(1);
|
||||
|
||||
32
.github/workflows/links.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Links
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 0 * * 0"
|
||||
|
||||
jobs:
|
||||
linkChecker:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write # required for peter-evans/create-issue-from-file
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Link Checker
|
||||
id: lychee
|
||||
uses: lycheeverse/lychee-action@v2
|
||||
with:
|
||||
fail: false
|
||||
args: docs --config ./.lychee/config.toml --verbose --no-progress
|
||||
format: markdown
|
||||
|
||||
- name: Create Issue From File
|
||||
if: steps.lychee.outputs.exit_code != 0
|
||||
uses: peter-evans/create-issue-from-file@v5
|
||||
with:
|
||||
title: Link Checker Report
|
||||
content-filepath: ./.lychee/out.md
|
||||
labels: "Type:Documentation"
|
||||
assignees: jeff-bruemmer
|
||||
4
.github/workflows/loki-update.yml
vendored
@@ -61,9 +61,9 @@ jobs:
|
||||
with:
|
||||
github-token: ${{secrets.METABASE_AUTOMATION_USER_TOKEN}}
|
||||
script: |
|
||||
github.issues.removeLabel({
|
||||
github.rest.issues.removeLabel({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: 'loki-update'
|
||||
})
|
||||
});
|
||||
|
||||
10
.github/workflows/release-embedding-sdk.yml
vendored
@@ -210,12 +210,16 @@ jobs:
|
||||
|
||||
- name: Create a PR updating readme + published version, and changelog (using GitHub Metabase Automation account)
|
||||
run: |
|
||||
# TODO: Remove this step once github includes the new gh CLI version 2.65.0
|
||||
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
|
||||
brew install gh
|
||||
|
||||
git checkout -b update-sdk-version-${{ env.sdk_version }}
|
||||
git commit -a -m 'Update Readme version references and published npm version to ${{ env.sdk_version }}'
|
||||
git push origin HEAD
|
||||
gh pr create --base ${{ inputs.branch }}\
|
||||
--assignee "${GITHUB_ACTOR}"\
|
||||
--title "Update SDK version to ${{ env.sdk_version }}"\
|
||||
--title "docs(sdk): Update SDK version to ${{ env.sdk_version }}"\
|
||||
--body "Update Readme version references and published npm package version to ${{ env.sdk_version }}"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
@@ -257,8 +261,8 @@ jobs:
|
||||
# Please keep the value in sync with `inputs.branch`'s release branch
|
||||
npm publish --tag ${{fromJson('{"master": "nightly", "release-x.51.x": "51-stable"}')[inputs.branch]}}
|
||||
|
||||
- name: Add `latest` tag to the latest release branch (`release-x.51.x`) deployment
|
||||
if: ${{ inputs.branch == 'release-x.51.x' }}
|
||||
- name: Add `latest` tag to the latest release branch (`release-x.52.x`) deployment
|
||||
if: ${{ inputs.branch == 'release-x.52.x' }}
|
||||
working-directory: sdk
|
||||
run: |
|
||||
npm dist-tag add @metabase/embedding-sdk-react@${{ env.sdk_version }} latest
|
||||
|
||||
44
.github/workflows/release-log.yml
vendored
@@ -1,15 +1,18 @@
|
||||
name: Update Release Log
|
||||
run-name: Update Release Log ${{ inputs.version }}
|
||||
run-name: Update Release Log ${{ inputs.version || github.ref_name }}
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- release-x.*
|
||||
tags:
|
||||
- v*
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Major Metabase version (e.g. 45, 52, 68)'
|
||||
type: number
|
||||
required: true
|
||||
schedule:
|
||||
- cron: '45 * * * *' # hourly
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
@@ -21,11 +24,8 @@ jobs:
|
||||
update-release-log:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
env:
|
||||
VERSION: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')
|
||||
&& inputs.version || vars.CURRENT_VERSION }}
|
||||
# don't run this workflow for forks
|
||||
if: ${{ github.event_name != 'push' || github.repository == 'metabase/metabase' }}
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
@@ -35,9 +35,37 @@ jobs:
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master # this only works on master
|
||||
fetch-depth: 0 # we want all branches and tags
|
||||
- name: Install Dependencies
|
||||
run: yarn --cwd release --frozen-lockfile && npm i -g tsx
|
||||
- name: Build release scripts
|
||||
run: yarn --cwd release build
|
||||
- name: Get version number
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const {
|
||||
getVersionFromReleaseBranch,
|
||||
getMajorVersion,
|
||||
} = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
console.log({ context });
|
||||
|
||||
// if the version is explicitly set, use that
|
||||
if (context.payload?.inputs?.version) {
|
||||
core.exportVariable('VERSION', context.payload.inputs.version);
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, get the version from the release branch name
|
||||
const branch = context.payload.ref;
|
||||
const version = getVersionFromReleaseBranch(branch);
|
||||
const majorVersion = getMajorVersion(version);
|
||||
|
||||
console.log({ branch, version, majorVersion });
|
||||
core.exportVariable('VERSION', majorVersion);
|
||||
|
||||
- name: generate release Log
|
||||
run: cd release && tsx ./src/release-log-run.ts $VERSION > v$VERSION.html
|
||||
- name: generate release channel log
|
||||
|
||||
72
.github/workflows/release.yml
vendored
@@ -472,78 +472,6 @@ jobs:
|
||||
git config user.email github-actions@github.com
|
||||
$GITHUB_WORKSPACE/release/reorder-tags.sh ${{ needs.check-version.outputs.ee }} ${{ inputs.commit }}
|
||||
|
||||
trigger-docs-update:
|
||||
if: ${{ !inputs.auto }}
|
||||
needs:
|
||||
- push-tags
|
||||
- check-version
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
env:
|
||||
NEW_OSS_VERSION: ${{ needs.check-version.outputs.oss }}
|
||||
NEW_EE_VERSION: ${{ needs.check-version.outputs.ee }}
|
||||
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
script: | # js
|
||||
await github.rest.repos.createDispatchEvent({
|
||||
owner: '${{ github.repository_owner }}',
|
||||
repo: '${{ secrets.DOCS_REPO }}',
|
||||
event_type: 'trigger-docs-update',
|
||||
client_payload: {
|
||||
version: '${{ inputs.version }}'
|
||||
}
|
||||
});
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: update releases.md
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
script: | # js
|
||||
const fs = require('fs');
|
||||
|
||||
const releaseText = fs.readFileSync('./docs/releases.md', 'utf8');
|
||||
|
||||
const newReleaseText = releaseText
|
||||
.replace(
|
||||
/## Metabase Enterprise Edition releases\n\n/,
|
||||
`## Metabase Enterprise Edition releases\n\n- [${process.env.NEW_EE_VERSION}](https://github.com/metabase/metabase/releases/tag/${process.env.NEW_EE_VERSION})\n`
|
||||
)
|
||||
.replace(
|
||||
/## Metabase Open Source Edition releases\n\n/,
|
||||
`## Metabase Open Source Edition releases\n\n- [${process.env.NEW_OSS_VERSION}](https://github.com/metabase/metabase/releases/tag/${process.env.NEW_OSS_VERSION})\n`
|
||||
);
|
||||
|
||||
fs.writeFileSync('./docs/releases.md', newReleaseText);
|
||||
|
||||
- name: commit and push updates
|
||||
run: | # bash
|
||||
git config --global user.email "metabase-bot@metabase.com"
|
||||
git config --global user.name "Metabase bot"
|
||||
|
||||
git checkout -b docs-add-$NEW_OSS_VERSION
|
||||
cd docs/
|
||||
|
||||
git add releases.md
|
||||
git commit -m "Add $NEW_OSS_VERSION to the list of releases"
|
||||
git push origin docs-add-$NEW_OSS_VERSION --force
|
||||
|
||||
- name: open pr with updates
|
||||
run: | # bash
|
||||
gh pr create --fill \
|
||||
--body "Like it says on the tin 😁" \
|
||||
--label "Type:Documentation" \
|
||||
--label "backport" \
|
||||
--reviewer "jeff-bruemmer" \
|
||||
--assignee "jeff-bruemmer"
|
||||
|
||||
trigger-cloud-issues:
|
||||
if: ${{ !inputs.auto }}
|
||||
needs: push-tags
|
||||
|
||||
1
.gitignore
vendored
@@ -21,6 +21,7 @@
|
||||
/*.trace.db
|
||||
/.babel_cache
|
||||
/.env
|
||||
/.envrc
|
||||
/.lein-env
|
||||
/.lein-failures
|
||||
/.lein-plugins
|
||||
|
||||
|
After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
BIN
.loki/reference/chrome_laptop_viz_EChartsTooltip_Default.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
.loki/reference/chrome_laptop_viz_EChartsTooltip_Light_Theme.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
1
.lychee/config.toml
Normal file
@@ -0,0 +1 @@
|
||||
accept = ["200..=204", "429"]
|
||||
0
.lychee/out.md
Normal file
2
.lycheeignore
Normal file
@@ -0,0 +1,2 @@
|
||||
http://localhost*
|
||||
https://admin.google.com
|
||||
105
.storybook-sdk/main.js
Normal file
@@ -0,0 +1,105 @@
|
||||
const webpack = require("webpack");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const appConfig = require("../webpack.config");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const {
|
||||
isEmbeddingSdkPackageInstalled,
|
||||
embeddingSdkVersion: EMBEDDING_SDK_VERSION,
|
||||
} = resolveEmbeddingSdkPackage();
|
||||
|
||||
module.exports = {
|
||||
core: {
|
||||
builder: "webpack5",
|
||||
},
|
||||
stories: ["../enterprise/frontend/src/embedding-sdk/**/*.stories.tsx"],
|
||||
staticDirs: ["../resources/frontend_client"],
|
||||
addons: [
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-a11y",
|
||||
"@storybook/addon-interactions",
|
||||
"storybook-addon-pseudo-states",
|
||||
],
|
||||
features: {
|
||||
interactionsDebugger: true,
|
||||
},
|
||||
babel: () => {},
|
||||
typescript: {
|
||||
reactDocgen: "react-docgen-typescript-plugin",
|
||||
},
|
||||
webpackFinal: storybookConfig => ({
|
||||
...storybookConfig,
|
||||
plugins: [
|
||||
...storybookConfig.plugins,
|
||||
new MiniCssExtractPlugin(),
|
||||
new webpack.ProvidePlugin({
|
||||
Buffer: ["buffer", "Buffer"],
|
||||
}),
|
||||
new webpack.EnvironmentPlugin({
|
||||
EMBEDDING_SDK_VERSION,
|
||||
IS_EMBEDDING_SDK: true,
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
...storybookConfig.module,
|
||||
rules: [
|
||||
...storybookConfig.module.rules.filter(
|
||||
rule => !isCSSRule(rule) && !isSvgRule(rule),
|
||||
),
|
||||
...appConfig.module.rules.filter(
|
||||
rule => isCSSRule(rule) || isSvgRule(rule),
|
||||
),
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
...storybookConfig.resolve,
|
||||
alias: {
|
||||
...appConfig.resolve.alias,
|
||||
...(isEmbeddingSdkPackageInstalled && {
|
||||
// $ means that only exact "embedding-sdk" imports will be rerouted, all nested embedding-sdk/* will still be resolved locally
|
||||
"embedding-sdk$": require.resolve("@metabase/embedding-sdk-react"),
|
||||
}),
|
||||
},
|
||||
extensions: appConfig.resolve.extensions,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
const isCSSRule = rule => rule.test.toString() === "/\\.css$/";
|
||||
const isSvgRule = rule => rule.test && rule.test?.test(".svg");
|
||||
|
||||
function resolveEmbeddingSdkPackage() {
|
||||
let isEmbeddingSdkPackageInstalled = false;
|
||||
let embeddingSdkVersion;
|
||||
|
||||
try {
|
||||
const packagePath = require.resolve("@metabase/embedding-sdk-react");
|
||||
if (packagePath.includes("node_modules")) {
|
||||
isEmbeddingSdkPackageInstalled = true;
|
||||
}
|
||||
|
||||
const packageJsonContent = fs.readFileSync(
|
||||
path.join(packagePath, "package.json"),
|
||||
"utf-8",
|
||||
);
|
||||
embeddingSdkVersion = JSON.stringify(
|
||||
JSON.parse(packageJsonContent)?.version,
|
||||
);
|
||||
} catch (err) {
|
||||
const sdkPackageTemplateJson = fs.readFileSync(
|
||||
path.resolve(
|
||||
"./enterprise/frontend/src/embedding-sdk/package.template.json",
|
||||
),
|
||||
"utf-8",
|
||||
);
|
||||
const sdkPackageTemplateJsonContent = JSON.parse(sdkPackageTemplateJson);
|
||||
embeddingSdkVersion = JSON.stringify(sdkPackageTemplateJsonContent.version);
|
||||
}
|
||||
|
||||
return {
|
||||
isEmbeddingSdkPackageInstalled,
|
||||
embeddingSdkVersion,
|
||||
};
|
||||
}
|
||||
32
.storybook-sdk/preview.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { GlobalTypes } from "@storybook/types";
|
||||
|
||||
// @ts-expect-error: See metabase/lib/delay
|
||||
// This will skip the skippable delays in stories
|
||||
window.METABASE_REMOVE_DELAYS = true;
|
||||
|
||||
import { storybookThemeOptions } from "embedding-sdk/test/storybook-themes";
|
||||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const decorators = []; // No decorators for Embedding SDK stories, as we want to simulate real use cases
|
||||
|
||||
export const globalTypes: GlobalTypes = {
|
||||
sdkTheme: {
|
||||
name: "SDK Theme",
|
||||
description: "Global theme for sdk components",
|
||||
defaultValue: "default",
|
||||
toolbar: {
|
||||
icon: "paintbrush",
|
||||
items: storybookThemeOptions,
|
||||
showName: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -4,27 +4,16 @@ const appConfig = require("../webpack.config");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const isEmbeddingSDK = process.env.IS_EMBEDDING_SDK === "true";
|
||||
|
||||
const mainAppStories = [
|
||||
"../frontend/**/*.stories.mdx",
|
||||
"../frontend/**/*.stories.@(js|jsx|ts|tsx)",
|
||||
];
|
||||
|
||||
const embeddingSdkStories = [
|
||||
"../enterprise/frontend/src/embedding-sdk/**/*.stories.tsx",
|
||||
];
|
||||
|
||||
const {
|
||||
isEmbeddingSdkPackageInstalled,
|
||||
embeddingSdkVersion: EMBEDDING_SDK_VERSION,
|
||||
} = resolveEmbeddingSdkPackage();
|
||||
|
||||
module.exports = {
|
||||
core: {
|
||||
builder: "webpack5",
|
||||
},
|
||||
stories: isEmbeddingSDK ? embeddingSdkStories : mainAppStories,
|
||||
stories: mainAppStories,
|
||||
staticDirs: ["../resources/frontend_client"],
|
||||
addons: [
|
||||
"@storybook/addon-essentials",
|
||||
@@ -49,8 +38,7 @@ module.exports = {
|
||||
Buffer: ["buffer", "Buffer"],
|
||||
}),
|
||||
new webpack.EnvironmentPlugin({
|
||||
EMBEDDING_SDK_VERSION,
|
||||
IS_EMBEDDING_SDK: isEmbeddingSDK,
|
||||
IS_EMBEDDING_SDK: false,
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
@@ -68,10 +56,6 @@ module.exports = {
|
||||
...storybookConfig.resolve,
|
||||
alias: {
|
||||
...appConfig.resolve.alias,
|
||||
...(isEmbeddingSdkPackageInstalled && {
|
||||
// $ means that only exact "embedding-sdk" imports will be rerouted, all nested embedding-sdk/* will still be resolved locally
|
||||
"embedding-sdk$": require.resolve("@metabase/embedding-sdk-react"),
|
||||
}),
|
||||
},
|
||||
extensions: appConfig.resolve.extensions,
|
||||
},
|
||||
@@ -80,28 +64,3 @@ module.exports = {
|
||||
|
||||
const isCSSRule = rule => rule.test.toString() === "/\\.css$/";
|
||||
const isSvgRule = rule => rule.test && rule.test?.test(".svg");
|
||||
|
||||
function resolveEmbeddingSdkPackage() {
|
||||
let isEmbeddingSdkPackageInstalled = false;
|
||||
let embeddingSdkVersion;
|
||||
|
||||
try {
|
||||
embeddingSdkVersion =
|
||||
require("@metabase/embedding-sdk-react/package.json").version;
|
||||
isEmbeddingSdkPackageInstalled = true;
|
||||
} catch (err) {
|
||||
const sdkPackageTemplateJson = fs.readFileSync(
|
||||
path.resolve(
|
||||
"./enterprise/frontend/src/embedding-sdk/package.template.json",
|
||||
),
|
||||
"utf-8",
|
||||
);
|
||||
const sdkPackageTemplateJsonContent = JSON.parse(sdkPackageTemplateJson);
|
||||
embeddingSdkVersion = JSON.stringify(sdkPackageTemplateJsonContent.version);
|
||||
}
|
||||
|
||||
return {
|
||||
isEmbeddingSdkPackageInstalled,
|
||||
embeddingSdkVersion,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React from "react";
|
||||
import { ThemeProvider } from "metabase/ui";
|
||||
|
||||
const isEmbeddingSDK = process.env.IS_EMBEDDING_SDK === "true";
|
||||
// @ts-expect-error: See metabase/lib/delay
|
||||
// This will skip the skippable delays in stories
|
||||
window.METABASE_REMOVE_DELAYS = true;
|
||||
|
||||
if (!isEmbeddingSDK) {
|
||||
require("metabase/css/core/index.css");
|
||||
require("metabase/css/vendor.css");
|
||||
require("metabase/css/index.module.css");
|
||||
require("metabase/lib/dayjs");
|
||||
}
|
||||
require("metabase/css/core/index.css");
|
||||
require("metabase/css/vendor.css");
|
||||
require("metabase/css/index.module.css");
|
||||
require("metabase/lib/dayjs");
|
||||
|
||||
import { EmotionCacheProvider } from "metabase/styled-components/components/EmotionCacheProvider";
|
||||
import { getMetabaseCssVariables } from "metabase/styled-components/theme/css-variables";
|
||||
@@ -39,19 +39,22 @@ const globalStyles = css`
|
||||
${baseStyle}
|
||||
`;
|
||||
|
||||
export const decorators = isEmbeddingSDK
|
||||
? [] // No decorators for Embedding SDK stories, as we want to simulate real use cases
|
||||
: [
|
||||
renderStory => (
|
||||
<EmotionCacheProvider>
|
||||
<ThemeProvider>
|
||||
<Global styles={globalStyles} />
|
||||
<CssVariables />
|
||||
{renderStory()}
|
||||
</ThemeProvider>
|
||||
</EmotionCacheProvider>
|
||||
),
|
||||
];
|
||||
export const decorators = [
|
||||
renderStory => {
|
||||
if (!document.body.classList.contains("mb-wrapper")) {
|
||||
document.body.classList.add("mb-wrapper");
|
||||
}
|
||||
return (
|
||||
<EmotionCacheProvider>
|
||||
<ThemeProvider>
|
||||
<Global styles={globalStyles} />
|
||||
<CssVariables />
|
||||
{renderStory()}
|
||||
</ThemeProvider>
|
||||
</EmotionCacheProvider>
|
||||
);
|
||||
},
|
||||
];
|
||||
|
||||
function CssVariables() {
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -5,7 +5,6 @@ const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const SDK_DIST_DIR_PATH = path.resolve("./resources/embedding-sdk/dist");
|
||||
const SDK_PACKAGE_NAME = "@metabase/embedding-sdk-react";
|
||||
|
||||
/*
|
||||
* This script replaces all custom aliases in Embedding SDK generated ".d.ts" files so that this imports could be resolved
|
||||
@@ -14,12 +13,12 @@ const SDK_PACKAGE_NAME = "@metabase/embedding-sdk-react";
|
||||
|
||||
// this map should be synced with "tsconfig.sdk.json"
|
||||
const REPLACES_MAP = {
|
||||
"metabase-enterprise": `${SDK_PACKAGE_NAME}/dist/enterprise/frontend/src/metabase-enterprise`,
|
||||
"metabase-lib": `${SDK_PACKAGE_NAME}/dist/frontend/src/metabase-lib`,
|
||||
"metabase-types": `${SDK_PACKAGE_NAME}/dist/frontend/src/metabase-types`,
|
||||
metabase: `${SDK_PACKAGE_NAME}/dist/frontend/src/metabase`,
|
||||
"embedding-sdk": `${SDK_PACKAGE_NAME}/dist/enterprise/frontend/src/embedding-sdk`,
|
||||
cljs: `${SDK_PACKAGE_NAME}/dist/target/cljs_release`,
|
||||
"metabase-enterprise": "enterprise/frontend/src/metabase-enterprise",
|
||||
"metabase-lib": "frontend/src/metabase-lib",
|
||||
"metabase-types": "frontend/src/metabase-types",
|
||||
metabase: "frontend/src/metabase",
|
||||
"embedding-sdk": "enterprise/frontend/src/embedding-sdk",
|
||||
cljs: "target/cljs_release",
|
||||
};
|
||||
|
||||
const traverseFilesTree = dir => {
|
||||
@@ -42,24 +41,30 @@ const traverseFilesTree = dir => {
|
||||
}
|
||||
};
|
||||
|
||||
const getRelativePath = (fromPath, toPath) => {
|
||||
const relativePath = path.relative(path.dirname(fromPath), toPath);
|
||||
return relativePath.startsWith(".") ? relativePath : "./" + relativePath;
|
||||
};
|
||||
|
||||
const replaceAliasedImports = filePath => {
|
||||
let fileContent = fs.readFileSync(filePath, { encoding: "utf8" });
|
||||
|
||||
Object.entries(REPLACES_MAP).forEach(([alias, replacement]) => {
|
||||
Object.entries(REPLACES_MAP).forEach(([alias, targetPath]) => {
|
||||
const relativePath = getRelativePath(
|
||||
filePath,
|
||||
path.join(SDK_DIST_DIR_PATH, targetPath),
|
||||
);
|
||||
|
||||
fileContent = fileContent
|
||||
// replaces "metabase-lib/foo" with "<sdk>/metabase-lib/foo"
|
||||
.replaceAll(`from "${alias}/`, `from "${replacement}/`)
|
||||
// replaces "metabase-lib" with "<sdk>/metabase-lib"
|
||||
.replaceAll(`from "${alias}"`, `from "${replacement}"`)
|
||||
.replaceAll(`import("${alias}`, `import("${replacement}`)
|
||||
.replaceAll(`from "${alias}/`, `from "${relativePath}/`)
|
||||
.replaceAll(`from "${alias}"`, `from "${relativePath}"`)
|
||||
.replaceAll(`import("${alias}`, `import("${relativePath}`)
|
||||
.replace(
|
||||
// replace dynamic imports using alias, with possible relative paths - "../../" and "frontend/src/"
|
||||
// import("(../)*(frontend/src/)*<alias>
|
||||
new RegExp(
|
||||
`import\\("(\\.\\.\/)*(frontend\/src\/)*${alias.replace("/", "\\/")}`,
|
||||
"gi",
|
||||
),
|
||||
`import("${replacement}`,
|
||||
`import("${relativePath}`,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
5
deps.edn
@@ -49,6 +49,7 @@
|
||||
com.fasterxml.woodstox/woodstox-core {:mvn/version "6.6.1"} ; trans dep of commons-codec
|
||||
com.h2database/h2 {:mvn/version "2.1.214"} ; embedded SQL database
|
||||
com.gfredericks/test.chuck {:mvn/version "0.2.14"} ; generating strings from regex
|
||||
com.mchange/c3p0 {:mvn/version "0.10.1"} ; DB connection pool
|
||||
com.snowplowanalytics/snowplow-java-tracker
|
||||
{:mvn/version "1.0.1" ; Snowplow analytics
|
||||
:exclusions [com.fasterxml.jackson.core/jackson-databind]}
|
||||
@@ -76,11 +77,11 @@
|
||||
instaparse/instaparse {:mvn/version "1.4.12"} ; Make your own parser
|
||||
junegunn/grouper {:mvn/version "0.1.1"} ; Batch processing helper
|
||||
clj-commons/clj-yaml {:mvn/version "1.0.27"} ; Clojure wrapper for YAML library SnakeYAML
|
||||
io.github.camsaul/toucan2 {:mvn/version "1.0.556"}
|
||||
io.github.camsaul/toucan2 {:mvn/version "1.0.560"}
|
||||
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.2.24"} ; Parse native SQL queries
|
||||
io.github.metabase/macaw {:mvn/version "0.2.25"} ; 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
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
[clojure.test]
|
||||
[dev.debug-qp :as debug-qp]
|
||||
[dev.explain :as dev.explain]
|
||||
[dev.memory :as dev.memory]
|
||||
[dev.migrate :as dev.migrate]
|
||||
[dev.model-tracking :as model-tracking]
|
||||
[dev.render-png :as render-png]
|
||||
@@ -109,6 +110,9 @@
|
||||
migrate!
|
||||
rollback!
|
||||
migration-sql-by-id]
|
||||
[dev.memory
|
||||
with-memory-logging
|
||||
measuring-thread-allocations]
|
||||
[render-png
|
||||
open-html
|
||||
open-png-bytes
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
(assert (.isThreadAllocatedMemorySupported mx-bean))
|
||||
(.getThreadAllocatedBytes mx-bean thread-id)))
|
||||
|
||||
(set! *warn-on-reflection* true)
|
||||
|
||||
(defn mb-str
|
||||
"Format bytes as megabytes"
|
||||
[bytes]
|
||||
@@ -42,11 +40,42 @@
|
||||
(log/warnf "Allocated: %s" (mb-str (:allocations m#)))
|
||||
(:result m#)))
|
||||
|
||||
(def ^{:dynamic true
|
||||
:private true} *memory-log-level* -1)
|
||||
|
||||
(defn- used-mb
|
||||
[]
|
||||
(let [rt (Runtime/getRuntime)
|
||||
mb (* 1024.0 1024.0)]
|
||||
(/ (- (.totalMemory rt) (.freeMemory rt)) mb)))
|
||||
|
||||
(defn log-memory-usage
|
||||
"Executes body-fn and logs memory usage before and after execution.
|
||||
Returns the result of body-fn."
|
||||
[body-fn context]
|
||||
(binding [*memory-log-level* (inc *memory-log-level*)]
|
||||
(let [indent (apply str (repeat *memory-log-level* " "))
|
||||
before (used-mb)
|
||||
print-stats (fn
|
||||
([stats]
|
||||
(log/infof "%s%s | Memory before:: %.2f MB "
|
||||
indent context stats))
|
||||
([before after]
|
||||
(log/infof "%s%s | Memory after:: %.2f MB (delta: %.2f MB)"
|
||||
indent context after (- after before))))
|
||||
_ (print-stats before)
|
||||
result (body-fn)
|
||||
after (used-mb)
|
||||
_ (print-stats before after)]
|
||||
result)))
|
||||
|
||||
(defmacro with-memory-logging
|
||||
"Executes body and logs memory usage before and after execution.
|
||||
Returns the result of body."
|
||||
[context & body]
|
||||
`(log-memory-usage (fn [] ~@body) ~context))
|
||||
|
||||
(comment
|
||||
;; almost correct, at least a constant error
|
||||
(measuring-thread-allocations
|
||||
(byte-array (* 1024 1024)))
|
||||
;; => 1.028MB
|
||||
;; => 1.028MB
|
||||
;; => 1.028MB
|
||||
)
|
||||
(byte-array (* 1024 1024))))
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
([direction & [version]]
|
||||
(mdb/migrate! (mdb/data-source) direction version)
|
||||
#_{:clj-kondo/ignore [:discouraged-var]}
|
||||
(println "Migrated up. Latest migration:" (latest-migration))))
|
||||
(println (format "Migrated %s. Latest migration: %s" (name direction) (latest-migration)))))
|
||||
|
||||
(defn- rollback-n-migrations!
|
||||
[^Integer n]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Contributing to Metabase
|
||||
redirect_from:
|
||||
- /docs/latest/contributing
|
||||
- /docs/latest/developers-guide/contributing
|
||||
---
|
||||
|
||||
# Contributing to Metabase
|
||||
@@ -61,7 +61,7 @@ Once one or more people have started to work on a feature, it should be marked [
|
||||
|
||||
### E) Verification and merging
|
||||
|
||||
All PRs that involve more than an insignificant change should be reviewed. See our [Code Review Process](code-reviews.md).
|
||||
All PRs that involve more than an insignificant change should be reviewed. See our [Code Review Process](./developers-guide/code-reviews.md).
|
||||
|
||||
If all goes well, the feature gets coded up, verified and then the pull request gets merged! High-fives all around.
|
||||
|
||||
@@ -95,7 +95,7 @@ By our definition, "Bugs" are situations where the program doesn't do what it wa
|
||||
|
||||
There are a lot of docs, which means keeping them up to date is hard. If you notice inconsistencies, errors, or outdated information, please help us keep them current!
|
||||
|
||||
Note that **we cannot accept translations for documentation at this time**. We support [in-app translations](../configuring-metabase/localization.md), and only support languages that have 100% coverage. But 1) the in-app text is orders of magnitude shorter than our docs, 2) it changes at a slower pace, and 3) we have a lot of people help out. We may consider supporting docs in multiple languages in the future, but for now we need to focus our resources on improving our existing documentation (and expanding it to include all of the new features we're adding).
|
||||
Note that **we cannot accept translations for documentation at this time**. We support [in-app translations](./configuring-metabase/localization.md), and only support languages that have 100% coverage. But 1) the in-app text is orders of magnitude shorter than our docs, 2) it changes at a slower pace, and 3) we have a lot of people help out. We may consider supporting docs in multiple languages in the future, but for now we need to focus our resources on improving our existing documentation (and expanding it to include all of the new features we're adding).
|
||||
|
||||
### Working on features
|
||||
|
||||
@@ -132,6 +132,7 @@ Metabase's reference documentation.
|
||||
- [Data reference](./exploration-and-organization/data-model-reference.md)
|
||||
- [Events and timelines](./exploration-and-organization/events-and-timelines.md)
|
||||
- [X-rays](./exploration-and-organization/x-rays.md)
|
||||
- [Content verification](./exploration-and-organization/content-verification.md)
|
||||
|
||||
### People
|
||||
|
||||
@@ -140,7 +141,8 @@ Metabase's reference documentation.
|
||||
- [Managing people and groups](./people-and-groups/managing.md)
|
||||
- [Password complexity](./people-and-groups/changing-password-complexity.md)
|
||||
- [Session expiration](./people-and-groups/changing-session-expiration.md)
|
||||
- [Google Sign-In or LDAP](./people-and-groups/google-and-ldap.md)
|
||||
- [Google Sign-In](./people-and-groups/google-sign-in.md)
|
||||
- [LDAP](./people-and-groups/ldap.md)
|
||||
- [API keys](./people-and-groups/api-keys.md)
|
||||
|
||||
#### Paid SSO options
|
||||
@@ -206,7 +208,7 @@ Metabase's reference documentation.
|
||||
### Metabase API
|
||||
|
||||
- [Metabase API documentation](./api-documentation.md)
|
||||
- [API tutorial](https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation//metabase-api)
|
||||
- [API tutorial](https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation/metabase-api)
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
@@ -262,7 +264,7 @@ We tweet stuff.
|
||||
|
||||
Follow us on GitHub.
|
||||
|
||||
### [List of releases](./releases.md)
|
||||
### [List of releases](https://github.com/metabase/metabase/releases)
|
||||
|
||||
A list of all Metabase releases, including both the Enterprise Edition and the Open Source Edition.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ title: "Metabase API documentation"
|
||||
_These reference files were generated from source comments by running:_
|
||||
|
||||
```
|
||||
clojure -M:ee:run api-documentation
|
||||
clojure -M:ee:doc api-documentation
|
||||
```
|
||||
|
||||
## About the Metabase API
|
||||
@@ -17,12 +17,16 @@ clojure -M:ee:run api-documentation
|
||||
|
||||
## API tutorial
|
||||
|
||||
Check out an introduction to the [Metabase API](https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation//metabase-api).
|
||||
Check out an introduction to the [Metabase API](https://www.metabase.com/learn/administration/metabase-api.html).
|
||||
|
||||
## API keys
|
||||
|
||||
Create keys to authenticate programmatic requests to your Metabase. See [API keys](./people-and-groups/api-keys.md).
|
||||
|
||||
## API changelog
|
||||
|
||||
For breaking changes, see the API [changelog](./developers-guide/api-changelog.md).
|
||||
|
||||
## API endpoints
|
||||
|
||||
_* indicates endpoints used for features available on [paid plans](https://www.metabase.com/pricing)._
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
title: "Alert"
|
||||
summary: |
|
||||
/api/alert endpoints.
|
||||
|
||||
Deprecated: will soon be migrated to notification APIs.
|
||||
---
|
||||
|
||||
# Alert
|
||||
|
||||
/api/alert endpoints.
|
||||
|
||||
Deprecated: will soon be migrated to notification APIs.
|
||||
|
||||
## `DELETE /api/alert/:id/subscription`
|
||||
|
||||
For users to unsubscribe themselves from the given alert.
|
||||
|
||||
@@ -44,11 +44,11 @@ Invalidate cache entries.
|
||||
|
||||
- **`include`** All cache configuration overrides should invalidate cache too.
|
||||
|
||||
- **`database`** A database id.
|
||||
- **`database`** A list of database ids.
|
||||
|
||||
- **`dashboard`** A dashboard id.
|
||||
- **`dashboard`** A list of dashboard ids.
|
||||
|
||||
- **`question`** A question id.
|
||||
- **`question`** A list of question ids.
|
||||
|
||||
## `PUT /api/cache/`
|
||||
|
||||
|
||||
@@ -208,7 +208,9 @@ Run the query associated with a Card, and return its results as a file in the sp
|
||||
|
||||
- **`parameters`** nullable value must be a valid JSON string.
|
||||
|
||||
- **`format_rows`** nullable boolean.
|
||||
- **`pivot_results`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
- **`format_rows`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
## `POST /api/card/:card-id/refresh`
|
||||
|
||||
|
||||
@@ -223,10 +223,14 @@ Modify an existing Collection, including archiving or unarchiving it, or moving
|
||||
|
||||
## `PUT /api/collection/graph`
|
||||
|
||||
Do a batch update of Collections Permissions by passing in a modified graph.
|
||||
Will overwrite parts of the graph that are present in the request, and leave the rest unchanged.
|
||||
Do a batch update of Collections Permissions by passing in a modified graph. Will overwrite parts of the graph that
|
||||
are present in the request, and leave the rest unchanged.
|
||||
|
||||
If the `skip_graph` query parameter is true, it will only return the current revision.
|
||||
If the `force` query parameter is `true`, a `revision` number is not required. The provided graph will be persisted
|
||||
as-is, and has the potential to clobber other writes that happened since the last read.
|
||||
|
||||
If the `skip_graph` query parameter is `true`, it will only return the current revision, not the entire permissions
|
||||
graph.
|
||||
|
||||
You must be a superuser to do this.
|
||||
|
||||
@@ -234,11 +238,13 @@ You must be a superuser to do this.
|
||||
|
||||
- **`namespace`** nullable value must be a non-blank string.
|
||||
|
||||
- **`revision`** value must be an integer.
|
||||
- **`revision`** nullable value must be an integer.
|
||||
|
||||
- **`groups`** map.
|
||||
|
||||
- **`skip_graph`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
- **`skip-graph`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
- **`force`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -220,7 +220,9 @@ Run the query associated with a Saved Question (`Card`) in the context of a `Das
|
||||
|
||||
- **`parameters`** nullable value must be a valid JSON string.
|
||||
|
||||
- **`format_rows`** nullable boolean.
|
||||
- **`format_rows`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
- **`pivot_results`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
- **`request-parameters`**
|
||||
|
||||
|
||||
@@ -30,7 +30,9 @@ Execute a query and download the result data as a file in the specified format.
|
||||
|
||||
- **`visualization_settings`** value must be a valid JSON string.
|
||||
|
||||
- **`format_rows`** nullable boolean.
|
||||
- **`pivot_results`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
- **`format_rows`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
## `POST /api/dataset/native`
|
||||
|
||||
|
||||
@@ -24,6 +24,14 @@ Do a batch update of Application Permissions by passing a modified graph.
|
||||
|
||||
You must be a superuser to do this.
|
||||
|
||||
### PARAMS:
|
||||
|
||||
- **`skip-graph`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
- **`force`** nullable value must be a valid boolean string ('true' or 'false').
|
||||
|
||||
- **`body`** map.
|
||||
|
||||
---
|
||||
|
||||
[<< Back to API index](../../api-documentation.md)
|
||||
@@ -20,7 +20,7 @@ You must be a superuser to do this.
|
||||
|
||||
- **`moderated_item_id`** value must be an integer greater than zero.
|
||||
|
||||
- **`moderated_item_type`** enum of card, :card.
|
||||
- **`moderated_item_type`** enum of card, :card, dashboard, :dashboard.
|
||||
|
||||
- **`status`** nullable nullable enum of verified.
|
||||
|
||||
|
||||
@@ -140,6 +140,8 @@ Like `GET /api/embed/card/query`, but returns the results as a file in the speci
|
||||
|
||||
- **`format_rows`** nullable boolean.
|
||||
|
||||
- **`pivot_results`** nullable boolean.
|
||||
|
||||
- **`query-params`**
|
||||
|
||||
## `GET /api/embed/dashboard/:token`
|
||||
@@ -188,6 +190,8 @@ Fetch the results of running a Card belonging to a Dashboard using a JSON Web To
|
||||
|
||||
- **`format_rows`** nullable boolean.
|
||||
|
||||
- **`pivot_results`** nullable boolean.
|
||||
|
||||
- **`query-params`**
|
||||
|
||||
## `GET /api/embed/dashboard/:token/field/:field-id/remapping/:remapped-id`
|
||||
|
||||