Compare commits
865 Commits
static-viz
...
python-lib
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd50ffa7dd | ||
|
|
2880033f06 | ||
|
|
87161c6d71 | ||
|
|
89117dbfb0 | ||
|
|
3a1b93b79d | ||
|
|
2f651e074d | ||
|
|
54a2642138 | ||
|
|
d3a74d538d | ||
|
|
82b097feb8 | ||
|
|
a8f5ff5193 | ||
|
|
b8fef1a67f | ||
|
|
ce6420ebc7 | ||
|
|
6f74fd4593 | ||
|
|
33593abd60 | ||
|
|
702bd9a3f2 | ||
|
|
8284646d15 | ||
|
|
1e0246d2f1 | ||
|
|
d82c40a1db | ||
|
|
e39983b3db | ||
|
|
01f4bcfb43 | ||
|
|
cae08116f0 | ||
|
|
a314bb587c | ||
|
|
09731e48fa | ||
|
|
cdba119297 | ||
|
|
5957b1f5df | ||
|
|
2357bea601 | ||
|
|
32281e2096 | ||
|
|
f17e329af5 | ||
|
|
c481f1ceb6 | ||
|
|
f63e05fda1 | ||
|
|
928f6f830b | ||
|
|
29e936e2f8 | ||
|
|
802fe0fcfe | ||
|
|
0ae5027542 | ||
|
|
e64e7ec93b | ||
|
|
fcb4ca1f80 | ||
|
|
54695561ad | ||
|
|
e965057f1b | ||
|
|
7ed61da2df | ||
|
|
0fba1b34a9 | ||
|
|
6ca68fc067 | ||
|
|
93bcf2f1b8 | ||
|
|
c830ff5164 | ||
|
|
97296942ab | ||
|
|
a9b58f9dd7 | ||
|
|
54d2a79a1a | ||
|
|
4147277e28 | ||
|
|
1815fb8afa | ||
|
|
058e4b3bc5 | ||
|
|
8c5cd34ec9 | ||
|
|
eea9b658da | ||
|
|
17fb99163f | ||
|
|
7257a4d1d2 | ||
|
|
0287e639b1 | ||
|
|
0999cfab54 | ||
|
|
9e18d5b9f7 | ||
|
|
9910f6d0ca | ||
|
|
6939615ce2 | ||
|
|
b7bb799e14 | ||
|
|
3eb696e22b | ||
|
|
60da15bf27 | ||
|
|
3b3e5f91d6 | ||
|
|
0fcff349d1 | ||
|
|
f8a66a7470 | ||
|
|
4672ea6c34 | ||
|
|
73e4ba5bd8 | ||
|
|
20d91af3a5 | ||
|
|
2d43e09f84 | ||
|
|
8cb6965fa7 | ||
|
|
1279c1f226 | ||
|
|
9efe8835fa | ||
|
|
23b4d7ece0 | ||
|
|
40e71f4baa | ||
|
|
2dd76b303e | ||
|
|
f7eb4ca800 | ||
|
|
f3860aee72 | ||
|
|
5d93b6fe71 | ||
|
|
f09dbce65d | ||
|
|
0783824721 | ||
|
|
e6d90444c2 | ||
|
|
dabaa3007e | ||
|
|
00fb1c3841 | ||
|
|
e7fd61a386 | ||
|
|
a17971e449 | ||
|
|
02390555ba | ||
|
|
20577becba | ||
|
|
4c3656a57b | ||
|
|
cca17f5f4d | ||
|
|
f74de7e31e | ||
|
|
cb946d095d | ||
|
|
c4ed3cac1d | ||
|
|
2e184e6c48 | ||
|
|
71f7fe60f1 | ||
|
|
c80fea1587 | ||
|
|
50cb92e548 | ||
|
|
b5f5624007 | ||
|
|
b514c93c50 | ||
|
|
f9614edfdf | ||
|
|
21325c4366 | ||
|
|
b37c60a342 | ||
|
|
4a01316597 | ||
|
|
eb474fbf52 | ||
|
|
d90fcce25b | ||
|
|
9733cd683a | ||
|
|
8462072dfd | ||
|
|
c482aa6f03 | ||
|
|
c621b64c2f | ||
|
|
9275b7fb84 | ||
|
|
bda65e63db | ||
|
|
74d6c3f356 | ||
|
|
815d7a3186 | ||
|
|
7e0f54bb73 | ||
|
|
92171ab506 | ||
|
|
4fc51375be | ||
|
|
de8a48277f | ||
|
|
dad98c137d | ||
|
|
68d9786697 | ||
|
|
db02774c9c | ||
|
|
ef5e78f979 | ||
|
|
3b955d9067 | ||
|
|
f4d3359e33 | ||
|
|
6b190fdcb1 | ||
|
|
d3d865dda9 | ||
|
|
558c69ee84 | ||
|
|
86bc79d826 | ||
|
|
6739de6bfc | ||
|
|
f21fda68f1 | ||
|
|
350561daf9 | ||
|
|
cc99a79835 | ||
|
|
9be149e22f | ||
|
|
a283c947aa | ||
|
|
ab4e737c31 | ||
|
|
4a1ce5d04f | ||
|
|
34f1e6811f | ||
|
|
8a5c220e5c | ||
|
|
daeb777e4d | ||
|
|
708f4696ca | ||
|
|
fc453f6bbc | ||
|
|
f50d99d709 | ||
|
|
c19e0fa75f | ||
|
|
805e5beb8b | ||
|
|
246b6534a1 | ||
|
|
a532fe0e28 | ||
|
|
83dc4947f4 | ||
|
|
8d77a4f153 | ||
|
|
92febb9f2b | ||
|
|
92267df836 | ||
|
|
7b4ed715ae | ||
|
|
fe9b74f261 | ||
|
|
3f720c9624 | ||
|
|
207cbffc05 | ||
|
|
0f2d049daf | ||
|
|
cd962a792e | ||
|
|
55ab852f4b | ||
|
|
1280bb454d | ||
|
|
3d295d8025 | ||
|
|
456dc422fc | ||
|
|
500e039023 | ||
|
|
3075c57bf4 | ||
|
|
cd290b0daa | ||
|
|
7dceeb13b8 | ||
|
|
686a52c702 | ||
|
|
788ef138b0 | ||
|
|
c5fbd85f0b | ||
|
|
008c87b572 | ||
|
|
b21d3365b7 | ||
|
|
a639f6bbec | ||
|
|
42b06a759f | ||
|
|
b3088ecfe4 | ||
|
|
a1d8b0650a | ||
|
|
9740c5fe74 | ||
|
|
bfdd0754ed | ||
|
|
df6404e2f5 | ||
|
|
22224b8304 | ||
|
|
11c83cab30 | ||
|
|
32f47019f0 | ||
|
|
ee3c3ff237 | ||
|
|
467734b04e | ||
|
|
2c02a11a51 | ||
|
|
28125c53b5 | ||
|
|
bd01f49307 | ||
|
|
c77f693f51 | ||
|
|
6915d54e9f | ||
|
|
4b99970499 | ||
|
|
f13e579c26 | ||
|
|
6b8e95a34f | ||
|
|
94875789ca | ||
|
|
c5a14f7ec4 | ||
|
|
ec14b08b13 | ||
|
|
8d6e60df0f | ||
|
|
fd168103b8 | ||
|
|
f2ddc223b6 | ||
|
|
e1df9b5c14 | ||
|
|
e1083a25f7 | ||
|
|
fe3ea7401d | ||
|
|
f0de6a74b6 | ||
|
|
1815a69384 | ||
|
|
cefa86ccea | ||
|
|
4d6426249a | ||
|
|
af7a73b5f7 | ||
|
|
9035fda953 | ||
|
|
2f34d06d53 | ||
|
|
b4df47d8c8 | ||
|
|
4d270c04d1 | ||
|
|
245f9e5090 | ||
|
|
ea56586c04 | ||
|
|
2b28d4e60f | ||
|
|
ee1aa7620c | ||
|
|
128759d892 | ||
|
|
9f6acff3f5 | ||
|
|
9191713854 | ||
|
|
0c871cbd68 | ||
|
|
8a71067f33 | ||
|
|
8f038a2476 | ||
|
|
52dad58417 | ||
|
|
97bbf28724 | ||
|
|
b06558f7fc | ||
|
|
9e4bb24349 | ||
|
|
2c269334ab | ||
|
|
b594e954d8 | ||
|
|
de545a639e | ||
|
|
cc9f0cc6da | ||
|
|
35588c7f9e | ||
|
|
c5920c39e8 | ||
|
|
1ffcaee719 | ||
|
|
9f619f71cc | ||
|
|
1e63d81675 | ||
|
|
a13415c31f | ||
|
|
22554bed89 | ||
|
|
db1155d958 | ||
|
|
e0b446f108 | ||
|
|
ba51fad9d2 | ||
|
|
bf19cc9606 | ||
|
|
d4b7faa3ff | ||
|
|
8c8fba1874 | ||
|
|
b53b8411c4 | ||
|
|
c380541d30 | ||
|
|
6ce3e4b250 | ||
|
|
ca970b80e7 | ||
|
|
f80fee03bd | ||
|
|
2b9ead20f9 | ||
|
|
f0f9b98f0f | ||
|
|
1cccfd3c66 | ||
|
|
79f2bc3a06 | ||
|
|
2970fc027f | ||
|
|
a8fe573099 | ||
|
|
6171621ea3 | ||
|
|
f6d0e32a02 | ||
|
|
1697548096 | ||
|
|
8bd9ea4b3f | ||
|
|
c9baddf99f | ||
|
|
bba0093d38 | ||
|
|
bfd69205ef | ||
|
|
d6c7c03ebe | ||
|
|
32b49c788c | ||
|
|
f447bdaa8f | ||
|
|
1b468c92f9 | ||
|
|
264ab81bd9 | ||
|
|
fbb2824944 | ||
|
|
34331c5a79 | ||
|
|
935e458161 | ||
|
|
31f5c10ffe | ||
|
|
c77efb4ba1 | ||
|
|
e7510b606e | ||
|
|
ff2dc465f7 | ||
|
|
43de9c4f6a | ||
|
|
126098289b | ||
|
|
087a69eb78 | ||
|
|
ad621ed1f0 | ||
|
|
f4821a0935 | ||
|
|
54bee8a76b | ||
|
|
49080efe82 | ||
|
|
5973b65a81 | ||
|
|
e0f8ed8415 | ||
|
|
fb808245e3 | ||
|
|
159462606f | ||
|
|
7d1ba026db | ||
|
|
18199cf553 | ||
|
|
1fd87edf97 | ||
|
|
76097a2c65 | ||
|
|
cc5eb4332c | ||
|
|
54ad1db5c8 | ||
|
|
a3af25f5b0 | ||
|
|
ca9ebb9972 | ||
|
|
6ec9182ad0 | ||
|
|
dbdf070383 | ||
|
|
efb033096e | ||
|
|
85ab7c0184 | ||
|
|
0c17daf51b | ||
|
|
91bd482969 | ||
|
|
010ab29959 | ||
|
|
3f897aa4f8 | ||
|
|
d17158db77 | ||
|
|
29c80be876 | ||
|
|
76dc608ed8 | ||
|
|
88aaf24794 | ||
|
|
ded4524241 | ||
|
|
65b3027992 | ||
|
|
a99144ee23 | ||
|
|
022b84e40d | ||
|
|
21125870c0 | ||
|
|
d72ca3c6cc | ||
|
|
0622b4004a | ||
|
|
8348a94edb | ||
|
|
c96bd66166 | ||
|
|
21a54d7591 | ||
|
|
b8fb092432 | ||
|
|
5f6d3ee14e | ||
|
|
f6b143d489 | ||
|
|
8e5d085924 | ||
|
|
e1b4627f33 | ||
|
|
fd50372b5d | ||
|
|
322edf01ba | ||
|
|
50059a9790 | ||
|
|
1115e30d3b | ||
|
|
518877e2f6 | ||
|
|
11f98faf74 | ||
|
|
b0749f1b2b | ||
|
|
c7cba11e85 | ||
|
|
a1bcd98682 | ||
|
|
95b077f039 | ||
|
|
840a2b71e8 | ||
|
|
8325bb3375 | ||
|
|
00e078cfa4 | ||
|
|
105039ee2f | ||
|
|
b3c3ce62ab | ||
|
|
e0a501e35b | ||
|
|
89403cd164 | ||
|
|
6d1ad5ad65 | ||
|
|
41551f5654 | ||
|
|
3c6ae7d9c0 | ||
|
|
46cf12e858 | ||
|
|
8bb7956042 | ||
|
|
d70f6dae3b | ||
|
|
9b4da26149 | ||
|
|
c8fb2a8ff4 | ||
|
|
a08cb0df7b | ||
|
|
eeee70fd5f | ||
|
|
e0615cb2b5 | ||
|
|
fe01932aad | ||
|
|
90ef491973 | ||
|
|
eb8aad0e2c | ||
|
|
e20f7e2382 | ||
|
|
925cfb5a64 | ||
|
|
d17734fd9b | ||
|
|
0cf6547fed | ||
|
|
35e712e21b | ||
|
|
4bfd392609 | ||
|
|
ed9ed5b85f | ||
|
|
53958ef6fb | ||
|
|
e263d6b598 | ||
|
|
41b42da633 | ||
|
|
5003a1e5ca | ||
|
|
949096259a | ||
|
|
4feb3d4230 | ||
|
|
4be8421fae | ||
|
|
652c2a1799 | ||
|
|
668289e248 | ||
|
|
37417f1e1f | ||
|
|
6901a209e2 | ||
|
|
67e37c58b4 | ||
|
|
9319fb8ca6 | ||
|
|
75e51b4368 | ||
|
|
65e54c1d17 | ||
|
|
894290024a | ||
|
|
c47c99e3af | ||
|
|
549b72685e | ||
|
|
5c7bc9630e | ||
|
|
e591235f8a | ||
|
|
fde1fa7173 | ||
|
|
ebbe91df3c | ||
|
|
69d55d3b84 | ||
|
|
963bcc28fe | ||
|
|
8e11381d68 | ||
|
|
39107da5c3 | ||
|
|
101fb38bfc | ||
|
|
65e2a389ca | ||
|
|
57ef35fd81 | ||
|
|
2c8296bf53 | ||
|
|
8413b6a841 | ||
|
|
1dff00b209 | ||
|
|
b43945927a | ||
|
|
d2e66d0081 | ||
|
|
576c774001 | ||
|
|
07c8dfab7c | ||
|
|
fe26b3ba57 | ||
|
|
a40beb072a | ||
|
|
720c8513c5 | ||
|
|
a7ab68a82a | ||
|
|
8a5b76955d | ||
|
|
dd3e9ffb8d | ||
|
|
c1adff4357 | ||
|
|
8dc14759a1 | ||
|
|
e6d4839ffc | ||
|
|
b90e090fec | ||
|
|
33c3ef25dc | ||
|
|
b7a16be235 | ||
|
|
b8d7c3fe1b | ||
|
|
74efddd5f4 | ||
|
|
945263e788 | ||
|
|
11cf0a20b7 | ||
|
|
04027d1310 | ||
|
|
fdc0cdeb8b | ||
|
|
10d46bb28e | ||
|
|
da1637a882 | ||
|
|
02afe10001 | ||
|
|
cbe38462e2 | ||
|
|
66fff2949c | ||
|
|
434a9bd053 | ||
|
|
54e84ef141 | ||
|
|
79580a4fec | ||
|
|
680672d641 | ||
|
|
eb5c21f8b4 | ||
|
|
4d8a8e93fb | ||
|
|
a5e72d83c5 | ||
|
|
7528f2f3b0 | ||
|
|
d1660dba51 | ||
|
|
7755c56386 | ||
|
|
ccd51b88fa | ||
|
|
65978ae49a | ||
|
|
7875745bfe | ||
|
|
2f778b9dd9 | ||
|
|
b7ce1a1bd5 | ||
|
|
d5a0face2b | ||
|
|
0358ebe99d | ||
|
|
3b3ec3e396 | ||
|
|
fa1946c7d9 | ||
|
|
decf483773 | ||
|
|
7866ca3e84 | ||
|
|
0a82070f27 | ||
|
|
e77320ac9e | ||
|
|
21486dd01b | ||
|
|
4ce5db9db3 | ||
|
|
9ccb92ab46 | ||
|
|
15e73ac7cf | ||
|
|
e5e2ff55fa | ||
|
|
781045b019 | ||
|
|
fa2cbffbd5 | ||
|
|
e4e3f15eff | ||
|
|
66dbc98ff7 | ||
|
|
00a034905b | ||
|
|
d8aa553a09 | ||
|
|
1aad10c239 | ||
|
|
1ae8ff82e5 | ||
|
|
ecfa6ea920 | ||
|
|
de01ff004e | ||
|
|
a075a22dac | ||
|
|
7da39401a4 | ||
|
|
b1a819ad57 | ||
|
|
6a0f4e8070 | ||
|
|
a941f1d9c2 | ||
|
|
8717a4fc02 | ||
|
|
7227b7d97c | ||
|
|
ef1273e815 | ||
|
|
76b863c7ea | ||
|
|
849be9e037 | ||
|
|
0695681d7c | ||
|
|
b5a67bf540 | ||
|
|
83744d69a7 | ||
|
|
e5e2c767a0 | ||
|
|
31650d2f87 | ||
|
|
c19a5dab9e | ||
|
|
84763ca40d | ||
|
|
ffd615080b | ||
|
|
bfcdbd2cda | ||
|
|
b32310dad9 | ||
|
|
6f461a78b5 | ||
|
|
e1e553e39c | ||
|
|
873f5830d0 | ||
|
|
b6c062b365 | ||
|
|
22a294c135 | ||
|
|
e141921ac8 | ||
|
|
012c0e5661 | ||
|
|
c7dfb541f3 | ||
|
|
1ea8c670f7 | ||
|
|
7ed9553ee3 | ||
|
|
ba67bef0d2 | ||
|
|
6902bb5020 | ||
|
|
8442c3a3fd | ||
|
|
e6cf33c740 | ||
|
|
39daa3258a | ||
|
|
ef60fa5ee5 | ||
|
|
9ec5f14c6b | ||
|
|
affd550c24 | ||
|
|
454598b4c0 | ||
|
|
c2016c28c8 | ||
|
|
7dd4936c57 | ||
|
|
21fefa6115 | ||
|
|
386f8ce2ec | ||
|
|
21f673ccbb | ||
|
|
f0448ada69 | ||
|
|
34c3a5f9e6 | ||
|
|
e1c0570dc5 | ||
|
|
1b89bf16ba | ||
|
|
43d2b9ac84 | ||
|
|
c1a8102d17 | ||
|
|
6bf6cb679d | ||
|
|
30c56819ca | ||
|
|
52e84b6a7c | ||
|
|
c6a9193bff | ||
|
|
f1e4a05f67 | ||
|
|
7ea8fc3b61 | ||
|
|
79cc5d8230 | ||
|
|
f4da670b85 | ||
|
|
d4a2e17537 | ||
|
|
e7edd17483 | ||
|
|
1dcee6ed85 | ||
|
|
4f1ff924a8 | ||
|
|
c9777da390 | ||
|
|
c7ae69b2d7 | ||
|
|
4f24f5fe40 | ||
|
|
ce0372fd73 | ||
|
|
694fbaa5a2 | ||
|
|
be2773de2b | ||
|
|
6df12e022a | ||
|
|
5e5ff95ef7 | ||
|
|
c8c39cfeb1 | ||
|
|
15f7d3d20e | ||
|
|
89056a9d5d | ||
|
|
db4f81cb38 | ||
|
|
b39d5925b0 | ||
|
|
2daba8f0b4 | ||
|
|
4e1bb2a25a | ||
|
|
8879b09200 | ||
|
|
c7b3f9e02d | ||
|
|
9fcc08fc3a | ||
|
|
81611988c3 | ||
|
|
bfa2adc9ce | ||
|
|
b4cc30dc29 | ||
|
|
e236250e5b | ||
|
|
7e9d0e6a2b | ||
|
|
0e9f773d55 | ||
|
|
8ac019cefb | ||
|
|
0d677e4f51 | ||
|
|
aaf6c6c72e | ||
|
|
ac78a328eb | ||
|
|
0e915e0437 | ||
|
|
d23bea5a3a | ||
|
|
4a2f553be7 | ||
|
|
7337591710 | ||
|
|
ed6ec28ab4 | ||
|
|
250533e660 | ||
|
|
1c1b2ea9f4 | ||
|
|
8cd9b383ad | ||
|
|
a673032d34 | ||
|
|
6829370337 | ||
|
|
431cbbc6c3 | ||
|
|
29a312d9ef | ||
|
|
107dae72db | ||
|
|
acfc829c9e | ||
|
|
ee8247ec03 | ||
|
|
b81fcbdfd5 | ||
|
|
8b6e21c991 | ||
|
|
109af9e274 | ||
|
|
ff8e978614 | ||
|
|
c6a894b633 | ||
|
|
34177f0205 | ||
|
|
1a61edcb1d | ||
|
|
04f1216708 | ||
|
|
3b516a576a | ||
|
|
c61282ef5b | ||
|
|
b7c83570c2 | ||
|
|
698f76a8b2 | ||
|
|
607e704537 | ||
|
|
9806696566 | ||
|
|
ff8a240aac | ||
|
|
7801a6da7c | ||
|
|
f1a484e514 | ||
|
|
87555cfae7 | ||
|
|
0fe45fd684 | ||
|
|
92c90b9eff | ||
|
|
65434b299a | ||
|
|
b11e39d2d9 | ||
|
|
0aba0aaa50 | ||
|
|
6f77396704 | ||
|
|
dc19217a06 | ||
|
|
e4e80b135b | ||
|
|
c81937785a | ||
|
|
d872c00600 | ||
|
|
142c5531b4 | ||
|
|
adc28afc97 | ||
|
|
034eed5529 | ||
|
|
f8342709cb | ||
|
|
eb3499678d | ||
|
|
79383ca86f | ||
|
|
d0c625a30c | ||
|
|
49fe303eff | ||
|
|
1e82f4e558 | ||
|
|
f6b907585b | ||
|
|
f00d64699e | ||
|
|
35522222e5 | ||
|
|
40627fc68e | ||
|
|
d3add0b065 | ||
|
|
5f9d7bcff4 | ||
|
|
34f15d4926 | ||
|
|
c4ab9abd8b | ||
|
|
7da7cc3d9f | ||
|
|
b98becc8b7 | ||
|
|
60e4c4c75e | ||
|
|
cd5ca874ef | ||
|
|
527685e5fd | ||
|
|
46b91762c7 | ||
|
|
c5c274646b | ||
|
|
c3b7b72437 | ||
|
|
ec0f31eccb | ||
|
|
f559614992 | ||
|
|
75d6135498 | ||
|
|
66f5f5845d | ||
|
|
7e42d91bc9 | ||
|
|
ac7c00caf4 | ||
|
|
c27e94d91a | ||
|
|
814151c604 | ||
|
|
fa0d39183e | ||
|
|
c5e5f16faf | ||
|
|
71c08b48e6 | ||
|
|
f9248c70ff | ||
|
|
fb5bfdcb7f | ||
|
|
68bdab6756 | ||
|
|
367988575f | ||
|
|
237f028135 | ||
|
|
451e90660b | ||
|
|
e73b625533 | ||
|
|
f1c33c1581 | ||
|
|
4762092265 | ||
|
|
7c979921b5 | ||
|
|
dcb4ce2aec | ||
|
|
1e75fb2496 | ||
|
|
1bf72241c5 | ||
|
|
946666971c | ||
|
|
acd8a71676 | ||
|
|
03822446fb | ||
|
|
7f1391b53f | ||
|
|
f79cb88f19 | ||
|
|
e69e5c958d | ||
|
|
4e155de716 | ||
|
|
54a28dc851 | ||
|
|
0d3492c6e2 | ||
|
|
5583aa331c | ||
|
|
75917ecd3b | ||
|
|
a4b70f7874 | ||
|
|
bf1932af14 | ||
|
|
d1b83f9b02 | ||
|
|
04a5a289aa | ||
|
|
e2dc67831d | ||
|
|
0b2a56b859 | ||
|
|
bc546a38de | ||
|
|
6868375992 | ||
|
|
15ea427ec5 | ||
|
|
a27f642240 | ||
|
|
afa9b31c4c | ||
|
|
37e6eee311 | ||
|
|
658e5dc747 | ||
|
|
509225c8d2 | ||
|
|
92e6d0c760 | ||
|
|
8d655ac2da | ||
|
|
d0f2438d44 | ||
|
|
6a3d185b2b | ||
|
|
2656ef82cd | ||
|
|
134a0c464d | ||
|
|
6d398465f9 | ||
|
|
3ac91dcc82 | ||
|
|
16eb4796a0 | ||
|
|
9711799d06 | ||
|
|
116a1195f2 | ||
|
|
5600626386 | ||
|
|
bcf3af51ef | ||
|
|
85ed69c790 | ||
|
|
6fc936e66f | ||
|
|
c1762bf787 | ||
|
|
86b21a98f0 | ||
|
|
ab8166e1cf | ||
|
|
f299892792 | ||
|
|
5d5d7f0e67 | ||
|
|
b42ac636f0 | ||
|
|
9320ec4ac7 | ||
|
|
6aa97914b4 | ||
|
|
03c268b840 | ||
|
|
cd7977fa5d | ||
|
|
be23df0964 | ||
|
|
ec4b043c00 | ||
|
|
cb62d6d9c9 | ||
|
|
32c081354a | ||
|
|
ce8543e048 | ||
|
|
bd181add0b | ||
|
|
a9e1fe68a8 | ||
|
|
2da534d5fa | ||
|
|
742b0e7d29 | ||
|
|
08e3658741 | ||
|
|
2b5933b991 | ||
|
|
a7af11df4e | ||
|
|
7a36514339 | ||
|
|
847992a550 | ||
|
|
4579edafa0 | ||
|
|
2bc99f976a | ||
|
|
7256a9a8a8 | ||
|
|
e5d04632d5 | ||
|
|
0e75814ad4 | ||
|
|
51cafc1874 | ||
|
|
7c0714c7e6 | ||
|
|
6cc8118d28 | ||
|
|
4e047df4ee | ||
|
|
47c8da0e28 | ||
|
|
1b2833bd26 | ||
|
|
abc5dc471b | ||
|
|
ad20093b7f | ||
|
|
56e4ed86a3 | ||
|
|
984a2564fc | ||
|
|
57e37a6773 | ||
|
|
63d54fc6af | ||
|
|
02cf9664ae | ||
|
|
15357d168b | ||
|
|
035f6707c1 | ||
|
|
782432ca01 | ||
|
|
662e3c8ead | ||
|
|
bdd0f32b50 | ||
|
|
1321b75fff | ||
|
|
e34a651ac0 | ||
|
|
861d7bf029 | ||
|
|
5eff320fcb | ||
|
|
f11e8248d0 | ||
|
|
15ae50ace3 | ||
|
|
a417789bc2 | ||
|
|
c1d3945035 | ||
|
|
c4bd02d99f | ||
|
|
cd2b8d5ba8 | ||
|
|
2ea9652950 | ||
|
|
2ff4e99eaa | ||
|
|
69a3b0f10c | ||
|
|
75b7e4d4ff | ||
|
|
1a61eb257c | ||
|
|
384288806b | ||
|
|
f7e06aac9d | ||
|
|
16232d530b | ||
|
|
3035ab0fb4 | ||
|
|
fe43845ee2 | ||
|
|
bf85745bbb | ||
|
|
250f5453fb | ||
|
|
3334d7ad75 | ||
|
|
b9ccb9c883 | ||
|
|
5144a0c868 | ||
|
|
940be59861 | ||
|
|
63a634de52 | ||
|
|
2c62a6763b | ||
|
|
da57ec87d0 | ||
|
|
751254246a | ||
|
|
13835ef100 | ||
|
|
f3ef92f7ca | ||
|
|
49389aea80 | ||
|
|
240160f605 | ||
|
|
7aeb66ccce | ||
|
|
3721cd73ba | ||
|
|
840c232c5f | ||
|
|
f277e1f0c3 | ||
|
|
d0ab801141 | ||
|
|
b44c4d3c8e | ||
|
|
1b3446fe16 | ||
|
|
7948d6df58 | ||
|
|
5062575687 | ||
|
|
821510a5c4 | ||
|
|
fe478e275a | ||
|
|
2e884c4ce6 | ||
|
|
57a07bdb4c | ||
|
|
9586169df9 | ||
|
|
3c955df9e9 | ||
|
|
a36b1553ee | ||
|
|
0cfee32754 | ||
|
|
22507a963a | ||
|
|
e9ab99a8f1 | ||
|
|
a12945b800 | ||
|
|
8c049ad6fe | ||
|
|
d50129f95c | ||
|
|
99c391fb9f | ||
|
|
47f6a9ac46 | ||
|
|
0f0d91d824 | ||
|
|
dd41094d50 | ||
|
|
676c64a2aa | ||
|
|
709df6c4ac | ||
|
|
f2096262fa | ||
|
|
73763282b7 | ||
|
|
43f07d3c88 | ||
|
|
ecc7d9ba86 | ||
|
|
c9205461c1 | ||
|
|
65974dc29d | ||
|
|
b452abc839 | ||
|
|
debcec5881 | ||
|
|
2f15322530 | ||
|
|
cce80c3f1d | ||
|
|
5647025c0c | ||
|
|
ebb0d64993 | ||
|
|
96a1ed0b8f | ||
|
|
8d6ba8f390 | ||
|
|
6ee5cbf07a | ||
|
|
aba008b9b7 | ||
|
|
a9a088ef1f | ||
|
|
3fc274a4cf | ||
|
|
ba8f1f3ccf | ||
|
|
db122be70b | ||
|
|
9781d9b7cd | ||
|
|
3feae381dd | ||
|
|
9c2156a025 | ||
|
|
4ac4d34af7 | ||
|
|
9a4c0bb7c3 | ||
|
|
ebd8ecb06c | ||
|
|
98a9b04fb1 | ||
|
|
19f1e5517a | ||
|
|
ee248d5fff | ||
|
|
b3d4d009aa | ||
|
|
d2f01b00eb | ||
|
|
a076cca120 | ||
|
|
42e48c71e0 | ||
|
|
b3a9f566df | ||
|
|
5ef76f8592 | ||
|
|
fbc7f9668d | ||
|
|
4c79e29cca | ||
|
|
0ab4df1655 | ||
|
|
4b128f68a9 | ||
|
|
b0687c26d2 | ||
|
|
c6674c0185 | ||
|
|
69b313f83e | ||
|
|
d76385094e | ||
|
|
772e56a62e | ||
|
|
ab2eb8a1f9 | ||
|
|
d1dd7964c2 | ||
|
|
a1206f3886 | ||
|
|
6c24ddee41 | ||
|
|
e4afb704fe | ||
|
|
aedb754045 | ||
|
|
1991635e2a | ||
|
|
8ad7691ba9 | ||
|
|
30df0133e7 | ||
|
|
c2cee019de | ||
|
|
812d1eceef | ||
|
|
d7653edd9d | ||
|
|
f294fb48b7 | ||
|
|
19f3c013aa | ||
|
|
5edd511b5b | ||
|
|
b46048533c | ||
|
|
d0c0516fa2 | ||
|
|
eeb46a43f1 | ||
|
|
31412ebe1e | ||
|
|
5b885a5447 | ||
|
|
8df9924e76 | ||
|
|
f6d3a73bb3 | ||
|
|
2581cc50b4 | ||
|
|
be36bd367d | ||
|
|
064110eaa2 | ||
|
|
794d472d29 | ||
|
|
dd9668fd41 | ||
|
|
5a2c86ad40 | ||
|
|
35a47b2418 | ||
|
|
304d4cda21 | ||
|
|
211f371fd5 | ||
|
|
3a5e8d1471 | ||
|
|
93ec57af84 | ||
|
|
e5b8670c6d | ||
|
|
88b979623a | ||
|
|
458913d017 | ||
|
|
d9373fa6d8 | ||
|
|
34e884c47a | ||
|
|
ee9d5d3832 | ||
|
|
230784e3fb | ||
|
|
8119bc5c8c | ||
|
|
94570c4c1b | ||
|
|
aade35f0db | ||
|
|
289e00d760 |
@@ -49,7 +49,7 @@
|
||||
;; disabled linters
|
||||
;;
|
||||
|
||||
:redundant-ignore {:level :off} ; lots of false positives, see https://github.com/clj-kondo/clj-kondo/issues/2414
|
||||
:redundant-ignore {:level :off} ; lots of false positives, see https://github.com/clj-kondo/clj-kondo/issues/2414
|
||||
:unexpected-recur {:level :off} ; TODO (cam): I think we just need to tell it how to handle MBQL match and we can enable this?
|
||||
|
||||
;;
|
||||
@@ -173,7 +173,6 @@
|
||||
metabase.driver.sql-jdbc.execute/execute-prepared-statement!
|
||||
metabase.notification.models/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!
|
||||
@@ -215,7 +214,7 @@
|
||||
;; misc config for built-in linters
|
||||
;;
|
||||
|
||||
:invalid-arity {:skip-args [metabase.lib.util.match/match]} ; TODO (cam): can we fix these?
|
||||
:invalid-arity {:skip-args [metabase.lib.util.match/match]} ; TODO (cam): can we fix these?
|
||||
:refer-all {:level :warning, :exclude [clojure.test]}
|
||||
:unused-referred-var {:exclude {compojure.core [GET DELETE POST PUT]}}
|
||||
|
||||
@@ -250,16 +249,15 @@
|
||||
(taoensso.nippy/extend-freeze)
|
||||
(taoensso.nippy/extend-thaw)]}
|
||||
|
||||
;; TODO (Cam 8/22/25) -- what's the point of marking stuff deprecated if we don't have Kondo enforce it? We should
|
||||
;; remove all of these and add individual ignores as needed.
|
||||
:deprecated-var
|
||||
{:exclude
|
||||
{metabase.cmd.core/dump {:namespaces ["metabase\\.cmd-test" "metabase-enterprise\\.serialization\\.cmd-test"]}
|
||||
metabase.cmd.core/load {:namespaces ["metabase\\.cmd-test" "metabase-enterprise\\.serialization\\.cmd-test"]}
|
||||
metabase.driver.sql-jdbc.execute.old-impl/set-timezone-sql {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql-jdbc.execute/set-time-zone-if-supported! {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver/current-db-time {:namespaces ["metabase.*"]}
|
||||
metabase.driver/supports? {:namespaces ["metabase.*"]}
|
||||
metabase.query-processor.middleware.resolve-joins/maybe-resolve-source-table {:namespaces ["metabase.*"]}
|
||||
metabase.query-processor.util/normalize-token {:namespaces ["metabase.*"]}}}
|
||||
{metabase.driver.sql-jdbc.execute.old-impl/set-timezone-sql {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver.sql-jdbc.execute/set-time-zone-if-supported! {:namespaces ["metabase\\.driver.*"]}
|
||||
metabase.driver/current-db-time {:namespaces ["metabase.*"]}
|
||||
metabase.driver/supports? {:namespaces ["metabase.*"]}
|
||||
metabase.query-processor.util/normalize-token {:namespaces ["metabase.*"]}}}
|
||||
|
||||
:discouraged-var
|
||||
{clojure.core/print {:message "Use metabase.util.log instead of clojure.core/print"}
|
||||
@@ -292,6 +290,8 @@
|
||||
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.convert/->legacy-MBQL {:message "Conversion to legacy MBQL is discouraged, please use Lib to manipulate MBQL queries"}
|
||||
metabase.lib.core/->legacy-MBQL {:message "Conversion to legacy MBQL is discouraged, please use Lib to manipulate MBQL queries"}
|
||||
metabase.lib.equality/find-column-indexes-for-refs {:message "Use lib.equality/closest-matches-in-metadata or lib.equality/find-closest-matches-for-refs instead of lib.equality/find-column-indexes-for-refs"}
|
||||
next.jdbc/active-tx? {:message "Use metabase.app-db.core/in-transaction? to see if we are in a transaction"}
|
||||
toucan2.core/debug {:message "Don't commit code using t2/debug"}
|
||||
@@ -300,6 +300,7 @@
|
||||
:discouraged-namespace
|
||||
{camel-snake-kebab.core {:message "CSK is not Turkish-safe, use the versions in metabase.util instead."}
|
||||
cheshire.core {:message "Use metabase.util.json instead of cheshire.core directly."}
|
||||
clj-time.core {:message "Use java-time.api or metabase.util.date-2 instead of clj-time"}
|
||||
clojure.tools.logging {:message "Use metabase.util.log instead of clojure.tools.logging directly"}
|
||||
grouper.core {:message "Use metabase.util.grouper instead of grouper.core"}
|
||||
honeysql.core {:message "Use Honey SQL 2. Honey SQL 1 is removed as a dependency in Metabase 49+."}
|
||||
@@ -408,11 +409,16 @@
|
||||
clojure.test.check.clojure-test/defspec clojure.test/deftest
|
||||
clojure.test.check.properties/for-all clojure.core/let
|
||||
clojurewerkz.quartzite.jobs/defjob clojure.core/defn
|
||||
com.climate.claypoole/with-shutdown! clojure.core/let
|
||||
instaparse.core/defparser clojure.core/def
|
||||
metabase-enterprise.action-v2.test-util/with-test-tables! clojure.core/let
|
||||
metabase-enterprise.content-translation.routes-test/with-new-secret-key! clojure.core/fn
|
||||
metabase-enterprise.serialization.test-util/with-dbs clojure.core/fn
|
||||
metabase-enterprise.serialization.test-util/with-random-dump-dir clojure.core/let
|
||||
metabase-enterprise.content-translation.routes-test/with-new-secret-key! clojure.core/fn
|
||||
metabase-enterprise.transforms.api-test/with-transform-tags clojure.core/let
|
||||
metabase-enterprise.transforms.api-test/with-worker-runs clojure.core/let
|
||||
metabase-enterprise.transforms.test-util/with-transform-cleanup! clojure.core/let
|
||||
metabase-enterprise.transforms.execute/with-transform-lifecycle clojure.core/let
|
||||
metabase.actions.test-util/with-actions clojure.core/let
|
||||
metabase.api.common/let-404 clojure.core/let
|
||||
metabase.app-db.custom-migrations.util/with-temp-scheduler! clojure.core/fn
|
||||
@@ -512,6 +518,7 @@
|
||||
metabase-enterprise.advanced-permissions.models.permissions.application-permissions-test/with-new-group-and-current-graph hooks.common/with-two-top-level-bindings
|
||||
metabase-enterprise.audit-app.pages-test/with-temp-objects hooks.common/with-one-binding
|
||||
metabase-enterprise.cache.config-test/with-temp-persist-models hooks.common/with-seven-bindings
|
||||
metabase-enterprise.semantic-search.db.connection/with-migrate-tx hooks.common/let-one-with-optional-value
|
||||
metabase-enterprise.serialization.test-util/with-temp-dpc hooks.toucan2.tools.with-temp/with-temp
|
||||
metabase.api.common.internal-test/with-jetty-server hooks.common/with-one-binding
|
||||
metabase.api.macros/defendpoint hooks.metabase.api.macros/defendpoint
|
||||
@@ -543,6 +550,7 @@
|
||||
metabase.lib.schema.mbql-clause/define-tuple-mbql-clause hooks.metabase.lib.schema.mbql-clause/define-mbql-clause
|
||||
metabase.lib.test-util.macros/$ids hooks.metabase.test.data/$ids
|
||||
metabase.lib.test-util.macros/mbql-query hooks.metabase.test.data/mbql-query
|
||||
metabase.lib.test-util.macros/mbql-5-query hooks.metabase.test.data/mbql-query
|
||||
metabase.lib.test-util.macros/with-testing-against-standard-queries hooks.metabase.lib.test-util.macros/with-testing-against-standard-queries
|
||||
metabase.model-persistence.api-test/with-persistence-setup! hooks.common/with-one-top-level-binding
|
||||
metabase.model-persistence.api-test/with-setup! hooks.common/with-one-top-level-binding
|
||||
@@ -642,6 +650,7 @@
|
||||
|
||||
:macroexpand
|
||||
{clojurewerkz.quartzite.jobs/build macros.quartz/build-job
|
||||
clojurewerkz.quartzite.schedule.calendar-interval/build macros.quartz/build-job
|
||||
clojurewerkz.quartzite.schedule.cron/schedule macros.quartz/schedule
|
||||
clojurewerkz.quartzite.schedule.simple/schedule macros.quartz/simple-schedule
|
||||
clojurewerkz.quartzite.triggers/build macros.quartz/build-trigger
|
||||
@@ -716,12 +725,19 @@
|
||||
{:pattern "metabase\\.driver.*$"
|
||||
:name driver-namespaces}
|
||||
;;
|
||||
;; Perf-sensitive namespaces are currently the union of metabase.lib.*, driver namespaces, and QP (without tests).
|
||||
;;
|
||||
{:pattern "^(?!.*-test(?:\\..*)?$)(?!.*test-util)(?!^metabase\\.test.*)^metabase\\.(lib|driver|legacy-mbql|query-processor).*"
|
||||
:name performance-sensitive}
|
||||
;;
|
||||
;; general QP tests are ones that run across multiple drivers. Anything `metabase.query-processor*-test`,
|
||||
;; `metabase.driver.sql*-test` (excluding SQLServer and SQLite), or
|
||||
;; `metabase-enterprise.sandbox.query-processor*-test`
|
||||
;;
|
||||
{:pattern "^metabase(?:((?:-enterprise\\.sandbox)?\\.query-processor)|(?:\\.driver\\.sql(?!server)(?!ite))).*-test$"
|
||||
:name general-qp-and-driver-test-namespaces}]
|
||||
:name general-qp-and-driver-test-namespaces}
|
||||
{:pattern "^metabase\\.python-runner\\..*"
|
||||
:name python-runner-namespaces}]
|
||||
|
||||
:config-in-ns
|
||||
{test-namespaces
|
||||
@@ -729,9 +745,13 @@
|
||||
{:inline-def {:level :off}
|
||||
:missing-docstring {:level :off}
|
||||
:private-call {:level :off}
|
||||
:discouraged-var {metabase.driver/database-supports? {:level :off}}
|
||||
:metabase/defsetting-must-specify-export {:level :off}
|
||||
:metabase/defsetting-namespace {:level :off}}
|
||||
:metabase/defsetting-namespace {:level :off}
|
||||
|
||||
:discouraged-var
|
||||
{metabase.driver/database-supports? {:level :off}
|
||||
metabase.lib.convert/->legacy-MBQL {:level :off}
|
||||
metabase.lib.core/->legacy-MBQL {:level :off}}}
|
||||
|
||||
:hooks
|
||||
{:analyze-call
|
||||
@@ -744,9 +764,13 @@
|
||||
{:metabase/validate-escaped-single-quotes-in-i18n {:level :warning}
|
||||
:metabase/validate-string-or-str-args-to-i18n {:level :warning}
|
||||
:metabase/discourage-millis-duration {:level :warning}
|
||||
|
||||
:discouraged-var
|
||||
{clojure.core/with-redefs {:message "Don't use with-redefs outside of tests"}
|
||||
clojure.core/eval {:message "Don't use eval outside of tests"}}}}
|
||||
clojure.core/eval {:message "Don't use eval outside of tests"}}
|
||||
|
||||
:discouraged-namespace
|
||||
{metabase.query-processor.store {:message "Please do not use the QP Store outside of legacy QP or driver code. Use MBQL 5/Lib or lib.metadata.jvm/applicaton-database-metadata-provider instead."}}}}
|
||||
|
||||
printable-namespaces
|
||||
{:linters
|
||||
@@ -771,9 +795,11 @@
|
||||
;; eventually we should do this for the whole codebase, but the args are in the opposite order so switching them
|
||||
;; all at once isn't trivial, at least we can stop using it in new code.
|
||||
:discouraged-var
|
||||
{medley.core/map-keys {:message "Use clojure.core/update-keys"}
|
||||
medley.core/map-vals {:message "Use clojure.core/update-vals"}
|
||||
metabase.test/with-temp {:message "Don't use application database inside MLv2 code"}}
|
||||
{medley.core/map-keys {:message "Use metabase.util.performance/update-keys"}
|
||||
medley.core/map-vals {:message "Use clojure.core/update-vals"}
|
||||
metabase.lib.convert/->legacy-MBQL {:level :off}
|
||||
metabase.lib.core/->legacy-MBQL {:level :off}
|
||||
metabase.test/with-temp {:message "Don't use application database inside Lib code"}}
|
||||
|
||||
:discouraged-namespace
|
||||
{metabase.driver {:message "MLv2 code should be independent of driver code/methods"}
|
||||
@@ -795,26 +821,36 @@
|
||||
{:discouraged-var
|
||||
{metabase.driver/database-supports? {:level :off}}}}
|
||||
|
||||
performance-sensitive
|
||||
{:linters
|
||||
{:discouraged-var
|
||||
{clojure.core/update-keys {:message "Use metabase.util.performance/update-keys"}}}}
|
||||
|
||||
qp-and-driver-source-namespaces
|
||||
{:linters
|
||||
{:discouraged-namespace
|
||||
{metabase.util.malli.schema {:message "Prefer metabase.lib.schema or metabase.legacy-mbql.schema schemas in QP/driver code"}
|
||||
toucan.db {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan.models {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan.util.test {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan2.core {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}}
|
||||
{metabase.query-processor.store {:level :off}
|
||||
metabase.util.malli.schema {:message "Prefer metabase.lib.schema or metabase.legacy-mbql.schema schemas in QP/driver code"}
|
||||
toucan.db {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan.models {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan.util.test {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
toucan2.core {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}}
|
||||
|
||||
:discouraged-var
|
||||
{medley.core/map-keys {:message "Use clojure.core/update-keys"}
|
||||
{medley.core/map-keys {:message "Use metabase.util.performance/update-keys"}
|
||||
medley.core/map-vals {:message "Use clojure.core/update-vals"}
|
||||
metabase.app-db.core/query {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
metabase.app-db.core/reducible-query {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}}}}
|
||||
metabase.app-db.core/reducible-query {:message "Don't use application database directly in QP code; use QP Store/metadata provider"}
|
||||
metabase.lib.convert/->legacy-MBQL {:level :off}
|
||||
metabase.lib.core/->legacy-MBQL {:level :off}}}}
|
||||
|
||||
general-qp-and-driver-test-namespaces
|
||||
{:linters
|
||||
{:discouraged-var
|
||||
{metabase.test/with-column-remappings {:message "Use metabase.lib.test-util/remap-metadata-provider instead of with-column-remappings in QP tests"}
|
||||
metabase.test.util/with-column-remappings {:message "Use metabase.lib.test-util/remap-metadata-provider instead of with-column-remappings in QP tests"}}
|
||||
{metabase.test/with-column-remappings {:message "Use lib.tu/remap-metadata-provider instead of with-column-remappings in QP tests"}
|
||||
metabase.test.util/with-column-remappings {:message "Use lib.tu/remap-metadata-provider instead of with-column-remappings in QP tests"}
|
||||
metabase.test/with-temp {:message "Use lib.tu/mock-metadata-provider in QP tests. Exceptions: tests for code that doesn't use MPs or models not supported by MPs"}
|
||||
toucan2.tools.with-temp/with-temp {:message "Use lib.tu/mock-metadata-provider in QP tests. Exceptions: tests for code that doesn't use MPs or models not supported by MPs"}}
|
||||
|
||||
:metabase/disallow-hardcoded-driver-names-in-tests
|
||||
{:level :warning}}}}}
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
metabase.lib.join/with-join-alias [[:default]]
|
||||
metabase.lib.join/with-join-conditions [[:default]]
|
||||
metabase.lib.test-util.macros/$ids [[:inner 0]]
|
||||
metabase.lib.test-util.macros/mbql-5-query [[:inner 0]]
|
||||
metabase.lib.test-util.macros/mbql-query [[:inner 0]]
|
||||
metabase.lib.util.match/match [[:inner 0]]
|
||||
metabase.lib.util.match/match-one [[:inner 0]]
|
||||
|
||||
@@ -14,6 +14,7 @@ if (shouldLintCssModules) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ignorePatterns: ["!.storybook"],
|
||||
rules: {
|
||||
strict: [2, "never"],
|
||||
"no-undef": 2,
|
||||
@@ -48,6 +49,7 @@ module.exports = {
|
||||
],
|
||||
curly: [1, "all"],
|
||||
eqeqeq: [1, "smart"],
|
||||
"import/no-duplicates": ["warn", { considerQueryString: true }],
|
||||
"import/no-default-export": 2,
|
||||
"import/no-named-as-default": 0,
|
||||
"import/no-commonjs": 1,
|
||||
@@ -178,6 +180,7 @@ module.exports = {
|
||||
{
|
||||
files: ["*.js", "*.jsx", "*.ts", "*.tsx"],
|
||||
rules: {
|
||||
"jtag-missing-key": "error",
|
||||
"no-unconditional-metabase-links-render": "error",
|
||||
"no-color-literals": "error",
|
||||
"no-literal-metabase-strings": "error",
|
||||
@@ -202,12 +205,14 @@ module.exports = {
|
||||
"enterprise/frontend/src/metabase-enterprise/whitelabel/**/*",
|
||||
"frontend/lint/**/*",
|
||||
"*.stories.*",
|
||||
"**/.storybook/*",
|
||||
"stories-data.*",
|
||||
"e2e/**/*",
|
||||
"**/tests/*",
|
||||
"release/**/*",
|
||||
"rspack.config.js",
|
||||
"rspack.main.config.js",
|
||||
"rspack.embedding-sdk-package.config.js",
|
||||
"rspack.embedding-sdk-bundle.config.js",
|
||||
],
|
||||
rules: {
|
||||
|
||||
50
.github/CODEOWNERS
vendored
@@ -1,11 +1,13 @@
|
||||
# Before changing this file, make sure you have read how we use it:
|
||||
# https://www.notion.so/metabase/Pull-Request-Code-Review-Guide-374f05df889748b69d67af753f9bc9b8?pvs=4#36550c04ceab40b5a8b8bee6264b090c
|
||||
|
||||
enterprise/frontend/src/embedding-sdk @metabase/embedding
|
||||
enterprise/frontend/src/embedding-sdk-package @metabase/embedding
|
||||
enterprise/frontend/src/embedding-sdk-bundle @metabase/embedding
|
||||
enterprise/frontend/src/embedding-sdk-shared @metabase/embedding
|
||||
frontend/src/metabase/embedding-sdk @metabase/embedding
|
||||
frontend/src/metabase/public/containers/PublicOrEmbeddedQuestion @metabase/embedding
|
||||
frontend/src/metabase/public/containers/PublicOrEmbeddedDashboard @metabase/embedding
|
||||
frontend/src/metabase/ui @metabase/core-frontend-admin-webapp
|
||||
frontend/src/metabase/ui @metabase/core-frontend-ux-west
|
||||
# snowplow/* @metabase/data
|
||||
src/metabase/analytics/prometheus.clj @metabase/cloud-ops
|
||||
.github @metabase/devexp
|
||||
@@ -20,8 +22,8 @@ docs/developers-guide # exclude from tech-writer ownership
|
||||
#
|
||||
|
||||
# modules/drivers @metabase/drivers
|
||||
src/metabase/driver/sql_jdbc/actions.clj @metabase/core-workflows
|
||||
test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-workflows
|
||||
src/metabase/driver/sql_jdbc/actions.clj @metabase/core-ux-east
|
||||
test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-ux-east
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/advanced_config @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/advanced_config @metabase/core-backend-admin-webapp
|
||||
@@ -53,8 +55,8 @@ test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-workflows
|
||||
# enterprise/backend/src/metabase_enterprise/core @metabase/devexp
|
||||
# enterprise/backend/test/metabase_enterprise/core @metabase/devexp
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/dashboard_subscription_filters @metabase/core-workflows
|
||||
# enterprise/backend/test/metabase_enterprise/dashboard_subscription_filters @metabase/core-workflows
|
||||
# enterprise/backend/src/metabase_enterprise/dashboard_subscription_filters @metabase/core-ux-east
|
||||
# enterprise/backend/test/metabase_enterprise/dashboard_subscription_filters @metabase/core-ux-east
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/enhancements @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/enhancements @metabase/core-backend-admin-webapp
|
||||
@@ -71,11 +73,11 @@ test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-workflows
|
||||
# enterprise/backend/src/metabase_enterprise/scim @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/scim @metabase/core-backend-admin-webapp
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/search @metabase/core-workflows
|
||||
# enterprise/backend/test/metabase_enterprise/search @metabase/core-workflows
|
||||
# enterprise/backend/src/metabase_enterprise/search ...
|
||||
# enterprise/backend/test/metabase_enterprise/search ...
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/serialization @metabase/core-workflows
|
||||
# enterprise/backend/test/metabase_enterprise/serialization @metabase/core-workflows
|
||||
# enterprise/backend/src/metabase_enterprise/serialization @metabase/core-ux-east
|
||||
# enterprise/backend/test/metabase_enterprise/serialization @metabase/core-ux-east
|
||||
|
||||
# enterprise/backend/src/metabase_enterprise/snippet_collections @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/snippet_collections @metabase/core-backend-admin-webapp
|
||||
@@ -95,8 +97,8 @@ test/metabase/driver/sql_jdbc/actions_test.clj @metabase/core-workflows
|
||||
# enterprise/backend/src/metabase_enterprise/upload_management @metabase/core-backend-admin-webapp
|
||||
# enterprise/backend/test/metabase_enterprise/upload_management @metabase/core-backend-admin-webapp
|
||||
|
||||
src/metabase/actions @metabase/core-backend-admin-webapp
|
||||
test/metabase/actions @metabase/core-backend-admin-webapp
|
||||
src/metabase/actions @metabase/core-ux-east
|
||||
test/metabase/actions @metabase/core-ux-east
|
||||
|
||||
# src/metabase/activity_feed @metabase/core-backend-admin-webapp
|
||||
# test/metabase/activity_feed @metabase/core-backend-admin-webapp
|
||||
@@ -122,11 +124,11 @@ test/metabase/actions @metabase/core-backend-admin-webapp
|
||||
# src/metabase/cmd @metabase/devexp
|
||||
# test/metabase/cmd @metabase/devexp
|
||||
|
||||
# src/metabase/channel @metabase/core-workflows
|
||||
# test/metabase/channel @metabase/core-workflows
|
||||
# src/metabase/channel @metabase/core-ux-east
|
||||
# test/metabase/channel @metabase/core-ux-east
|
||||
|
||||
# src/metabase/cloud_migration @metabase/core-workflows
|
||||
# test/metabase/cloud_migration @metabase/core-workflows
|
||||
# src/metabase/cloud_migration ...
|
||||
# test/metabase/cloud_migration ...
|
||||
|
||||
# src/metabase/cmd @metabase/devexp
|
||||
# test/metabase/cmd @metabase/devexp
|
||||
@@ -158,8 +160,8 @@ test/metabase/actions @metabase/core-backend-admin-webapp
|
||||
# src/metabase/indexed_entities @metabase/core-backend-querying
|
||||
# test/metabase/indexed_entities @metabase/core-backend-querying
|
||||
|
||||
# src/metabase/integrations @metabase/core-workflows
|
||||
# test/metabase/integrations @metabase/core-workflows
|
||||
# src/metabase/integrations ...
|
||||
# test/metabase/integrations ...
|
||||
|
||||
# src/metabase/legacy_mbql @metabase/core-backend-querying
|
||||
# test/metabase/legacy_mbql @metabase/core-backend-querying
|
||||
@@ -182,8 +184,8 @@ test/metabase/actions @metabase/core-backend-admin-webapp
|
||||
# src/metabase/moderation @metabase/core-backend-admin-webapp
|
||||
# test/metabase/moderation @metabase/core-backend-admin-webapp
|
||||
|
||||
# src/metabase/notification @metabase/core-workflows
|
||||
# test/metabase/notification @metabase/core-workflows
|
||||
# src/metabase/notification @metabase/core-ux-east
|
||||
# test/metabase/notification @metabase/core-ux-east
|
||||
|
||||
# src/metabase/permissions @metabase/core-backend-admin-webapp
|
||||
# test/metabase/permissions @metabase/core-backend-admin-webapp
|
||||
@@ -200,8 +202,8 @@ test/metabase/actions @metabase/core-backend-admin-webapp
|
||||
# src/metabase/public_sharing @metabase/core-backend-admin-webapp
|
||||
# test/metabase/public_sharing @metabase/core-backend-admin-webapp
|
||||
|
||||
# src/metabase/pulse @metabase/core-workflows
|
||||
# test/metabase/pulse @metabase/core-workflows
|
||||
# src/metabase/pulse @metabase/core-ux-east
|
||||
# test/metabase/pulse @metabase/core-ux-east
|
||||
|
||||
# src/metabase/query_analysis @metabase/core-backend-querying
|
||||
# test/metabase/query_analysis @metabase/core-backend-querying
|
||||
@@ -218,8 +220,8 @@ test/metabase/actions @metabase/core-backend-admin-webapp
|
||||
# src/metabase/sample_data @metabase/core-backend-admin-webapp
|
||||
# test/metabase/sample_data @metabase/core-backend-admin-webapp
|
||||
|
||||
# src/metabase/search @metabase/core-workflows
|
||||
# test/metabase/search @metabase/core-workflows
|
||||
# src/metabase/search ...
|
||||
# test/metabase/search ...
|
||||
|
||||
# src/metabase/segments @metabase/core-backend-querying
|
||||
# test/metabase/segments @metabase/core-backend-querying
|
||||
|
||||
14
.github/actions/await-port/action.yml
vendored
@@ -11,6 +11,18 @@ runs:
|
||||
- name: Wait for port ${{ inputs.port }} to be ready
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Waiting for port ${{ inputs.port }} to be ready..."
|
||||
timeout=300 # 5 minutes timeout
|
||||
elapsed=0
|
||||
while ! nc -z localhost ${{ inputs.port }}; do
|
||||
sleep 0.1;
|
||||
if [ $elapsed -ge $timeout ]; then
|
||||
echo "❌ Timeout waiting for port ${{ inputs.port }} after ${timeout} seconds"
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
elapsed=$((elapsed + 1))
|
||||
if [ $((elapsed % 10)) -eq 0 ]; then
|
||||
echo " Still waiting for port ${{ inputs.port }}... ($elapsed seconds)"
|
||||
fi
|
||||
done
|
||||
echo "✅ Port ${{ inputs.port }} is ready!"
|
||||
|
||||
68
.github/actions/fetch-artifact/action.yml
vendored
@@ -5,6 +5,14 @@ inputs:
|
||||
name:
|
||||
description: The name of the artifact to fetch
|
||||
required: true
|
||||
output-name:
|
||||
description: Optional custom name for the output jar file (defaults to metabase.jar)
|
||||
required: false
|
||||
default: "metabase.jar"
|
||||
extract-path:
|
||||
description: Directory path where the jar should be extracted (defaults to current directory)
|
||||
required: false
|
||||
default: "."
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
@@ -25,7 +33,7 @@ runs:
|
||||
});
|
||||
|
||||
if (!artifacts.data?.artifacts?.[0]?.id) {
|
||||
throw new Error(`No artifacts found for ${{ inputs.commit }}`);
|
||||
throw new Error(`No artifacts found for ${{ inputs.name }}`);
|
||||
}
|
||||
|
||||
const artifact_id = artifacts.data.artifacts[0].id;
|
||||
@@ -39,25 +47,59 @@ runs:
|
||||
|
||||
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/mb.zip`, Buffer.from(download.data));
|
||||
|
||||
- name: unzip uberjar artifact
|
||||
shell: bash
|
||||
run: unzip mb.zip
|
||||
- name: Move the Uberjar
|
||||
- name: Extract and rename JAR
|
||||
shell: bash
|
||||
run: | # bash
|
||||
if [ -e "metabase.jar" ]; then
|
||||
echo "metabase.jar is already in the right place"
|
||||
elif [ -e "target/uberjar/metabase.jar" ]; then
|
||||
echo "moving metabase.jar to current directory"
|
||||
mv target/uberjar/metabase.jar metabase.jar
|
||||
OUTPUT_NAME="${{ inputs.output-name }}"
|
||||
EXTRACT_PATH="${{ inputs.extract-path }}"
|
||||
|
||||
# Create a temporary directory for extraction to avoid conflicts
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
|
||||
# Extract to temporary directory
|
||||
unzip mb.zip -d "$TEMP_DIR"
|
||||
|
||||
# Create target directory
|
||||
mkdir -p "$EXTRACT_PATH"
|
||||
|
||||
# Find the jar and move all files from its directory
|
||||
if [ -e "$TEMP_DIR/metabase.jar" ]; then
|
||||
# Move all files to extract path
|
||||
mv "$TEMP_DIR"/* "$EXTRACT_PATH/" 2>/dev/null || true
|
||||
# Rename the jar to custom name if different
|
||||
if [ "$OUTPUT_NAME" != "metabase.jar" ]; then
|
||||
mv "$EXTRACT_PATH/metabase.jar" "$EXTRACT_PATH/$OUTPUT_NAME"
|
||||
fi
|
||||
elif [ -e "$TEMP_DIR/target/uberjar/metabase.jar" ]; then
|
||||
# Move all files from uberjar directory to extract path
|
||||
mv "$TEMP_DIR/target/uberjar"/* "$EXTRACT_PATH/" 2>/dev/null || true
|
||||
# Rename the jar to custom name if different
|
||||
if [ "$OUTPUT_NAME" != "metabase.jar" ]; then
|
||||
mv "$EXTRACT_PATH/metabase.jar" "$EXTRACT_PATH/$OUTPUT_NAME"
|
||||
fi
|
||||
else
|
||||
echo "Could not find the metabase.jar file"
|
||||
echo "Could not find metabase.jar in extracted files"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up temporary directory
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
# Set the JAR_PATH environment variable
|
||||
if [ "$EXTRACT_PATH" == "." ]; then
|
||||
echo "JAR_PATH=$OUTPUT_NAME" >> $GITHUB_ENV
|
||||
else
|
||||
echo "JAR_PATH=$EXTRACT_PATH/$OUTPUT_NAME" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Verify that this is a valid JAR file
|
||||
shell: bash
|
||||
run: file --mime-type ./metabase.jar
|
||||
run: |
|
||||
echo "Verifying JAR at: $JAR_PATH"
|
||||
file --mime-type "$JAR_PATH"
|
||||
|
||||
- name: Reveal its version.properties
|
||||
shell: bash
|
||||
run: jar xf metabase.jar version.properties && cat version.properties
|
||||
run: |
|
||||
echo "Extracting version.properties from: $JAR_PATH"
|
||||
jar xf "$JAR_PATH" version.properties && cat version.properties
|
||||
|
||||
74
.github/actions/get-docker-info/action.yml
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
name: Get Docker Info
|
||||
description: Determines Docker repository and tag based on branch and edition
|
||||
|
||||
inputs:
|
||||
branch:
|
||||
description: Branch name (defaults to current branch)
|
||||
required: false
|
||||
default: ${{ github.head_ref || github.ref_name }}
|
||||
edition:
|
||||
description: Edition (ee or oss)
|
||||
required: false
|
||||
default: ee
|
||||
owner:
|
||||
description: Repository owner (defaults to current repo owner)
|
||||
required: false
|
||||
default: ${{ github.repository_owner }}
|
||||
|
||||
outputs:
|
||||
repo:
|
||||
description: Docker repository name
|
||||
value: ${{ steps.docker-info.outputs.repo }}
|
||||
tag:
|
||||
description: Docker tag
|
||||
value: ${{ steps.docker-info.outputs.tag }}
|
||||
full_image:
|
||||
description: Full Docker image name (repo:tag)
|
||||
value: ${{ steps.docker-info.outputs.full_image }}
|
||||
editions:
|
||||
description: JSON array of editions to build
|
||||
value: ${{ steps.docker-info.outputs.editions }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Determine Docker info
|
||||
id: docker-info
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const branch = '${{ inputs.branch }}';
|
||||
const edition = '${{ inputs.edition }}';
|
||||
const owner = '${{ inputs.owner }}';
|
||||
|
||||
console.log(`Determining Docker info for branch: ${branch}, edition: ${edition}`);
|
||||
|
||||
let repo, tag, editions;
|
||||
|
||||
if (branch === 'master') {
|
||||
// Master builds both editions with specific repos
|
||||
editions = ['ee', 'oss'];
|
||||
tag = 'latest';
|
||||
|
||||
if (edition === 'ee') {
|
||||
repo = `${owner}/metabase-enterprise-head`;
|
||||
} else {
|
||||
repo = `${owner}/metabase-head`;
|
||||
}
|
||||
} else {
|
||||
// All other branches only build EE to metabase-dev
|
||||
editions = ['ee'];
|
||||
tag = branch.replaceAll('/', '-'); // slashes make docker sad
|
||||
repo = `${owner}/metabase-dev`;
|
||||
}
|
||||
|
||||
const fullImage = `${repo}:${tag}`;
|
||||
|
||||
// Set outputs
|
||||
core.setOutput('repo', repo);
|
||||
core.setOutput('tag', tag);
|
||||
core.setOutput('full_image', fullImage);
|
||||
core.setOutput('editions', JSON.stringify(editions));
|
||||
|
||||
console.log(`Docker image: ${fullImage}`);
|
||||
console.log(`Editions: ${JSON.stringify(editions)}`);
|
||||
8
.github/actions/prepare-backend/action.yml
vendored
@@ -1,4 +1,7 @@
|
||||
name: Prepare back-end environment
|
||||
description: |
|
||||
Prepare the backend. Installs jdk, Clojure, and fetches the cache for m2. The CI config fetchs `ci-test-config.json`
|
||||
from master and lets us ignore tests at the var level if they are flaking.
|
||||
inputs:
|
||||
java-version:
|
||||
required: true
|
||||
@@ -21,9 +24,14 @@ runs:
|
||||
distribution: 'temurin'
|
||||
- name: Install Clojure CLI
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
run: |
|
||||
curl -O https://download.clojure.org/install/linux-install-${{ inputs.clojure-version }}.sh &&
|
||||
sudo bash ./linux-install-${{ inputs.clojure-version }}.sh
|
||||
- name: Fetch CI config
|
||||
shell: bash
|
||||
run: |
|
||||
curl -o ci-test-config.json https://raw.githubusercontent.com/metabase/metabase/refs/heads/master/ci-test-config.json
|
||||
- name: Check to see if dependencies should be cached
|
||||
if: ${{ contains(github.event.head_commit.message, '[ci nocache]') }}
|
||||
run: echo "Commit message includes [ci nocache]; dependencies will NOT be cached"
|
||||
|
||||
2
.github/actions/test-driver/action.yml
vendored
@@ -40,7 +40,7 @@ runs:
|
||||
list-tests: failed
|
||||
fail-on-error: false
|
||||
- name: Upload Logs on Failure
|
||||
if: failure()
|
||||
if: always() && !success()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-${{ github.job }}
|
||||
|
||||
10
.github/file-paths.yaml
vendored
@@ -30,6 +30,7 @@ frontend_configs: &frontend_configs
|
||||
- "postcss.config.js"
|
||||
- "rspack.config.js"
|
||||
- "rspack.main.config.js"
|
||||
- "rspack.embedding-sdk-package.config.js"
|
||||
- "rspack.embedding-sdk-bundle.config.js"
|
||||
- "rspack.static-viz.config.js"
|
||||
- ".nvmrc"
|
||||
@@ -137,16 +138,17 @@ e2e_embedding_sdk_compatibility:
|
||||
- "e2e/runner/embedding-sdk/**"
|
||||
- "e2e/test-host-app/**/*.cy.*.{js,ts}"
|
||||
|
||||
snowplow: &snowplow
|
||||
- ".github/workflows/snowplow.yml"
|
||||
- "snowplow/**"
|
||||
|
||||
e2e_all:
|
||||
- *default
|
||||
- *e2e_ci
|
||||
- *sources
|
||||
- *e2e_specs
|
||||
- "e2e/**"
|
||||
|
||||
snowplow:
|
||||
- ".github/workflows/snowplow.yml"
|
||||
- "snowplow/**"
|
||||
- *snowplow
|
||||
|
||||
documentation:
|
||||
- "docs/**"
|
||||
|
||||
84
.github/scripts/get-issue-data.js
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
const githubSlackMap = require("../../release/github-slack-map.json");
|
||||
|
||||
async function getIssueData({ context, github, manualIssueNumber }) {
|
||||
let issueNumber;
|
||||
let issueData;
|
||||
let prReviews = [];
|
||||
const triggerType = context.eventName;
|
||||
|
||||
if (context.eventName === "issues") {
|
||||
issueNumber = context.payload.issue.number;
|
||||
issueData = context.payload.issue;
|
||||
} else if (context.eventName === "workflow_dispatch") {
|
||||
issueNumber = parseInt(manualIssueNumber);
|
||||
const { data } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
issueData = data;
|
||||
} else if (context.eventName === "pull_request_review") {
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
const { data: prData } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
});
|
||||
|
||||
// Extract issue number from branch name (e.g., "claude-fix/issue-12345-some-title")
|
||||
const branchMatch = prData.head.ref.match(/claude-fix\/issue-(\d+)/);
|
||||
if (!branchMatch) {
|
||||
throw new Error(
|
||||
`Could not extract issue number from branch name: ${prData.head.ref}`,
|
||||
);
|
||||
}
|
||||
|
||||
issueNumber = parseInt(branchMatch[1]);
|
||||
|
||||
const { data } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
issueData = data;
|
||||
|
||||
const { data: reviews } = await github.rest.pulls.listReviews({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
});
|
||||
|
||||
prReviews = reviews.filter(
|
||||
(review) =>
|
||||
review.state === "CHANGES_REQUESTED" &&
|
||||
isMetabaseMember(review.user.login),
|
||||
);
|
||||
}
|
||||
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
|
||||
const employeeComments = comments.filter((comment) =>
|
||||
isMetabaseMember(comment.user.login),
|
||||
);
|
||||
|
||||
return {
|
||||
issueNumber,
|
||||
issueData,
|
||||
employeeComments,
|
||||
prReviews,
|
||||
triggerType,
|
||||
isIssueAuthorEmployee: isMetabaseMember(issueData.user.login),
|
||||
};
|
||||
}
|
||||
|
||||
function isMetabaseMember(username) {
|
||||
return username in githubSlackMap;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getIssueData,
|
||||
};
|
||||
30
.github/team.json
vendored
@@ -50,14 +50,7 @@
|
||||
"name": "Admin Webapp",
|
||||
"label": ".Team/AdminWebapp",
|
||||
"members": [
|
||||
"npfitz",
|
||||
"johnswanson",
|
||||
"iethree",
|
||||
"nvoxland",
|
||||
"edpaget",
|
||||
"deniskaber",
|
||||
"alxnddr",
|
||||
"bpander"
|
||||
"eliotmetabase"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -86,7 +79,11 @@
|
||||
{
|
||||
"name": "Product Growth",
|
||||
"label": ".Team/ProductGrowth",
|
||||
"members": ["nemanjaglumac", "chodorowicz"]
|
||||
"members": [
|
||||
"nemanjaglumac",
|
||||
"chodorowicz",
|
||||
"andsalves"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Cloud",
|
||||
@@ -101,6 +98,21 @@
|
||||
"members": [
|
||||
"eliotmetabase"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UX West",
|
||||
"label": ".Team/UXWest",
|
||||
"members": [
|
||||
"eliotmetabase",
|
||||
"npfitz",
|
||||
"johnswanson",
|
||||
"iethree",
|
||||
"nvoxland",
|
||||
"edpaget",
|
||||
"deniskaber",
|
||||
"alxnddr",
|
||||
"bpander"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
3
.github/workflows/backend.yml
vendored
@@ -154,7 +154,7 @@ jobs:
|
||||
fail-on-error: false
|
||||
|
||||
- name: Upload Logs on Failure
|
||||
if: failure()
|
||||
if: always() && !success()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-${{ matrix.java-version }}-${{ matrix.job.edition }}-${{ github.job }}
|
||||
@@ -195,6 +195,7 @@ jobs:
|
||||
- name: Run cljfmt
|
||||
run: ./bin/mage cljfmt-all --force-check
|
||||
|
||||
|
||||
be-tests-result:
|
||||
needs:
|
||||
- be-linter-eastwood
|
||||
|
||||
14
.github/workflows/block-master-source-branch-prs.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: Block Master Branch PRs
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
check-source-branch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Block master branch PRs
|
||||
if: github.head_ref == 'master'
|
||||
run: |
|
||||
echo "PRs from `master` branches are not allowed, please use a new branch name for your PR."
|
||||
exit 1
|
||||
327
.github/workflows/claude-code-bug-fix.yml
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
name: "Claude Code Bug Fix"
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- labeled
|
||||
pull_request_review:
|
||||
types:
|
||||
- submitted
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
issue_number:
|
||||
description: "Issue number to fix"
|
||||
required: true
|
||||
type: string
|
||||
override_employee_check:
|
||||
description: "Override employee check for issue creator"
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
auto-fix-bug:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
id-token: write
|
||||
if: |
|
||||
(github.event_name == 'issues' && github.event.label.name == 'Claude Bug Fix' && github.event.issue.state == 'open') ||
|
||||
(github.event_name == 'workflow_dispatch') ||
|
||||
(github.event_name == 'pull_request_review' && github.event.review.state == 'changes_requested' && startsWith(github.event.pull_request.head.ref, 'claude-fix/'))
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get issue data and check employee status
|
||||
id: get_issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { getIssueData } = require('${{ github.workspace }}/.github/scripts/get-issue-data.js');
|
||||
|
||||
try {
|
||||
const result = await getIssueData({
|
||||
context,
|
||||
github,
|
||||
manualIssueNumber: '${{ github.event.inputs.issue_number }}'
|
||||
});
|
||||
|
||||
const { issueNumber, issueData, employeeComments, prReviews, triggerType, isIssueAuthorEmployee } = result;
|
||||
|
||||
// Check employee status and fail if not authorized
|
||||
if (!result.isIssueAuthorEmployee && '${{ github.event.inputs.override_employee_check }}' !== 'true') {
|
||||
core.setFailed(`User ${result.issueData.user.login} is not a Metabase employee. Skipping bug fix automation.`);
|
||||
}
|
||||
|
||||
core.setOutput('issue_number', issueNumber);
|
||||
core.setOutput('issue_data', JSON.stringify(issueData));
|
||||
core.setOutput('issue_comments', JSON.stringify(employeeComments));
|
||||
core.setOutput('pr_reviews', JSON.stringify(prReviews));
|
||||
core.setOutput('trigger_type', triggerType);
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
|
||||
- name: Set up git configuration
|
||||
run: |
|
||||
git config --global user.name "Claude Code[bot]"
|
||||
git config --global user.email "noreply@anthropic.com"
|
||||
|
||||
- name: Prepare issue context and bug fix prompt
|
||||
id: prepare_prompt
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
ISSUE_DATA: ${{ steps.get_issue.outputs.issue_data }}
|
||||
ISSUE_COMMENTS: ${{ steps.get_issue.outputs.issue_comments }}
|
||||
PR_REVIEWS: ${{ steps.get_issue.outputs.pr_reviews }}
|
||||
TRIGGER_TYPE: ${{ steps.get_issue.outputs.trigger_type }}
|
||||
with:
|
||||
script: |
|
||||
const issueData = JSON.parse(process.env.ISSUE_DATA);
|
||||
const issueComments = JSON.parse(process.env.ISSUE_COMMENTS);
|
||||
const prReviews = JSON.parse(process.env.PR_REVIEWS);
|
||||
const triggerType = process.env.TRIGGER_TYPE;
|
||||
const issueNumber = '${{ steps.get_issue.outputs.issue_number }}';
|
||||
|
||||
// Convert issue title to kebab case and create branch name
|
||||
const issueTitle = issueData.title || 'untitled';
|
||||
const kebabTitle = issueTitle
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-+|-+$/g, '')
|
||||
.replace(/-+/g, '-')
|
||||
.substring(0, 50);
|
||||
const branchName = `claude-fix/issue-${issueNumber}-${kebabTitle}`;
|
||||
|
||||
// Format data for bash environment
|
||||
const formattedComments = issueComments.length > 0
|
||||
? issueComments.map(comment =>
|
||||
`**Comment by @${comment.user.login} on ${comment.created_at}:**\n${comment.body}`
|
||||
).join('\n\n---\n\n')
|
||||
: '';
|
||||
const formattedReviews = prReviews.length > 0
|
||||
? prReviews.map(review =>
|
||||
`**Review by @${review.user.login} on ${review.submitted_at} (Changes Requested):**\n${review.body || 'No review comment provided'}`
|
||||
).join('\n\n---\n\n')
|
||||
: '';
|
||||
|
||||
core.exportVariable('BRANCH_NAME', branchName);
|
||||
core.exportVariable('ISSUE_NUMBER', issueNumber);
|
||||
core.exportVariable('ISSUE_TITLE', issueData.title);
|
||||
core.exportVariable('ISSUE_AUTHOR', issueData.user.login);
|
||||
core.exportVariable('ISSUE_CREATED', issueData.created_at);
|
||||
core.exportVariable('ISSUE_BODY', issueData.body || 'No description provided');
|
||||
core.exportVariable('ISSUE_COMMENTS_FORMATTED', formattedComments);
|
||||
core.exportVariable('PR_REVIEWS_FORMATTED', formattedReviews);
|
||||
core.exportVariable('TRIGGER_TYPE', triggerType);
|
||||
|
||||
- name: Generate bug fix prompt
|
||||
run: |
|
||||
cat << 'EOF' >> $GITHUB_ENV
|
||||
BUG_FIX_PROMPT<<PROMPT_END
|
||||
You are helping to fix a bug reported in GitHub issue #${{ env.ISSUE_NUMBER }}.
|
||||
|
||||
## Bug Report Details
|
||||
**Title:** ${{ env.ISSUE_TITLE }}
|
||||
**Reporter:** ${{ env.ISSUE_AUTHOR }}
|
||||
**Created:** ${{ env.ISSUE_CREATED }}
|
||||
|
||||
**Description:**
|
||||
${{ env.ISSUE_BODY }}
|
||||
|
||||
**Comments:**
|
||||
${{ env.ISSUE_COMMENTS_FORMATTED }}
|
||||
EOF
|
||||
|
||||
# Add review feedback section only if this is a review trigger
|
||||
if [ "${{ env.TRIGGER_TYPE }}" = "pull_request_review" ]; then
|
||||
cat << 'EOF' >> $GITHUB_ENV
|
||||
|
||||
## Previous Fix Attempt - Review Feedback (MUST ADDRESS)
|
||||
Your previous automated fix attempt received the following feedback that needs to be addressed:
|
||||
|
||||
${{ env.PR_REVIEWS_FORMATTED }}
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Add the rest of the prompt (always the same)
|
||||
cat << 'EOF' >> $GITHUB_ENV
|
||||
|
||||
## Instructions
|
||||
1. **Analyze the issue description and comments** - Understand what the issue is describing
|
||||
a. Pay particular attention to reproduction steps and if there's an agreed upon fix.
|
||||
2. **Search the codebase** - Use Grep and Glob tools to find relevant files
|
||||
3. **Implement a fix** - Follow existing code patterns and conventions
|
||||
4. **Test the fix** - Run appropriate tests using the commands in CLAUDE.md:
|
||||
- JavaScript/TypeScript: `yarn test-unit path/to/file.unit.spec.js`
|
||||
- Clojure: `clojure -X:dev:test :only namespace/test-name`
|
||||
- Lint: `yarn lint-eslint-pure` for JS/TS, `./bin/mage kondo <file>` for Clojure
|
||||
5. **Verify the fix** - Ensure tests pass and code follows conventions
|
||||
|
||||
## Important Guidelines
|
||||
- Follow the development patterns in CLAUDE.md
|
||||
- Write failing tests first, then fix them
|
||||
- Work in small, testable increments
|
||||
- Don't commit changes - leave that for the workflow
|
||||
- IMPORTANT: Focus only on fixing the reported bug, don't make unrelated changes
|
||||
|
||||
## Scratchpad Directory
|
||||
A `.claude-scratchpad/` directory has been created for your temporary files:
|
||||
- Use this directory for ALL temporary verification files. However, prefer using production test files rather than adhoc ones.
|
||||
- Only modify actual production code in the main repository directories
|
||||
- The scratchpad will be cleaned up automatically - nothing from it will be committed
|
||||
|
||||
Start by understanding the bug and then systematically work toward a solution.
|
||||
PROMPT_END
|
||||
EOF
|
||||
|
||||
- name: Determine branch strategy
|
||||
run: |
|
||||
BRANCH_NAME="${{ env.BRANCH_NAME }}"
|
||||
if git branch -r --list "origin/${BRANCH_NAME}" | grep -q .; then
|
||||
echo "Branch already exists: $BRANCH_NAME"
|
||||
echo "Will push to existing branch and skip PR creation"
|
||||
echo "BRANCH_EXISTS=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Creating new branch: $BRANCH_NAME"
|
||||
echo "Will create new PR"
|
||||
echo "BRANCH_EXISTS=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
# Export the branch name
|
||||
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
|
||||
|
||||
- name: Create scratchpad directory for Claude
|
||||
run: |
|
||||
# Create a scratchpad directory for Claude to use for temporary files
|
||||
mkdir -p .claude-scratchpad
|
||||
echo "Scratchpad directory created for Claude's temporary verification files"
|
||||
|
||||
- name: Generate GitHub App Token for Claude
|
||||
uses: actions/create-github-app-token@v1
|
||||
id: claude-app-token
|
||||
with:
|
||||
app-id: ${{ secrets.METABASE_BOT_APP_ID }}
|
||||
private-key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Generate Bug Fix with Claude Code
|
||||
uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
mode: agent
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
github_token: ${{ steps.claude-app-token.outputs.token }}
|
||||
direct_prompt: ${{ env.BUG_FIX_PROMPT }}
|
||||
timeout_minutes: "25"
|
||||
allowed_tools: "Bash(yarn test-unit*),Bash(yarn lint-eslint-pure),Bash(./bin/mage*),Bash(clojure*),Bash(find*),Bash(ls*),Bash(grep*),Write,Read,Glob,Grep,Edit,MultiEdit"
|
||||
disallowed_tools: "Bash(git commit*),Bash(git push*),Bash(gh*)"
|
||||
|
||||
- name: Clean up scratchpad directory
|
||||
run: |
|
||||
# Remove the scratchpad directory so its contents don't get committed
|
||||
rm -rf .claude-scratchpad/
|
||||
# Remove output file generated by Claude Code action
|
||||
rm -f output.txt
|
||||
echo "Scratchpad directory and action output files cleaned up"
|
||||
|
||||
- name: Check for changes and analysis
|
||||
id: check_changes
|
||||
run: |
|
||||
# Now check for actual code changes (excluding analysis file)
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
echo "Changes detected:"
|
||||
git status --short
|
||||
else
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
echo "No changes made by Claude."
|
||||
fi
|
||||
|
||||
- name: Get issue team labels and prepare reviewers
|
||||
if: steps.check_changes.outputs.has_changes == 'true'
|
||||
id: prepare_reviewers
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
ISSUE_DATA: ${{ steps.get_issue.outputs.issue_data }}
|
||||
with:
|
||||
script: |
|
||||
const issueData = JSON.parse(process.env.ISSUE_DATA);
|
||||
const issueLabels = issueData.labels.map(label => label.name);
|
||||
const teamLabels = issueLabels.filter(label => label.startsWith('.Team/'));
|
||||
const issueCreator = issueData.user.login;
|
||||
core.setOutput('team_labels', teamLabels.join(','));
|
||||
core.setOutput('reviewers', issueCreator);
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.check_changes.outputs.has_changes == 'true'
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: ${{ env.BRANCH_NAME }}
|
||||
base: master
|
||||
commit-message: |
|
||||
Fix: ${{ env.ISSUE_TITLE }}
|
||||
|
||||
Fixes #${{ env.ISSUE_NUMBER }}
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
committer: "Claude Code[bot] <noreply@anthropic.com>"
|
||||
author: "Claude Code[bot] <noreply@anthropic.com>"
|
||||
title: "Fix: ${{ env.ISSUE_TITLE }}"
|
||||
body: |
|
||||
This PR automatically fixes the bug reported in #${{ env.ISSUE_NUMBER }}.
|
||||
|
||||
## Bug Report
|
||||
**Original Issue:** #${{ env.ISSUE_NUMBER }}
|
||||
**Reporter:** @${{ env.ISSUE_AUTHOR }}
|
||||
**Issue Title:** ${{ env.ISSUE_TITLE }}
|
||||
|
||||
## Automated Fix
|
||||
🤖 This fix was generated automatically by Claude Code based on the issue description.
|
||||
|
||||
**Please review carefully:**
|
||||
- [ ] The fix addresses the reported issue
|
||||
- [ ] Tests pass and code follows conventions
|
||||
- [ ] No unrelated changes were introduced
|
||||
- [ ] The solution is appropriate and maintainable
|
||||
|
||||
## Next Steps
|
||||
- Review the changes and test thoroughly
|
||||
- If the fix looks good, approve and merge
|
||||
- If issues are found, either fix them or close this PR
|
||||
|
||||
---
|
||||
Closes #${{ env.ISSUE_NUMBER }}
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
labels: |
|
||||
${{ steps.prepare_reviewers.outputs.team_labels }}
|
||||
automated-fix
|
||||
ci skip
|
||||
reviewers: ${{ steps.prepare_reviewers.outputs.reviewers }}
|
||||
|
||||
- name: Log existing branch update
|
||||
if: steps.check_changes.outputs.has_changes == 'true' && env.BRANCH_EXISTS == 'true'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
console.log('🔄 Updated existing branch: ${{ env.BRANCH_NAME }}');
|
||||
console.log('The changes have been pushed to the existing PR for this issue.');
|
||||
|
||||
- name: Log analysis for no changes
|
||||
if: steps.check_changes.outputs.has_changes == 'false'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
console.log('🤖 No code changes were made by Claude.');
|
||||
126
.github/workflows/containerize-uberjar.yml
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
name: Containerize Uberjar
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
get-container-info:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
name: Get container info
|
||||
outputs:
|
||||
editions: ${{ steps.ee-info.outputs.editions }}
|
||||
ee: ${{ toJson(fromJson(steps.build-matrix.outputs.result).ee) }}
|
||||
oss: ${{ toJson(fromJson(steps.build-matrix.outputs.result).oss) }}
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
- name: Get EE Docker info
|
||||
id: ee-info
|
||||
uses: ./.github/actions/get-docker-info
|
||||
with:
|
||||
edition: ee
|
||||
- name: Get OSS Docker info
|
||||
id: oss-info
|
||||
uses: ./.github/actions/get-docker-info
|
||||
with:
|
||||
edition: oss
|
||||
- name: Build matrix info
|
||||
id: build-matrix
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const editions = JSON.parse('${{ steps.ee-info.outputs.editions }}');
|
||||
const result = {
|
||||
editions: editions,
|
||||
ee: {
|
||||
repo: '${{ steps.ee-info.outputs.repo }}',
|
||||
tag: '${{ steps.ee-info.outputs.tag }}'
|
||||
},
|
||||
oss: {
|
||||
repo: '${{ steps.oss-info.outputs.repo }}',
|
||||
tag: '${{ steps.oss-info.outputs.tag }}'
|
||||
}
|
||||
};
|
||||
console.log('Build matrix:', result);
|
||||
return result;
|
||||
|
||||
containerize:
|
||||
needs: [get-container-info]
|
||||
if: needs.get-container-info.result == 'success'
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
uses: ./.github/workflows/containerize-jar.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
artifact-name: metabase-${{ matrix.edition }}-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
commit: ${{ github.event.inputs.commit || github.sha }}
|
||||
repo: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).repo }}
|
||||
tag: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).tag }}
|
||||
release: "false"
|
||||
build-args: |
|
||||
GIT_COMMIT_SHA=${{ github.event.inputs.commit || github.sha }}
|
||||
|
||||
run-trivy:
|
||||
needs: [get-container-info, containerize]
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
runs-on: ubuntu-22.04
|
||||
name: Run Trivy vulnerability scanner
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.commit || github.sha }}
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@0.29.0
|
||||
env:
|
||||
TRIVY_OFFLINE_SCAN: true
|
||||
repo: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).repo }}
|
||||
tag: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).tag }}
|
||||
with:
|
||||
image-ref: docker.io/${{ env.repo }}:${{ env.tag }}
|
||||
format: sarif
|
||||
output: trivy-results.sarif
|
||||
version: "v0.57.1"
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: "trivy-results.sarif"
|
||||
|
||||
post-comment:
|
||||
needs: [get-container-info, containerize]
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-22.04
|
||||
name: Post PR comment
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
- name: Get Docker info for comment
|
||||
id: docker-info
|
||||
uses: ./.github/actions/get-docker-info
|
||||
with:
|
||||
branch: ${{ github.head_ref || github.ref_name }}
|
||||
edition: ee
|
||||
|
||||
- name: Post PR comment
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
header: docker-build-status
|
||||
message: |
|
||||
✅ Docker build completed for commit ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
The uberjar has been built and containerized successfully.
|
||||
|
||||
**Branch:** `${{ github.head_ref || github.ref_name }}`
|
||||
**Docker Image:** `${{ steps.docker-info.outputs.full_image }}`
|
||||
**Docker Hub:** [View on Docker Hub](https://hub.docker.com/r/${{ steps.docker-info.outputs.repo }}/tags?name=${{ steps.docker-info.outputs.tag }})
|
||||
**Triggered by:** @${{ github.actor }}
|
||||
|
||||
Pull the image:
|
||||
```bash
|
||||
docker pull ${{ steps.docker-info.outputs.full_image }}
|
||||
```
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- enterprise/frontend/src/embedding-sdk/**
|
||||
- enterprise/frontend/src/embedding-sdk-bundle/**
|
||||
|
||||
jobs:
|
||||
pr-title-reminder:
|
||||
|
||||
182
.github/workflows/docs-generate-base.yml
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
# .github/workflows/reusable-doc-update.yml
|
||||
name: Reusable - Update Documentation
|
||||
|
||||
# This workflow is designed to be called by other workflows.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
target_branch:
|
||||
description: "The branch to check out and create a PR against"
|
||||
required: true
|
||||
type: string
|
||||
m2_cache_key_suffix:
|
||||
description: "A unique suffix for the Maven cache key"
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
automation_token:
|
||||
description: "A token with permissions to create branches and PRs"
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-docs:
|
||||
name: Update documentation for ${{ inputs.target_branch }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.automation_token }}
|
||||
ref: ${{ inputs.target_branch }}
|
||||
|
||||
- name: Prepare backend environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: "auto-update-docs-${{ inputs.m2_cache_key_suffix }}"
|
||||
|
||||
- name: Generate environment variables documentation
|
||||
id: generate_env_docs
|
||||
run: |
|
||||
set -e # Exit on any error
|
||||
# Ensure we're on the target branch for documentation generation
|
||||
git checkout ${{ inputs.target_branch }}
|
||||
echo "Generating environment variables documentation from branch: ${{ inputs.target_branch }}"
|
||||
clojure -M:ee:doc environment-variables-documentation
|
||||
continue-on-error: false
|
||||
|
||||
- name: Generate config template documentation
|
||||
id: generate_config_docs
|
||||
run: |
|
||||
set -e # Exit on any error
|
||||
echo "Generating config template documentation..."
|
||||
clojure -M:ee:doc config-template
|
||||
continue-on-error: false
|
||||
|
||||
- name: Generate API documentation
|
||||
id: generate_api_docs
|
||||
run: |
|
||||
set -e # Exit on any error
|
||||
echo "Generating API documentation..."
|
||||
clojure -M:ee:doc api-documentation
|
||||
continue-on-error: false
|
||||
|
||||
- name: Check for changes
|
||||
id: check_changes
|
||||
run: |
|
||||
if git diff --quiet docs/; then
|
||||
echo "changes=false" >> $GITHUB_OUTPUT
|
||||
echo "No changes detected in docs directory"
|
||||
else
|
||||
echo "changes=true" >> $GITHUB_OUTPUT
|
||||
echo "Changes detected in docs directory"
|
||||
fi
|
||||
|
||||
- name: Create branch and commit changes
|
||||
id: commit_and_push
|
||||
if: steps.check_changes.outputs.changes == 'true'
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
|
||||
BRANCH_NAME="docs/auto-update-${{ inputs.target_branch }}-$(date +%Y-%m-%d-%H%M%S)"
|
||||
echo "Creating branch: $BRANCH_NAME"
|
||||
|
||||
# Create and switch to new branch from current target branch
|
||||
git checkout -b "$BRANCH_NAME"
|
||||
|
||||
# Stage and commit changes
|
||||
git add docs/
|
||||
if git diff --cached --quiet; then
|
||||
echo "No changes to commit"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git commit -m "Update generated docs (${{ inputs.target_branch }})" --no-verify
|
||||
git push -u origin "$BRANCH_NAME"
|
||||
|
||||
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
|
||||
echo "Successfully created and pushed branch"
|
||||
|
||||
- name: Create pull request
|
||||
id: create_pr
|
||||
if: steps.check_changes.outputs.changes == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.automation_token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
run: |
|
||||
CHANGES_SUMMARY=$(git diff --name-only HEAD~1 docs/ 2>/dev/null | head -10 | sed 's/^/- /' || echo "- No specific files detected")
|
||||
TOTAL_CHANGES=$(git diff --name-only HEAD~1 docs/ 2>/dev/null | wc -l || echo "0")
|
||||
BRANCH_NAME="${{ steps.commit_and_push.outputs.branch_name }}"
|
||||
|
||||
echo "Creating PR with branch: $BRANCH_NAME"
|
||||
echo "Changes detected: $TOTAL_CHANGES files"
|
||||
|
||||
for i in {1..3}; do
|
||||
echo "Attempt $i of 3..."
|
||||
if gh pr create \
|
||||
--base "${{ inputs.target_branch }}" \
|
||||
--head "$BRANCH_NAME" \
|
||||
--title "Auto-update documentation for ${{ inputs.target_branch }}" \
|
||||
--body "This PR contains automatically generated documentation updates.
|
||||
|
||||
## Changes detected
|
||||
The following documentation files were updated:
|
||||
$CHANGES_SUMMARY
|
||||
$([ "$TOTAL_CHANGES" -gt 10 ] && echo "- ... and $((TOTAL_CHANGES - 10)) more files")
|
||||
|
||||
## Generation commands
|
||||
Documentation was generated using:
|
||||
- \`clojure -M:ee:doc environment-variables-documentation\`
|
||||
- \`clojure -M:ee:doc config-template\`
|
||||
- \`clojure -M:ee:doc api-documentation\`
|
||||
|
||||
Please review the changes and merge if they look correct." \
|
||||
--label "Type:Documentation" \
|
||||
--label "no-backport" \
|
||||
--reviewer "metabase/tech-writers"; then
|
||||
echo "PR created successfully on attempt $i"
|
||||
break
|
||||
else
|
||||
echo "PR creation failed on attempt $i"
|
||||
if [ $i -eq 3 ]; then
|
||||
echo "All attempts failed. Exiting with error."
|
||||
exit 1
|
||||
fi
|
||||
echo "Waiting 10 seconds before retry..."
|
||||
sleep 10
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Skip PR creation
|
||||
if: steps.check_changes.outputs.changes == 'false'
|
||||
run: |
|
||||
echo "No documentation changes detected, skipping PR creation"
|
||||
|
||||
- name: Workflow summary
|
||||
if: always()
|
||||
run: |
|
||||
if [ "${{ steps.check_changes.outputs.changes }}" == "true" ]; then
|
||||
if [ "${{ steps.commit_and_push.outcome }}" == "success" ]; then
|
||||
if [ "${{ steps.create_pr.outcome }}" == "success" ]; then
|
||||
echo "## ✅ Documentation Updated Successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Branch: \`${{ steps.commit_and_push.outputs.branch_name }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- PR created targeting **${{ inputs.target_branch }}**" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "## ⚠️ Branch Created but PR Failed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Branch: \`${{ steps.commit_and_push.outputs.branch_name }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Manual PR creation required" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
else
|
||||
echo "## ❌ Failed to Create Branch" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Check workflow logs for details" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
else
|
||||
echo "## ℹ️ No Changes Detected" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Documentation is up to date on **${{ inputs.target_branch }}**" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
36
.github/workflows/docs-links.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Check doc links
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "docs/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
link-checker:
|
||||
name: Check documentation links
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
docs
|
||||
.lychee
|
||||
|
||||
- name: Cache lychee
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/lychee
|
||||
key: lychee-${{ runner.os }}-${{ hashFiles('.lychee/config.toml') }}
|
||||
|
||||
- name: Run link checker
|
||||
id: link-check
|
||||
uses: lycheeverse/lychee-action@v2
|
||||
with:
|
||||
fail: true
|
||||
args: docs --config ./.lychee/config.toml --offline
|
||||
format: markdown
|
||||
16
.github/workflows/docs-master-generate.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: Auto-update documentation (master)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 1 * * 1-5" # Every Monday through Friday at 1 AM UTC
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-master-docs:
|
||||
name: Call documentation update for master
|
||||
uses: ./.github/workflows/docs-generate-base.yml
|
||||
with:
|
||||
target_branch: "master"
|
||||
m2_cache_key_suffix: "master"
|
||||
secrets:
|
||||
automation_token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
16
.github/workflows/docs-release-generate.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: Auto-update documentation (release)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 2 * * 1-5" # Every Monday through Friday at 2 AM UTC
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-release-docs:
|
||||
name: Call documentation update for release branch
|
||||
uses: ./.github/workflows/docs-generate-base.yml
|
||||
with:
|
||||
target_branch: "release-x.56.x"
|
||||
m2_cache_key_suffix: "release"
|
||||
secrets:
|
||||
automation_token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
43
.github/workflows/drivers-stress-test.yml
vendored
@@ -689,24 +689,25 @@ jobs:
|
||||
junit-name: 'be-tests-starburst-ee'
|
||||
test-args: ":only ${{ inputs.test }} :times ${{ inputs.times }}"
|
||||
|
||||
be-tests-vertica-ee:
|
||||
if: inputs.driver == 'Vertica'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: vertica
|
||||
services:
|
||||
vertica:
|
||||
image: vertica/vertica-ce:12.0.2-0
|
||||
ports:
|
||||
- "5433:5433"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Make plugins directory
|
||||
run: mkdir plugins
|
||||
- name: Test Vertica driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-vertica-ee'
|
||||
test-args: ":only ${{ inputs.test }} :times ${{ inputs.times }}"
|
||||
# TODO(rileythomp, 2025-08-20): Re-enable vertica tests once the docker image is updated
|
||||
# be-tests-vertica-ee:
|
||||
# if: ${{ false && inputs.driver == 'Vertica' }}
|
||||
# runs-on: ubuntu-22.04
|
||||
# timeout-minutes: 90
|
||||
# env:
|
||||
# CI: 'true'
|
||||
# DRIVERS: vertica
|
||||
# services:
|
||||
# vertica:
|
||||
# image: vertica/vertica-ce:12.0.2-0
|
||||
# ports:
|
||||
# - "5433:5433"
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - name: Make plugins directory
|
||||
# run: mkdir plugins
|
||||
# - name: Test Vertica driver
|
||||
# uses: ./.github/actions/test-driver
|
||||
# with:
|
||||
# junit-name: 'be-tests-vertica-ee'
|
||||
# test-args: ":only ${{ inputs.test }} :times ${{ inputs.times }}"
|
||||
|
||||
177
.github/workflows/drivers.yml
vendored
@@ -44,11 +44,11 @@ jobs:
|
||||
echo "A relevant team label is present. Tier 3 driver tests will run."
|
||||
else
|
||||
echo "Checking for changes in relevant folders..."
|
||||
CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }})
|
||||
CHANGED_FILES=$(git diff --name-only $(git merge-base ${{ github.event.pull_request.base.sha }} ${{ github.sha }}) ${{ github.sha }})
|
||||
|
||||
# Initialize an empty array to store folders with changes
|
||||
CHANGED_FOLDERS=()
|
||||
for folder in "src/metabase/lib" "src/metabase/query_processor" "modules/drivers"; do
|
||||
for folder in "src/metabase/lib" "src/metabase/query_processor" "modules/drivers" "src/metabase/driver"; do
|
||||
if echo "$CHANGED_FILES" | grep -q "$folder"; then
|
||||
CHANGED_FOLDERS+=("$folder")
|
||||
fi
|
||||
@@ -73,9 +73,11 @@ jobs:
|
||||
CI: 'true'
|
||||
DRIVERS: athena
|
||||
MB_ATHENA_TEST_REGION: us-east-1
|
||||
MB_ATHENA_TEST_REGION_ROUTING: us-east-2
|
||||
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 }}
|
||||
MB_ATHENA_TEST_S3_STAGING_DIR_ROUTING: ${{ secrets.MB_ATHENA_TEST_S3_STAGING_DIR_ROUTING }}
|
||||
# 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 }}
|
||||
@@ -336,6 +338,12 @@ jobs:
|
||||
name: H2
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: Start python-runner
|
||||
working-directory: python-runner
|
||||
run: make run-all
|
||||
- name: Test H2 driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
@@ -440,6 +448,12 @@ jobs:
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: Start python-runner
|
||||
working-directory: python-runner
|
||||
run: make run-all
|
||||
- name: Test ${{ matrix.version.name }}
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
@@ -743,6 +757,12 @@ jobs:
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: Start python-runner
|
||||
working-directory: python-runner
|
||||
run: make run-all
|
||||
- name: Test ${{ matrix.version.name }} (${{ matrix.job.name }})
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
@@ -1038,79 +1058,81 @@ jobs:
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
be-tests-starburst-ee:
|
||||
needs: determine-driver-skips
|
||||
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: starburst
|
||||
services:
|
||||
starburst:
|
||||
image: trinodb/trino:latest
|
||||
env:
|
||||
CATALOG_MANAGEMENT: dynamic
|
||||
ports:
|
||||
- "8080:8080"
|
||||
name: Starburst
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Make plugins directory
|
||||
run: mkdir plugins
|
||||
- name: Test Starburst driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-starburst-ee'
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
# TODO(dpsutton, 2025-08-20): Re-enable starburst when we figure out why it randomly dies in CI
|
||||
# be-tests-starburst-ee:
|
||||
# needs: determine-driver-skips
|
||||
# if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
|
||||
# runs-on: ubuntu-22.04
|
||||
# timeout-minutes: 60
|
||||
# env:
|
||||
# CI: 'true'
|
||||
# DRIVERS: starburst
|
||||
# services:
|
||||
# starburst:
|
||||
# image: trinodb/trino:latest
|
||||
# env:
|
||||
# CATALOG_MANAGEMENT: dynamic
|
||||
# ports:
|
||||
# - "8080:8080"
|
||||
# name: Starburst
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - name: Make plugins directory
|
||||
# run: mkdir plugins
|
||||
# - name: Test Starburst driver
|
||||
# uses: ./.github/actions/test-driver
|
||||
# with:
|
||||
# junit-name: 'be-tests-starburst-ee'
|
||||
# test-args: >-
|
||||
# :only-tags [:mb/driver-tests]
|
||||
# - name: Upload Test Results
|
||||
# uses: ./.github/actions/upload-test-results
|
||||
# if: always()
|
||||
# with:
|
||||
# input-path: ./target/junit/
|
||||
# output-name: ${{ github.job }}
|
||||
# bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
# aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
# aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
# aws-region: ${{ vars.AWS_REGION }}
|
||||
# trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
be-tests-vertica-ee:
|
||||
needs: determine-driver-skips
|
||||
if: ${{ !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: vertica
|
||||
services:
|
||||
vertica:
|
||||
image: vertica/vertica-ce:12.0.2-0
|
||||
ports:
|
||||
- "5433:5433"
|
||||
name: Vertica
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Make plugins directory
|
||||
run: mkdir plugins
|
||||
- name: Test Vertica driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-vertica-ee'
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
# TODO(rileythomp, 2025-08-20): Re-enable vertica tests once the docker image is updated
|
||||
# be-tests-vertica-ee:
|
||||
# needs: determine-driver-skips
|
||||
# if: ${{ false && !inputs.skip && !(needs.determine-driver-skips.outputs.skip == 'true') }}
|
||||
# runs-on: ubuntu-22.04
|
||||
# timeout-minutes: 60
|
||||
# env:
|
||||
# CI: 'true'
|
||||
# DRIVERS: vertica
|
||||
# services:
|
||||
# vertica:
|
||||
# image: vertica/vertica-ce:12.0.2-0
|
||||
# ports:
|
||||
# - "5433:5433"
|
||||
# name: Vertica
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - name: Make plugins directory
|
||||
# run: mkdir plugins
|
||||
# - name: Test Vertica driver
|
||||
# uses: ./.github/actions/test-driver
|
||||
# with:
|
||||
# junit-name: 'be-tests-vertica-ee'
|
||||
# test-args: >-
|
||||
# :only-tags [:mb/driver-tests]
|
||||
# - name: Upload Test Results
|
||||
# uses: ./.github/actions/upload-test-results
|
||||
# if: always()
|
||||
# with:
|
||||
# input-path: ./target/junit/
|
||||
# output-name: ${{ github.job }}
|
||||
# bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
# aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
# aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
# aws-region: ${{ vars.AWS_REGION }}
|
||||
# trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
drivers-tests-result:
|
||||
needs:
|
||||
@@ -1133,8 +1155,9 @@ jobs:
|
||||
- be-tests-sparksql-ee
|
||||
- be-tests-sqlite-ee
|
||||
- be-tests-sqlserver
|
||||
- be-tests-starburst-ee
|
||||
- be-tests-vertica-ee
|
||||
# - be-tests-starburst-ee
|
||||
# TODO(rileythomp, 2025-08-20): Re-enable vertica tests once the docker image is updated
|
||||
# - be-tests-vertica-ee
|
||||
- be-tests-clickhouse-ee
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
@@ -1156,7 +1179,7 @@ jobs:
|
||||
}));
|
||||
|
||||
// are all jobs skipped or successful?
|
||||
if (jobs.every(job => (job.result === 'skipped' || job.result === 'success'))) {
|
||||
if (jobs.every(job => (job.result === 'skipped' || job.result === 'success' || job.name == 'be-tests-starburst-ee'))) {
|
||||
console.log("");
|
||||
console.log(" _------. ");
|
||||
console.log(" / , \_ ");
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
name: E2E Cross-version Component Tests for Embedding SDK
|
||||
# Thi workflow does the backward compatibility tests
|
||||
# between the Embedding SDK package of version N and Embedding SDK Bundle of version N - 1
|
||||
# N - 1 is a target of a PR
|
||||
name: Embedding SDK backward-compatibility E2E Component Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cached-embedding-sdk-dist-artifact-name:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: "SDK cross-version E2E > Check which files changed"
|
||||
name: "SDK backward-compatibility E2E > Check which files changed"
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
e2e_all: ${{ steps.changes.outputs.e2e_all }}
|
||||
e2e_embedding_sdk: ${{ steps.changes.outputs.e2e_embedding_sdk }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test which files changed
|
||||
@@ -19,11 +26,31 @@ jobs:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
decide-target-ref:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
target-ref: ${{ steps.get-target-ref.outputs.value }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Decide ref to checkout
|
||||
id: get-target-ref
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
echo "value=${{ github.base_ref }}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "value=$(git rev-parse HEAD^1)" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# if this is a test on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
name: "SDK cross-version E2E > [Backport only] Get build requirements"
|
||||
name: "SDK backward-compatibility E2E > [Backport only] Get build requirements"
|
||||
needs: [decide-target-ref]
|
||||
if: |
|
||||
!cancelled()
|
||||
!cancelled() &&
|
||||
contains(github.base_ref || github.ref, 'release-x')
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
@@ -32,6 +59,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.decide-target-ref.outputs.target-ref }}
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
@@ -54,76 +82,12 @@ jobs:
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
build:
|
||||
name: "SDK cross-version E2E > Build uberjar"
|
||||
needs: [files-changed, get-build-requirements]
|
||||
if: |
|
||||
!cancelled()
|
||||
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-cross-version
|
||||
|
||||
resolve-sdk-version:
|
||||
name: "SDK cross-version E2E > 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:
|
||||
name: "SDK cross-version E2E > Run e2e tests"
|
||||
needs: [get-build-requirements, build, resolve-sdk-version]
|
||||
name: "SDK backward-compatibility E2E > Run e2e tests"
|
||||
needs: [files-changed, decide-target-ref, get-build-requirements]
|
||||
if: |
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
!cancelled() &&
|
||||
needs.files-changed.outputs.e2e_embedding_sdk == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
@@ -142,45 +106,33 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# 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
|
||||
ref: ${{ needs.decide-target-ref.outputs.target-ref }}
|
||||
|
||||
- name: Move tests from the release commit into the repo
|
||||
run: |
|
||||
rm -rf ./e2e/support/*
|
||||
mv ./sdk-release-e2e/e2e/support/* ./e2e/support
|
||||
|
||||
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
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar-cross-version
|
||||
m2-cache-key: uberjar
|
||||
java-version: "${{ needs.get-build-requirements.outputs.java_version || 21 }}"
|
||||
|
||||
- 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"
|
||||
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
|
||||
|
||||
- name: Build uberjar with ./bin/build.sh
|
||||
run: ./bin/build.sh
|
||||
|
||||
- name: Retrieve Embedding SDK dist artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ inputs.cached-embedding-sdk-dist-artifact-name }}
|
||||
path: ${{ github.workspace }}/resources/embedding-sdk
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
|
||||
- name: 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 Metabase
|
||||
run: node e2e/runner/run_cypress_ci.js start
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
name: E2E cross-version for breaking changes
|
||||
|
||||
# See `bin/backward-compatibility-test.js` for the documentation of this workflow.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
fe-ref:
|
||||
description: "Frontend git ref to use"
|
||||
type: string
|
||||
required: true
|
||||
default: "master"
|
||||
be-ref:
|
||||
description: "Backend git ref to use"
|
||||
type: string
|
||||
required: true
|
||||
default: "master"
|
||||
total-shards:
|
||||
description: "Total number of parallel test shards"
|
||||
type: number
|
||||
required: false
|
||||
default: 4
|
||||
workflow_call:
|
||||
inputs:
|
||||
fe-ref:
|
||||
description: "Frontend git ref to use"
|
||||
type: string
|
||||
required: true
|
||||
be-ref:
|
||||
description: "Backend git ref to use"
|
||||
type: string
|
||||
required: true
|
||||
total-shards:
|
||||
description: "Total number of parallel test shards"
|
||||
type: number
|
||||
required: false
|
||||
default: 4
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
name: "Breaking changes E2E > Generate matrix"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix_json: ${{ steps.set_matrix.outputs.matrix_json }}
|
||||
shards_total: ${{ steps.set_matrix.outputs.shards_total }}
|
||||
steps:
|
||||
- name: Set up shard matrix
|
||||
id: set_matrix
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
# generate an output like `{"matrixJson": "{\"shard\": [1, 2, 3, 4]}", "shardsTotal": 4}` to be used in the other jobs
|
||||
script: |
|
||||
const totalShards = parseInt(process.env.TOTAL_SHARDS_INPUT, 10);
|
||||
|
||||
const matrix = { shard: Array.from({ length: totalShards }, (_, i) => i + 1) };
|
||||
|
||||
console.log("Generated matrix JSON", matrix);
|
||||
console.log(`Total shards: ${totalShards}`);
|
||||
|
||||
core.setOutput('matrix_json', JSON.stringify(matrix));
|
||||
core.setOutput('shards_total', totalShards);
|
||||
env:
|
||||
TOTAL_SHARDS_INPUT: ${{ inputs.total-shards }}
|
||||
|
||||
build-jar:
|
||||
name: "Breaking changes E2E > Build jar"
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Node.js
|
||||
# We're not using `actions/prepare-frontend` because we don't want to install deps from the root repo
|
||||
# nor we want to touch the cache as we'll be potentially be installing different versions of packages
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: cross-version-uberjar
|
||||
|
||||
- name: Build jar with different frontend and backend version
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
CYPRESS_CI: true
|
||||
run: |
|
||||
node bin/backward-compatibility-test.js \
|
||||
${{ inputs.fe-ref }} ${{ inputs.be-ref }} \
|
||||
build
|
||||
|
||||
- name: Upload Uberjar
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: metabase-jar-cross-version
|
||||
path: .tmp/metabase-be/target/uberjar/metabase.jar
|
||||
if-no-files-found: error
|
||||
|
||||
run-breaking-changes-tests:
|
||||
name: "Breaking changes E2E > Run breaking changes tests"
|
||||
needs: [build-jar, generate-matrix]
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
TOTAL_SHARDS: ${{ needs.generate-matrix.outputs.shards_total }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix_json) }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: cross-version-uberjar
|
||||
|
||||
- name: Download Uberjar
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-jar-cross-version
|
||||
path: .tmp/metabase-be/target/uberjar/
|
||||
|
||||
- name: Download FE repo
|
||||
run: |
|
||||
git clone --depth 1 -b ${{ inputs.fe-ref }} https://github.com/metabase/metabase.git .tmp/metabase-fe
|
||||
|
||||
- name: Install FE dependencies
|
||||
working-directory: .tmp/metabase-fe
|
||||
run: |
|
||||
yarn install
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
with:
|
||||
working-directory: .tmp/metabase-fe
|
||||
|
||||
- name: Run the tests
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
CYPRESS_MB_ALL_FEATURES_TOKEN: ${{ secrets.MB_ALL_FEATURES_TOKEN }}
|
||||
CYPRESS_MB_STARTER_CLOUD_TOKEN: ${{ secrets.MB_STARTER_CLOUD_TOKEN }}
|
||||
CYPRESS_MB_PRO_CLOUD_TOKEN: ${{ secrets.MB_PRO_CLOUD_TOKEN }}
|
||||
CYPRESS_MB_PRO_SELF_HOSTED_TOKEN: ${{ secrets.MB_PRO_SELF_HOSTED_TOKEN }}
|
||||
CYPRESS_CI: true
|
||||
run: |
|
||||
node bin/backward-compatibility-test.js \
|
||||
${{ inputs.fe-ref }} ${{ inputs.be-ref }} \
|
||||
start > /dev/null & \
|
||||
node bin/backward-compatibility-test.js \
|
||||
${{ inputs.fe-ref }} ${{ inputs.be-ref }} \
|
||||
test ${{ matrix.shard}}/${{ env.TOTAL_SHARDS }}
|
||||
@@ -178,12 +178,8 @@ jobs:
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
- name: Compile CLJS
|
||||
run: yarn build-pure:cljs
|
||||
shell: bash
|
||||
|
||||
- name: Build Embedding SDK package
|
||||
run: yarn build-embedding-sdk
|
||||
run: yarn build-embedding-sdk-package
|
||||
|
||||
- name: Prepare Embedding SDK artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -196,7 +192,7 @@ jobs:
|
||||
# - starts it
|
||||
# - runs its Cypress tests against the local metabase.jar and local @metabase/embedding-sdk-react package.
|
||||
# The job is not required, though if it's failing better to be sure that it's not caused by a breaking change.
|
||||
# For more details see `Sample Apps compatibility with Embedding SDK tests` in `enterprise/frontend/src/embedding-sdk/dev.md`
|
||||
# For more details see `Sample Apps compatibility with Embedding SDK tests` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
|
||||
e2e-sample-apps-tests:
|
||||
needs: [get-build-requirements, get-sample-apps-data, build]
|
||||
strategy:
|
||||
@@ -320,7 +316,7 @@ jobs:
|
||||
# - starts an app
|
||||
# - runs its Cypress tests against the e2e test metabase instance and local @metabase/embedding-sdk-react package.
|
||||
# The job is not required, though if it's failing better to be sure that it's not caused by a breaking change.
|
||||
# For more details see `Embedding SDK integration tests with Host Apps` in `enterprise/frontend/src/embedding-sdk/dev.md`
|
||||
# For more details see `Embedding SDK integration tests with Host Apps` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
|
||||
e2e-host-apps-tests:
|
||||
needs: [get-build-requirements, build]
|
||||
strategy:
|
||||
|
||||
8
.github/workflows/e2e-test.yml
vendored
@@ -79,9 +79,11 @@ jobs:
|
||||
uses: ./.github/actions/run-embedding-sdk-storybook
|
||||
|
||||
- name: Retrieve uberjar artifact for ${{ inputs.edition }}
|
||||
uses: actions/download-artifact@v4
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
with:
|
||||
name: metabase-${{ inputs.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
extract-path: "target/uberjar"
|
||||
output-name: "metabase.jar"
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
@@ -129,7 +131,7 @@ jobs:
|
||||
run: |
|
||||
echo "Running tests with specs: $SPEC_PATH"
|
||||
node e2e/runner/run_cypress_ci.js e2e \
|
||||
--env grepTags="-@mongo+-@flaky+-@OSS --@quarantine",grepOmitFiltered=true \
|
||||
--env grepTags="-@mongo+-@flaky+-@OSS+-@skip",grepOmitFiltered=true \
|
||||
--spec "$SPEC_PATH" \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
@@ -141,7 +143,7 @@ jobs:
|
||||
run: |
|
||||
echo "Running tests with specs: $SPEC_PATH"
|
||||
node e2e/runner/run_cypress_ci.js e2e \
|
||||
--env grepTags="${{inputs.tags}} --@quarantine",grepOmitFiltered=true \
|
||||
--env grepTags="${{inputs.tags}}+-@skip",grepOmitFiltered=true \
|
||||
--spec "$SPEC_PATH" \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
|
||||
29
.github/workflows/embedding-sdk.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
with:
|
||||
m2-cache-key: "cljs"
|
||||
- name: Build Embedding SDK package
|
||||
run: yarn build-embedding-sdk
|
||||
run: yarn build-embedding-sdk-package
|
||||
- name: Prepare Embedding SDK artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
if: ${{ steps.docs-generation.outcome == 'failure' }}
|
||||
run: exit 1
|
||||
|
||||
# See `Component e2e tests` in `enterprise/frontend/src/embedding-sdk/dev.md`
|
||||
# See `Component e2e tests` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
|
||||
sdk-e2e-tests:
|
||||
name: "SDK e2e tests"
|
||||
uses: ./.github/workflows/e2e-component-tests-embedding-sdk.yml
|
||||
@@ -146,24 +146,13 @@ jobs:
|
||||
with:
|
||||
cached-embedding-sdk-dist-artifact-name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
e2e-component-tests-embedding-sdk-cross-version:
|
||||
name: "[Backport only] SDK e2e cross version tests"
|
||||
# run on: every push on release branches, and every pr that targets a release branch
|
||||
if: ${{ startsWith(github.ref, 'refs/heads/release-x.') || (github.event_name == 'pull_request' && startsWith(github.base_ref, 'release-x.')) }}
|
||||
uses: ./.github/workflows/e2e-component-tests-embedding-sdk-cross-version.yml
|
||||
e2e-component-tests-embedding-sdk-backward-compatibility:
|
||||
name: "SDK e2e backward compatibility tests"
|
||||
uses: ./.github/workflows/e2e-component-tests-embedding-sdk-backward-compatibility.yml
|
||||
needs: [build]
|
||||
secrets: inherit
|
||||
|
||||
# Temporarily skipped because the cypress runner crashes
|
||||
# See `bin/backward-compatibility-test.js` for the documentation of this workflow.
|
||||
# cross-version-for-breaking-changes:
|
||||
# name: "[NOT REQUIRED - Experimental - Backport only] detect breaking changes with cross versions tests"
|
||||
# # run on: every pr that targets a release branch, it does NOT run for pr targeting master
|
||||
# if: ${{ github.event_name == 'pull_request' && startsWith(github.base_ref, 'release-x.') }}
|
||||
# uses: ./.github/workflows/e2e-cross-version-for-breaking-changes.yml
|
||||
# secrets: inherit
|
||||
# with:
|
||||
# fe-ref: ${{ github.base_ref }}
|
||||
# be-ref: ${{ github.head_ref }}
|
||||
with:
|
||||
cached-embedding-sdk-dist-artifact-name: embedding-sdk-${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
embedding-sdk-tests-result:
|
||||
needs:
|
||||
@@ -171,7 +160,7 @@ jobs:
|
||||
- embedding-sdk-docs-snippets-type-check
|
||||
- embedding-sdk-api-documentation-generation-validation
|
||||
- sdk-e2e-tests
|
||||
- e2e-component-tests-embedding-sdk-cross-version
|
||||
- e2e-component-tests-embedding-sdk-backward-compatibility
|
||||
if: always() && !cancelled()
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
|
||||
16
.github/workflows/frontend.yml
vendored
@@ -9,6 +9,16 @@ on:
|
||||
skip-lint:
|
||||
type: boolean
|
||||
default: false
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
skip:
|
||||
description: "Skip main frontend jobs (type-check, unit tests, timezone tests)"
|
||||
type: boolean
|
||||
default: false
|
||||
skip-lint:
|
||||
description: "Skip linting jobs (prettier, eslint, css variables check)"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}-frontend
|
||||
@@ -42,6 +52,8 @@ jobs:
|
||||
run: yarn run lint-prettier-pure
|
||||
- name: Run ESLint linter
|
||||
run: yarn run lint-eslint-pure
|
||||
- name: Run CSS linter
|
||||
run: yarn run lint-css
|
||||
|
||||
fe-type-check:
|
||||
if: ${{ !inputs.skip }}
|
||||
@@ -67,7 +79,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shard: [1, 2]
|
||||
shard: [1, 2] # 2 shards for parallel execution
|
||||
env:
|
||||
SHARDS: 2 # should match matrix above
|
||||
JEST_JUNIT_OUTPUT_DIR: ./target/junit
|
||||
@@ -84,7 +96,7 @@ jobs:
|
||||
run: yarn run test-unit --silent --shard=${{ matrix.shard }}/${{ env.SHARDS }}
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
if: always() && github.event_name != 'workflow_dispatch'
|
||||
with:
|
||||
input-path: ./target/junit
|
||||
output-name: frontend-unit
|
||||
|
||||
32
.github/workflows/links.yml
vendored
@@ -1,32 +0,0 @@
|
||||
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 --include-fragments --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
|
||||
6
.github/workflows/perf-test.yml
vendored
@@ -89,11 +89,11 @@ jobs:
|
||||
done
|
||||
echo "run_id=$(jq -r '.workflow_runs[0].id' e2e-tests.json)" >> $GITHUB_OUTPUT
|
||||
- name: Retrieve uberjar artifact for ee
|
||||
uses: actions/download-artifact@v4
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ inputs.wait_for_uberjar && steps.wait_for_uberjar.outputs.run_id || github.run_id }}
|
||||
extract-path: "target/uberjar"
|
||||
output-name: "metabase.jar"
|
||||
- name: Move uberjar to bin/docker
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar
|
||||
|
||||
4
.github/workflows/pr-env.yml
vendored
@@ -27,9 +27,11 @@ jobs:
|
||||
with:
|
||||
registries: "${{ secrets.PR_ENV_AWS_ACCOUNT_ID }}"
|
||||
- name: Retrieve uberjar artifact for ee
|
||||
uses: actions/download-artifact@v4
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
extract-path: "target/uberjar"
|
||||
output-name: "metabase.jar"
|
||||
- name: Move uberjar to bin/docker
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar
|
||||
|
||||
114
.github/workflows/release-embedding-sdk.yml
vendored
@@ -5,19 +5,12 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: "Branch we want to release the SDK from"
|
||||
description: "Branch we want to release the SDK from (to release from other branches use the workflow from those branches)"
|
||||
type: choice
|
||||
required: true
|
||||
default: "master"
|
||||
options:
|
||||
- master
|
||||
- release-x.51.x
|
||||
- release-x.52.x
|
||||
- release-x.53.x
|
||||
- release-x.54.x
|
||||
- release-x.55.x
|
||||
- release-x.56.x
|
||||
- esbuild-main
|
||||
|
||||
concurrency:
|
||||
# We want to ensure only one job is running at a time per branch because
|
||||
@@ -178,41 +171,39 @@ jobs:
|
||||
outputs:
|
||||
sdk_version: ${{ fromJson(steps.new-sdk-version.outputs.result).version }}
|
||||
major_version: ${{ fromJson(steps.new-sdk-version.outputs.result).majorVersion }}
|
||||
pre_release_label: ${{ fromJson(steps.new-sdk-version.outputs.result).preReleaseLabel }}
|
||||
steps:
|
||||
- name: Check out the code using the provided branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.branch }}
|
||||
|
||||
- name: Prepare build scripts
|
||||
run: yarn --cwd release --frozen-lockfile && yarn --cwd release build
|
||||
|
||||
- name: Get current SDK version
|
||||
id: current-sdk-version
|
||||
run: |
|
||||
VERSION=$(jq -r .version ./enterprise/frontend/src/embedding-sdk/package.template.json)
|
||||
VERSION=$(jq -r .version ./enterprise/frontend/src/embedding-sdk-package/package.template.json)
|
||||
echo "sdk_current_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get next SDK patch version
|
||||
- name: Get next SDK patch or pre-release version
|
||||
id: new-sdk-version
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const currentVersion = "${{ steps.current-sdk-version.outputs.sdk_current_version }}";
|
||||
const [currentVersionWithoutSuffix, suffix] = currentVersion.split("-");
|
||||
const versionParts = currentVersionWithoutSuffix.split(".");
|
||||
versionParts[versionParts.length - 1] = parseInt(versionParts.at(-1)) + 1;
|
||||
const newVersion = versionParts.join(".");
|
||||
const [_, majorVersion] = versionParts
|
||||
script: | #js
|
||||
const { getNextSdkVersion } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
if (!suffix) {
|
||||
return {
|
||||
version: newVersion,
|
||||
majorVersion
|
||||
};
|
||||
}
|
||||
const branch = "${{ inputs.branch }}";
|
||||
const currentVersion = "${{ steps.current-sdk-version.outputs.sdk_current_version }}";
|
||||
|
||||
const result = getNextSdkVersion(branch, currentVersion);
|
||||
|
||||
return {
|
||||
version: `${newVersion}-${suffix}`,
|
||||
majorVersion
|
||||
}
|
||||
version: result.version,
|
||||
preReleaseLabel: result.preReleaseLabel,
|
||||
majorVersion: result.majorVersion
|
||||
};
|
||||
|
||||
- name: Append workflow summary
|
||||
run: |
|
||||
@@ -298,8 +289,8 @@ jobs:
|
||||
run: |
|
||||
yarn embedding-sdk:generate-changelog -o changelog-diff
|
||||
|
||||
- name: Build SDK bundle
|
||||
run: yarn run build-embedding-sdk
|
||||
- name: Build SDK package
|
||||
run: yarn run build-embedding-sdk-package
|
||||
|
||||
- name: Generate SDK package.json in the build directory
|
||||
run: yarn run embedding-sdk:generate-package
|
||||
@@ -336,6 +327,7 @@ jobs:
|
||||
git config --global user.name "Metabase Automation"
|
||||
|
||||
- name: Update readme
|
||||
if: inputs.branch != 'master'
|
||||
run: |
|
||||
bash ./bin/embedding-sdk/release_utils.bash update_readme ${{ env.sdk_version }}
|
||||
|
||||
@@ -344,24 +336,37 @@ jobs:
|
||||
bash ./bin/embedding-sdk/release_utils.bash update_package_json_template ${{ env.sdk_version }}
|
||||
|
||||
- name: Retrieve SDK changelog diff
|
||||
if: inputs.branch != 'master'
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: sdk-changelog-diff
|
||||
|
||||
- name: Update changelog
|
||||
if: inputs.branch != 'master'
|
||||
run: |
|
||||
cat changelog-diff enterprise/frontend/src/embedding-sdk/CHANGELOG.md > new-changelog
|
||||
mv new-changelog enterprise/frontend/src/embedding-sdk/CHANGELOG.md
|
||||
cat changelog-diff enterprise/frontend/src/embedding-sdk-bundle/CHANGELOG.md > new-changelog
|
||||
mv new-changelog enterprise/frontend/src/embedding-sdk-bundle/CHANGELOG.md
|
||||
|
||||
- name: Create a PR updating readme + published version, and changelog (using GitHub Metabase Automation account)
|
||||
run: |
|
||||
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 }}'
|
||||
|
||||
if [ "${{ inputs.branch }}" = "master" ]; then
|
||||
COMMIT_MSG="chore(sdk): Update published npm version to ${{ env.sdk_version }}"
|
||||
PR_TITLE="chore(sdk): Update SDK version to ${{ env.sdk_version }}"
|
||||
PR_BODY="Update published npm package version to ${{ env.sdk_version }}"
|
||||
else
|
||||
COMMIT_MSG="docs(sdk): Update Readme version references and published npm version to ${{ env.sdk_version }}"
|
||||
PR_TITLE="docs(sdk): Update SDK version to ${{ env.sdk_version }}"
|
||||
PR_BODY="Update Readme version references and published npm package version to ${{ env.sdk_version }}"
|
||||
fi
|
||||
|
||||
git commit -a -m "$COMMIT_MSG"
|
||||
git push origin HEAD
|
||||
gh pr create --base ${{ inputs.branch }}\
|
||||
--assignee "${GITHUB_ACTOR}"\
|
||||
--title "docs(sdk): Update SDK version to ${{ env.sdk_version }}"\
|
||||
--body "Update Readme version references and published npm package version to ${{ env.sdk_version }}"
|
||||
gh pr create --base "${{ inputs.branch }}" \
|
||||
--assignee "${GITHUB_ACTOR}" \
|
||||
--title "$PR_TITLE" \
|
||||
--body "$PR_BODY"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
|
||||
@@ -389,24 +394,39 @@ jobs:
|
||||
name: metabase-sdk
|
||||
path: sdk
|
||||
|
||||
- name: Compute master tag
|
||||
id: compute-tag
|
||||
run: |
|
||||
if [ -n "${{ needs.determine-sdk-version.outputs.pre_release_label }}" ]; then
|
||||
echo "masterTag=${{ needs.determine-sdk-version.outputs.pre_release_label }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "masterTag=nightly" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Publish to NPM
|
||||
working-directory: sdk
|
||||
run: |
|
||||
echo //registry.npmjs.org/:_authToken=${{ secrets.NPM_RELEASE_TOKEN }} > .npmrc
|
||||
# Please keep the value in sync with `inputs.branch`'s release branch
|
||||
npm publish --tag ${{fromJson('{
|
||||
"master": "nightly",
|
||||
"release-x.51.x": "51-stable",
|
||||
"release-x.52.x": "52-stable",
|
||||
"release-x.53.x": "53-stable",
|
||||
"release-x.54.x": "54-stable",
|
||||
"release-x.55.x": "55-stable",
|
||||
"release-x.56.x": "56-nightly",
|
||||
"esbuild-main": "56-esbuild"
|
||||
}')[inputs.branch]}}
|
||||
|
||||
TAG=$(jq -r --null-input \
|
||||
--arg branch "${{ inputs.branch }}" \
|
||||
--arg masterTag "${{ steps.compute-tag.outputs.masterTag }}" '
|
||||
{
|
||||
"master": $masterTag,
|
||||
"release-x.51.x": "51-stable",
|
||||
"release-x.52.x": "52-stable",
|
||||
"release-x.53.x": "53-stable",
|
||||
"release-x.54.x": "54-stable",
|
||||
"release-x.55.x": "55-stable",
|
||||
"release-x.56.x": "56-stable"
|
||||
}[$branch]'
|
||||
)
|
||||
|
||||
echo "Resolved npm tag: $TAG"
|
||||
npm publish --tag "$TAG"
|
||||
|
||||
- name: Add `latest` tag to the latest release branch (`release-x.55.x`) deployment
|
||||
if: ${{ inputs.branch == 'release-x.55.x' }}
|
||||
if: ${{ inputs.branch == 'release-x.56.x' }}
|
||||
working-directory: sdk
|
||||
run: |
|
||||
npm dist-tag add @metabase/embedding-sdk-react@${{ env.sdk_version }} latest
|
||||
|
||||
21
.github/workflows/run-tests.yml
vendored
@@ -72,8 +72,6 @@ jobs:
|
||||
if: ${{ !cancelled() && !(needs.files-changed.outputs.documentation == 'true' && needs.files-changed.outputs.backend_all == 'false' && needs.files-changed.outputs.frontend_all == 'false' && needs.files-changed.outputs.e2e_all == 'false') }}
|
||||
uses: ./.github/workflows/uberjar.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
source_changed: ${{ needs.files-changed.outputs.backend_all == 'true' || needs.files-changed.outputs.frontend_all == 'true' || needs.static-viz-files-changed.outputs.static_viz == 'true' }}
|
||||
|
||||
backend-tests:
|
||||
if: ${{ !cancelled() }}
|
||||
@@ -83,6 +81,13 @@ jobs:
|
||||
with:
|
||||
skip: ${{ needs.files-changed.outputs.backend_all != 'true' && needs.static-viz-files-changed.outputs.static_viz != 'true' }}
|
||||
|
||||
semantic-search-tests:
|
||||
needs: files-changed
|
||||
uses: ./.github/workflows/semantic-search.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
skip: ${{ needs.files-changed.outputs.backend_all != 'true' }}
|
||||
|
||||
app-db-tests:
|
||||
needs: files-changed
|
||||
uses: ./.github/workflows/app-db.yml
|
||||
@@ -130,3 +135,15 @@ jobs:
|
||||
contains(github.event.pull_request.labels.*.name, 'PR-Env')
|
||||
uses: ./.github/workflows/pr-env.yml
|
||||
secrets: inherit
|
||||
|
||||
containerize:
|
||||
needs: [uberjar]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.uberjar.result == 'success' &&
|
||||
(
|
||||
(github.event_name == 'push' && contains(fromJson('["master", "metabot-v3-main", "internal-tools"]'), github.ref_name)) ||
|
||||
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar'))
|
||||
)
|
||||
uses: ./.github/workflows/containerize-uberjar.yml
|
||||
secrets: inherit
|
||||
|
||||
348
.github/workflows/semantic-search.yml
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
name: Semantic Search Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
skip:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}-semantic-search
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
semantic-search-tests-h2:
|
||||
if: ${{ !inputs.skip }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- name: H2 with pgvector pg17
|
||||
junit-name: semantic-search-tests-h2-pgvector-17
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
job:
|
||||
- name: Semantic Search Tests
|
||||
build-static-viz: false
|
||||
test-args: >-
|
||||
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
|
||||
exclude-tag: ':mb/driver-tests'
|
||||
|
||||
services:
|
||||
pgvector:
|
||||
image: ${{ matrix.version.pgvector-image }}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_DB: mb_semantic_search
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
env:
|
||||
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
|
||||
CI: 'true'
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test ${{ matrix.version.name }}
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
build-static-viz: ${{ matrix.job.build-static-viz }}
|
||||
junit-name: ${{ matrix.version.junit-name }}
|
||||
test-args: >-
|
||||
${{ matrix.job.test-args }}
|
||||
:exclude-tags '[${{ matrix.job.exclude-tag }}]'
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
semantic-search-tests-mariadb:
|
||||
if: ${{ !inputs.skip }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- name: MariaDB 10.2 with pgvector pg17
|
||||
junit-name: semantic-search-tests-mariadb-10-2
|
||||
mariadb-image: circleci/mariadb:10.2.23
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
- name: MariaDB Latest with pgvector pg17
|
||||
junit-name: semantic-search-tests-mariadb-latest
|
||||
mariadb-image: circleci/mariadb:latest
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
job:
|
||||
- name: Semantic Search Tests
|
||||
build-static-viz: false
|
||||
test-args: >-
|
||||
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
|
||||
exclude-tag: ':mb/driver-tests'
|
||||
|
||||
services:
|
||||
pgvector:
|
||||
image: ${{ matrix.version.pgvector-image }}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_DB: mb_semantic_search
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
mysql:
|
||||
image: ${{ matrix.version.mariadb-image }}
|
||||
ports:
|
||||
- "3306:3306"
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: true
|
||||
MYSQL_DATABASE: circle_test
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
MB_DB_TYPE: mysql
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_PORT: 3306
|
||||
MB_DB_DBNAME: circle_test
|
||||
MB_DB_USER: root
|
||||
MB_MYSQL_TEST_USER: root
|
||||
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test ${{ matrix.version.name }}
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
build-static-viz: ${{ matrix.job.build-static-viz }}
|
||||
junit-name: ${{ matrix.version.junit-name }}
|
||||
test-args: >-
|
||||
${{ matrix.job.test-args }}
|
||||
:exclude-tags '[${{ matrix.job.exclude-tag }}]'
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
semantic-search-tests-mysql:
|
||||
if: ${{ !inputs.skip }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- name: MySQL 8.0 with pgvector pg17
|
||||
junit-name: semantic-search-tests-mysql-8-0
|
||||
mysql-image: cimg/mysql:8.0
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
- name: MySQL Latest with pgvector pg17
|
||||
junit-name: semantic-search-tests-mysql-latest
|
||||
mysql-image: mysql:latest
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
job:
|
||||
- name: Semantic Search Tests
|
||||
build-static-viz: false
|
||||
test-args: >-
|
||||
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
|
||||
exclude-tag: ':mb/driver-tests'
|
||||
|
||||
services:
|
||||
pgvector:
|
||||
image: ${{ matrix.version.pgvector-image }}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_DB: mb_semantic_search
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
mysql:
|
||||
image: ${{ matrix.version.mysql-image }}
|
||||
ports:
|
||||
- "3306:3306"
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: true
|
||||
MYSQL_DATABASE: circle_test
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
MB_DB_TYPE: mysql
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_PORT: 3306
|
||||
MB_DB_DBNAME: circle_test
|
||||
MB_DB_USER: root
|
||||
MB_MYSQL_TEST_USER: root
|
||||
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test ${{ matrix.version.name }}
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
build-static-viz: ${{ matrix.job.build-static-viz }}
|
||||
junit-name: ${{ matrix.version.junit-name }}
|
||||
test-args: >-
|
||||
${{ matrix.job.test-args }}
|
||||
:exclude-tags '[${{ matrix.job.exclude-tag }}]'
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
semantic-search-tests-postgres:
|
||||
if: ${{ !inputs.skip }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- name: Postgres 12.x with pgvector pg17
|
||||
junit-name: semantic-search-tests-postgres-12
|
||||
postgres-image: postgres:12-alpine
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
- name: Postgres Latest with pgvector pg17
|
||||
junit-name: semantic-search-tests-postgres-latest
|
||||
postgres-image: postgres:latest
|
||||
pgvector-image: pgvector/pgvector:pg17
|
||||
job:
|
||||
- name: Semantic Search Tests
|
||||
build-static-viz: false
|
||||
test-args: >-
|
||||
:only '"enterprise/backend/test/metabase_enterprise/semantic_search"'
|
||||
exclude-tag: ':mb/driver-tests'
|
||||
|
||||
services:
|
||||
pgvector:
|
||||
image: ${{ matrix.version.pgvector-image }}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_DB: mb_semantic_search
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
postgres:
|
||||
image: ${{ matrix.version.postgres-image }}
|
||||
ports:
|
||||
- "5433:5432"
|
||||
env:
|
||||
POSTGRES_USER: mb_test
|
||||
POSTGRES_DB: mb_test
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: postgres
|
||||
MB_DB_TYPE: postgres
|
||||
MB_DB_PORT: 5433
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_DBNAME: mb_test
|
||||
MB_DB_USER: mb_test
|
||||
MB_POSTGRESQL_TEST_USER: mb_test
|
||||
MB_PGVECTOR_DB_URL: 'jdbc:postgres://localhost:5432/mb_semantic_search?user=postgres&password=postgres'
|
||||
name: "${{ matrix.version.name }} ${{ matrix.job.name }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test ${{ matrix.version.name }}
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
build-static-viz: ${{ matrix.job.build-static-viz }}
|
||||
junit-name: ${{ matrix.version.junit-name }}
|
||||
test-args: >-
|
||||
${{ matrix.job.test-args }}
|
||||
:exclude-tags '[${{ matrix.job.exclude-tag }}]'
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit/
|
||||
output-name: ${{ github.job }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
semantic-search-tests-result:
|
||||
needs:
|
||||
- semantic-search-tests-h2
|
||||
- semantic-search-tests-mariadb
|
||||
- semantic-search-tests-mysql
|
||||
- semantic-search-tests-postgres
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
name: semantic-search-tests-result
|
||||
if: always() && !cancelled()
|
||||
steps:
|
||||
- name: Check job status
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
needs: ${{ toJson(needs) }}
|
||||
with:
|
||||
script: | # js
|
||||
const needs = JSON.parse(process.env.needs);
|
||||
|
||||
const jobs = Object.entries(needs).map(
|
||||
([jobName, jobValues]) => ({
|
||||
name: jobName,
|
||||
result: jobValues.result
|
||||
}));
|
||||
|
||||
// are all jobs skipped or successful?
|
||||
if (jobs.every(job => (job.result === 'skipped' || job.result === 'success'))) {
|
||||
console.log("");
|
||||
console.log(" _------. ");
|
||||
console.log(" / , \_ ");
|
||||
console.log(" / / /{}\ |o\_ ");
|
||||
console.log(" / \ `--' /-' \ ");
|
||||
console.log(" | \ \ | ");
|
||||
console.log(" | |`-, | ");
|
||||
console.log(" / /__/)/ ");
|
||||
console.log(" | | ");
|
||||
console.log("");
|
||||
console.log("All semantic search tests have passed (or have been skipped). Cam is very proud of you.");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// otherwise, something failed
|
||||
console.log("");
|
||||
console.log(" .::::::::::. .::::::::::. ");
|
||||
console.log(" .::::''''''::::. .::::''''''::::. ");
|
||||
console.log(" .:::' `::::.... ....::::' `:::. ");
|
||||
console.log(" .::' `:::::::| |:::::::' `::. ");
|
||||
console.log(" .::| |::::::|_ ___ __|::::::| |::. ");
|
||||
console.log(" `--' |::::::|_()__()_|::::::| `--' ");
|
||||
console.log(" ::: |::-o::| |::o-::| ::: ");
|
||||
console.log(" `::. .|::::::| |::::::|. .::' ");
|
||||
console.log(" `:::. .::\-----' `-----/::. .:::' ");
|
||||
console.log(" `::::......::::' `::::......::::' ");
|
||||
console.log(" `::::::::::' `::::::::::' ");
|
||||
console.log("");
|
||||
console.log("Semantic search tests have failed. You have been sentenced to MetaJail.");
|
||||
|
||||
jobs.forEach((job) => {
|
||||
if (job.result !== 'success') {
|
||||
console.log(`${job.name} - ${job.result}`);
|
||||
}
|
||||
});
|
||||
|
||||
process.exit(1);
|
||||
21
.github/workflows/uberjar-containerize-labeled.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: Uberjar Containerize labeled
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ labeled, opened, synchronize, reopened ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
uberjar:
|
||||
if: ${{ contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar') || github.event.label.name == 'build-docker-uberjar' }}
|
||||
uses: ./.github/workflows/uberjar.yml
|
||||
secrets: inherit
|
||||
|
||||
containerize:
|
||||
needs: [uberjar]
|
||||
if: ${{ contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar') || github.event.label.name == 'build-docker-uberjar' }}
|
||||
uses: ./.github/workflows/containerize-uberjar.yml
|
||||
secrets: inherit
|
||||
140
.github/workflows/uberjar.yml
vendored
@@ -1,17 +1,16 @@
|
||||
name: Build + Docker Uberjar
|
||||
name: Build Uberjar
|
||||
|
||||
# This workflow builds an uberjar and pushes it to dockerhub for any branch, either on-demand,
|
||||
# or automatically for the listed branches
|
||||
|
||||
concurrency:
|
||||
group: uberjar-${{ github.ref }}
|
||||
group: uberjar-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}
|
||||
cancel-in-progress: false
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- metabot-v3-main
|
||||
- internal-tools
|
||||
paths-ignore:
|
||||
# config files
|
||||
@@ -28,11 +27,6 @@ on:
|
||||
commit:
|
||||
description: "Optional full-length commit SHA-1 hash"
|
||||
workflow_call:
|
||||
inputs:
|
||||
source_changed:
|
||||
description: "Whether source code has changed"
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
check-existing-artifacts:
|
||||
@@ -43,38 +37,41 @@ jobs:
|
||||
oss_exists: ${{ steps.check-oss.outcome == 'success' }}
|
||||
should_build: ${{ steps.decide.outputs.should_build }}
|
||||
steps:
|
||||
- name: Try to download existing EE artifact
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
- name: Try to fetch existing EE artifact
|
||||
id: check-ee
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@v4
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
output-name: metabase-ee.jar
|
||||
|
||||
- name: Try to download existing OSS artifact
|
||||
- name: Try to fetch existing OSS artifact
|
||||
id: check-oss
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@v4
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
with:
|
||||
name: metabase-oss-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
output-name: metabase-oss.jar
|
||||
|
||||
- name: Decide if build is needed
|
||||
id: decide
|
||||
run: |
|
||||
SOURCE_CHANGED="${{ inputs.source_changed == true }}"
|
||||
EE_EXISTS="${{ steps.check-ee.outcome == 'success' }}"
|
||||
OSS_EXISTS="${{ steps.check-oss.outcome == 'success' }}"
|
||||
|
||||
echo "Source changed: $SOURCE_CHANGED"
|
||||
echo "EE exists: $EE_EXISTS"
|
||||
echo "OSS exists: $OSS_EXISTS"
|
||||
|
||||
# Build if source changed OR artifacts don't exist
|
||||
if [[ "$SOURCE_CHANGED" == "true" ]] || [[ "$EE_EXISTS" == "false" ]] || [[ "$OSS_EXISTS" == "false" ]]; then
|
||||
# Build only if artifacts don't exist for this commit hash
|
||||
# Since we build by hash, if artifacts exist for this hash, we don't need to rebuild
|
||||
if [[ "$EE_EXISTS" == "false" ]] || [[ "$OSS_EXISTS" == "false" ]]; then
|
||||
SHOULD_BUILD="true"
|
||||
echo "Will build: source_changed=$SOURCE_CHANGED, ee_exists=$EE_EXISTS, oss_exists=$OSS_EXISTS"
|
||||
echo "Will build: ee_exists=$EE_EXISTS, oss_exists=$OSS_EXISTS"
|
||||
else
|
||||
SHOULD_BUILD="false"
|
||||
echo "Skipping build: artifacts exist and no source changes"
|
||||
echo "Skipping build: artifacts exist for this commit hash"
|
||||
fi
|
||||
|
||||
echo "should_build=$SHOULD_BUILD" >> $GITHUB_OUTPUT
|
||||
@@ -110,63 +107,17 @@ jobs:
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
get-container-info:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
name: Get container info
|
||||
# Skip if this is a PR without the build-docker-uberjar label
|
||||
if: github.ref_name == 'master' || contains(github.event.pull_request.labels.*.name, 'build-docker-uberjar')
|
||||
outputs:
|
||||
editions: ${{ toJson(fromJson(steps.info.outputs.result).editions) }}
|
||||
ee: ${{ toJson(fromJson(steps.info.outputs.result).ee) }}
|
||||
oss: ${{ toJson(fromJson(steps.info.outputs.result).oss) }}
|
||||
steps:
|
||||
- name: Get docker repo and tag
|
||||
id: info
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const branch = '${{ github.head_ref || github.ref_name }}';
|
||||
const owner = '${{ github.repository_owner }}';
|
||||
|
||||
console.log(`Branch: ${branch}`);
|
||||
|
||||
if (branch === "master") {
|
||||
return {
|
||||
editions: ["ee", "oss"],
|
||||
ee: {
|
||||
repo: `${owner}/metabase-enterprise-head`,
|
||||
tag: "latest"
|
||||
},
|
||||
oss: {
|
||||
repo: `${owner}/metabase-head`,
|
||||
tag: "latest"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
editions: ["ee"],
|
||||
ee: {
|
||||
repo: `${owner}/metabase-dev`,
|
||||
tag: branch.replaceAll("/", "-"), // slashes make docker sad
|
||||
},
|
||||
};
|
||||
|
||||
- name: Print output
|
||||
run: |
|
||||
echo "${{ steps.info.outputs.result }}"
|
||||
|
||||
build:
|
||||
needs:
|
||||
[check-existing-artifacts, get-build-requirements, get-container-info]
|
||||
[check-existing-artifacts, get-build-requirements]
|
||||
if: always() && !cancelled() && needs.check-existing-artifacts.outputs.should_build == 'true' && (needs.get-build-requirements.result == 'success' || needs.get-build-requirements.result == 'skipped')
|
||||
name: Build MB ${{ matrix.edition }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 15
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ needs.get-container-info.result == 'success' && fromJson(needs.get-container-info.outputs.editions) || fromJson('["ee", "oss"]') }}
|
||||
edition: ["ee", "oss"]
|
||||
env:
|
||||
MB_EDITION: ${{ matrix.edition }}
|
||||
INTERACTIVE: false
|
||||
@@ -195,14 +146,16 @@ jobs:
|
||||
check-jar-health:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Is ${{ matrix.edition }} (java ${{ matrix.java-version }}) healthy?
|
||||
needs: [build, check-existing-artifacts, get-container-info]
|
||||
needs: [build, check-existing-artifacts]
|
||||
if: always() && !cancelled() && (needs.build.result == 'success' || (needs.check-existing-artifacts.outputs.should_build == 'false' && needs.check-existing-artifacts.outputs.ee_exists == 'true' && needs.check-existing-artifacts.outputs.oss_exists == 'true'))
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ needs.get-container-info.result == 'success' && fromJson(needs.get-container-info.outputs.editions) || fromJson('["ee", "oss"]') }}
|
||||
edition: ["ee", "oss"]
|
||||
java-version: [21]
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
- name: Prepare JRE (Java Run-time Environment)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
@@ -210,57 +163,12 @@ jobs:
|
||||
java-version: ${{ matrix.java-version }}
|
||||
distribution: "temurin"
|
||||
- run: java -version
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Retrieve uberjar artifact
|
||||
- name: Retrieve uberjar artifact
|
||||
uses: ./.github/actions/fetch-artifact
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
- name: Launch uberjar
|
||||
run: >-
|
||||
java --add-opens java.base/java.nio=ALL-UNNAMED -jar ./target/uberjar/metabase.jar &
|
||||
java --add-opens java.base/java.nio=ALL-UNNAMED -jar ./metabase.jar &
|
||||
- name: Wait for Metabase to start
|
||||
run: while ! curl 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
|
||||
|
||||
containerize:
|
||||
needs: [check-jar-health, get-container-info, build]
|
||||
if: needs.get-container-info.result == 'success' && needs.build.result == 'success'
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
uses: ./.github/workflows/containerize-jar.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
artifact-name: metabase-${{ matrix.edition }}-${{ github.event.inputs.commit || github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
commit: ${{ github.event.inputs.commit || github.sha }}
|
||||
repo: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).repo }}
|
||||
tag: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).tag }}
|
||||
release: "false"
|
||||
build-args: |
|
||||
GIT_COMMIT_SHA=${{ github.event.inputs.commit || github.sha }}
|
||||
|
||||
run-trivy:
|
||||
needs: [get-container-info, containerize]
|
||||
strategy:
|
||||
matrix:
|
||||
edition: ${{ fromJson(needs.get-container-info.outputs.editions) }}
|
||||
runs-on: ubuntu-22.04
|
||||
name: Run Trivy vulnerability scanner
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.commit || github.sha }}
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@0.29.0
|
||||
env:
|
||||
TRIVY_OFFLINE_SCAN: true
|
||||
repo: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).repo }}
|
||||
tag: ${{ fromJson(needs.get-container-info.outputs[matrix.edition]).tag }}
|
||||
with:
|
||||
image-ref: docker.io/${{ env.repo }}:${{ env.tag }}
|
||||
format: sarif
|
||||
output: trivy-results.sarif
|
||||
version: "v0.57.1"
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: "trivy-results.sarif"
|
||||
|
||||
12
.gitignore
vendored
@@ -61,7 +61,9 @@ cypress.env.json
|
||||
/resources/frontend_client/app/dist/
|
||||
/resources/frontend_client/app/locales
|
||||
/resources/frontend_client/app/embed.js
|
||||
/resources/frontend_client/tmp-embed-js/
|
||||
/resources/frontend_client/app/embedding-sdk.js
|
||||
/resources/frontend_client/app/embedding-sdk.js.map
|
||||
/resources/frontend_client/tmp-*/
|
||||
/resources/frontend_client/embed.html
|
||||
/resources/frontend_client/embed-sdk.html
|
||||
/resources/frontend_client/index.html
|
||||
@@ -96,6 +98,13 @@ xcuserdata
|
||||
dev/src/dev/nocommit/
|
||||
dev/serialization_deltas/
|
||||
*~
|
||||
|
||||
# TypeScript compilation artifacts
|
||||
/build/
|
||||
*.tsbuildinfo
|
||||
/trace-output/
|
||||
/temp-types/
|
||||
|
||||
**/cypress_sample_database.json
|
||||
**/cypress_sample_instance_data.json
|
||||
/frontend/src/cljs
|
||||
@@ -154,3 +163,4 @@ CLAUDE.local.md
|
||||
|
||||
/logs
|
||||
/.clojure-mcp
|
||||
__pycache__/
|
||||
|
||||
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "python-runner"]
|
||||
path = python-runner
|
||||
url = https://github.com/metabase/python-runner-container.git
|
||||
branch = prototype
|
||||
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 71 KiB |