Compare commits
1089 Commits
testing
...
docs-api-l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
675a47d314 | ||
|
|
878a84389f | ||
|
|
d053b2fe80 | ||
|
|
ae97cbde23 | ||
|
|
4eeccde961 | ||
|
|
322b8958c8 | ||
|
|
2ed72d106b | ||
|
|
fe13ca6859 | ||
|
|
5c011ed5ec | ||
|
|
4bc96006af | ||
|
|
73fe6a603c | ||
|
|
e9d13a38c1 | ||
|
|
dea02a4d22 | ||
|
|
84dc6f75ee | ||
|
|
8985d95122 | ||
|
|
263256f7ab | ||
|
|
be4a57cf78 | ||
|
|
68101f50f2 | ||
|
|
393308bc5c | ||
|
|
4b64ef287b | ||
|
|
eb596a48f0 | ||
|
|
0502dd8a8e | ||
|
|
670ee25906 | ||
|
|
7dfe9d4cc4 | ||
|
|
5444d94a13 | ||
|
|
97a47fe9db | ||
|
|
189703e895 | ||
|
|
c170d97352 | ||
|
|
1a8e6132b2 | ||
|
|
4a9e296160 | ||
|
|
6ee87dcc9b | ||
|
|
b7950cd10e | ||
|
|
21e2b99ec6 | ||
|
|
72b3cc3f48 | ||
|
|
aab7f5baee | ||
|
|
0361bdd557 | ||
|
|
7c276e3bbf | ||
|
|
0b44617a5d | ||
|
|
7ff5975436 | ||
|
|
bcac621fa8 | ||
|
|
bea199498e | ||
|
|
5583a5c29a | ||
|
|
96b843e41c | ||
|
|
8b8147a807 | ||
|
|
79b33141f7 | ||
|
|
28a1629790 | ||
|
|
f42b605299 | ||
|
|
c2de5b5e5f | ||
|
|
6a3aa35832 | ||
|
|
48ae90a5b1 | ||
|
|
ff06e1b900 | ||
|
|
53af5593bd | ||
|
|
be1eac5e39 | ||
|
|
718f667515 | ||
|
|
4452359c58 | ||
|
|
428b0c9f86 | ||
|
|
91ddc60070 | ||
|
|
bda324e42b | ||
|
|
6fb5fdc8f4 | ||
|
|
53dee386d3 | ||
|
|
d4db9cd0e8 | ||
|
|
ec0ac2bf7a | ||
|
|
963d308568 | ||
|
|
f99b8baa5f | ||
|
|
522910ec6b | ||
|
|
bc4e2da39b | ||
|
|
9f01f0efa4 | ||
|
|
f29b68770f | ||
|
|
f147c3710b | ||
|
|
a8634811a0 | ||
|
|
482f6bbff4 | ||
|
|
ec4192eb9d | ||
|
|
41bac38d80 | ||
|
|
cfe322223b | ||
|
|
f314f6d56a | ||
|
|
4304b96ce2 | ||
|
|
56357db89f | ||
|
|
b04cfa86a6 | ||
|
|
7a4d682dde | ||
|
|
83cbbd7e45 | ||
|
|
4e451b4692 | ||
|
|
71735c6722 | ||
|
|
dd021f0862 | ||
|
|
6c933f2d91 | ||
|
|
4cfbd67ce2 | ||
|
|
f024e79c85 | ||
|
|
6d4b695b5f | ||
|
|
500b0e6d06 | ||
|
|
8f49ab0dd0 | ||
|
|
aa8a386e34 | ||
|
|
00a087bb52 | ||
|
|
41e4defd29 | ||
|
|
bb32a4111b | ||
|
|
94372d6fa6 | ||
|
|
c29f2e382d | ||
|
|
084384db11 | ||
|
|
e1a1e73128 | ||
|
|
a59eba3e63 | ||
|
|
685c36f599 | ||
|
|
3d01b319e5 | ||
|
|
93a703a911 | ||
|
|
ec2f229fe1 | ||
|
|
f19101b970 | ||
|
|
cce25745a7 | ||
|
|
fd32386973 | ||
|
|
5548e70d57 | ||
|
|
ea928cdb2c | ||
|
|
7bfb4662d1 | ||
|
|
a238b9310f | ||
|
|
f9b87a3f6b | ||
|
|
7178d0fba9 | ||
|
|
775feb1aa1 | ||
|
|
cc15ee649e | ||
|
|
5a52987617 | ||
|
|
11f501e810 | ||
|
|
e0a2a322ba | ||
|
|
19d7f3d58a | ||
|
|
fc85504079 | ||
|
|
ef01a0f9f1 | ||
|
|
08b11e1dfa | ||
|
|
4cba79cdf1 | ||
|
|
a21280000a | ||
|
|
601c4f7412 | ||
|
|
7008d38317 | ||
|
|
e480527e92 | ||
|
|
e56e508989 | ||
|
|
38cc13c3d3 | ||
|
|
bb854dbd50 | ||
|
|
d619950925 | ||
|
|
0fbb656080 | ||
|
|
869efcea7a | ||
|
|
bf6759b08d | ||
|
|
86b994e7a5 | ||
|
|
4bbd4cc2aa | ||
|
|
9dbfd5bc08 | ||
|
|
2021f7daec | ||
|
|
6e72ffbb53 | ||
|
|
da9d62a0e7 | ||
|
|
912ee7b034 | ||
|
|
5bc378d9ca | ||
|
|
0e415e664c | ||
|
|
4df1c417a9 | ||
|
|
6f8ff73343 | ||
|
|
70c6be8670 | ||
|
|
7ab0c413a4 | ||
|
|
ed61e82fa4 | ||
|
|
bd36ca40cc | ||
|
|
2970dc54d5 | ||
|
|
24249e76da | ||
|
|
6059f92ca2 | ||
|
|
4a0c62775f | ||
|
|
f768b844c3 | ||
|
|
79817b4f15 | ||
|
|
b7a030022b | ||
|
|
cd650bfd69 | ||
|
|
cd71625a45 | ||
|
|
2d01597302 | ||
|
|
afc1963a9b | ||
|
|
08771ef685 | ||
|
|
4882239cd9 | ||
|
|
6fa8ff4779 | ||
|
|
db1c4f3741 | ||
|
|
321c37ca1c | ||
|
|
a0d13128dc | ||
|
|
8c08ebbf3d | ||
|
|
d0137526c8 | ||
|
|
f88e47c127 | ||
|
|
591599bf4e | ||
|
|
f5a22e7a3b | ||
|
|
83e55c8dce | ||
|
|
f9545b8740 | ||
|
|
f7c5f1f2f5 | ||
|
|
fb7ae7d97c | ||
|
|
aae8d818ad | ||
|
|
b1de8b8bfd | ||
|
|
7ab2e5ecff | ||
|
|
e8ebd956f4 | ||
|
|
1200eb2f10 | ||
|
|
70b4ad81e9 | ||
|
|
82f13b6742 | ||
|
|
528222e7e2 | ||
|
|
62caae9946 | ||
|
|
a04af019b9 | ||
|
|
29b070c07a | ||
|
|
33e50fa799 | ||
|
|
876eedc92a | ||
|
|
1d8541ca43 | ||
|
|
53568b2570 | ||
|
|
2ed4ad3d7c | ||
|
|
208deba6e6 | ||
|
|
3f629276d8 | ||
|
|
b06e6e9c34 | ||
|
|
e81c4137fc | ||
|
|
3f367ac9a3 | ||
|
|
10986403a0 | ||
|
|
3b2fdbb676 | ||
|
|
9acb577c10 | ||
|
|
b62505f15b | ||
|
|
ceacccd0b1 | ||
|
|
ce49352589 | ||
|
|
219ca91f6d | ||
|
|
1770e0d228 | ||
|
|
0cecef1c38 | ||
|
|
4a47bd20f0 | ||
|
|
600e4aec03 | ||
|
|
c9b18c5fc6 | ||
|
|
d95746367e | ||
|
|
1f8b62c4ea | ||
|
|
6d4ea59746 | ||
|
|
5607cb71c0 | ||
|
|
99a1cdb660 | ||
|
|
ebb3f14c39 | ||
|
|
7c6b8bee37 | ||
|
|
41c73023b6 | ||
|
|
ad25f3c0eb | ||
|
|
130f406b4f | ||
|
|
10f52f57ef | ||
|
|
ccd6b59b34 | ||
|
|
faf82bd8d5 | ||
|
|
cb71e0e908 | ||
|
|
b88e7431b6 | ||
|
|
0c4d8284b0 | ||
|
|
a96a840c78 | ||
|
|
84f6a327fa | ||
|
|
4904ae048f | ||
|
|
115d77dfbe | ||
|
|
a1aff9440f | ||
|
|
f3edd784f0 | ||
|
|
c40657ff3a | ||
|
|
110079b65b | ||
|
|
fba8aab8ac | ||
|
|
f256f2d2eb | ||
|
|
9f3e0bc68a | ||
|
|
5313e018e8 | ||
|
|
c0eab4452e | ||
|
|
179554e564 | ||
|
|
dbd60f5c47 | ||
|
|
59c5690bd6 | ||
|
|
5197e318d7 | ||
|
|
fbe206dfba | ||
|
|
168bd09275 | ||
|
|
41b212a654 | ||
|
|
b2fade6394 | ||
|
|
8f93e5550d | ||
|
|
c3c2e8ee18 | ||
|
|
b03d6f7e2b | ||
|
|
da0397c091 | ||
|
|
47200643e1 | ||
|
|
6c22043070 | ||
|
|
34401cccab | ||
|
|
e80c600db5 | ||
|
|
3d6c90698b | ||
|
|
7b4c298126 | ||
|
|
631947bfb8 | ||
|
|
6ce8344c90 | ||
|
|
6d83cb2b60 | ||
|
|
9f4327cf87 | ||
|
|
989bb6ff23 | ||
|
|
82c39bb942 | ||
|
|
bcd41db9ad | ||
|
|
a135e609e8 | ||
|
|
c2504f4e99 | ||
|
|
fd0cafeb7b | ||
|
|
3e1f18a9cf | ||
|
|
89faa64681 | ||
|
|
8e68606eb4 | ||
|
|
26e8f86868 | ||
|
|
4c27ad5fa3 | ||
|
|
2c76bd4a92 | ||
|
|
8692d9e000 | ||
|
|
02e80cf2ae | ||
|
|
6f1f0c02ed | ||
|
|
3be2611784 | ||
|
|
5b3278831c | ||
|
|
c592413341 | ||
|
|
98e0fce497 | ||
|
|
88d5b7bc17 | ||
|
|
ad3fc72b03 | ||
|
|
51b73954e1 | ||
|
|
85ce744a2b | ||
|
|
33915469e3 | ||
|
|
b85e236113 | ||
|
|
32d8726ac9 | ||
|
|
72f70ade32 | ||
|
|
80cd4f3c80 | ||
|
|
2e73064e94 | ||
|
|
e1f2fb96c3 | ||
|
|
9006696ee3 | ||
|
|
727246d3b1 | ||
|
|
5e6851a8c3 | ||
|
|
83f0c60fea | ||
|
|
414048fba0 | ||
|
|
2b1c6958c0 | ||
|
|
590951cacb | ||
|
|
35ec452c6c | ||
|
|
63ce443b49 | ||
|
|
44dd5df5da | ||
|
|
4e8404d3b7 | ||
|
|
33ff237b59 | ||
|
|
703638cd10 | ||
|
|
142306a3f7 | ||
|
|
9401a0ba6f | ||
|
|
b4aa704be6 | ||
|
|
f5e63b4001 | ||
|
|
2d9d447492 | ||
|
|
0f9bb8045b | ||
|
|
aa0a444be4 | ||
|
|
c7e8d6cae5 | ||
|
|
16117c6423 | ||
|
|
18bfb20523 | ||
|
|
bf184ac3da | ||
|
|
37acc7e854 | ||
|
|
e2a8d43ed5 | ||
|
|
07ee64373f | ||
|
|
c63bfcf186 | ||
|
|
499553cc74 | ||
|
|
8e95128018 | ||
|
|
1470cb1abe | ||
|
|
68f645545d | ||
|
|
caadb4cfd6 | ||
|
|
0cd2032a35 | ||
|
|
b26eca90b9 | ||
|
|
3e7a8a4e48 | ||
|
|
d5b09bc9e0 | ||
|
|
8b8bbc66a4 | ||
|
|
299b698cd4 | ||
|
|
0c8b9a133b | ||
|
|
fa6f4762cc | ||
|
|
6e407f15aa | ||
|
|
167b1b6f87 | ||
|
|
e105de0219 | ||
|
|
87b60ba547 | ||
|
|
fd0954aeb7 | ||
|
|
755256a800 | ||
|
|
29428b7c80 | ||
|
|
5d7ac6573a | ||
|
|
81c0389fe9 | ||
|
|
6f1d9cbdd3 | ||
|
|
3159eda4dc | ||
|
|
7030df04e8 | ||
|
|
1ab92fde40 | ||
|
|
3e0b03e8fd | ||
|
|
b403648472 | ||
|
|
84b0948e60 | ||
|
|
bb6428e537 | ||
|
|
7368fb1de1 | ||
|
|
fe8f1f9a9d | ||
|
|
7a52063c5c | ||
|
|
b4e22eb6b0 | ||
|
|
8f41692cb0 | ||
|
|
43092b1d2a | ||
|
|
bd3542401a | ||
|
|
9cc1a46c8a | ||
|
|
69958ce424 | ||
|
|
138560b595 | ||
|
|
dda69aa5f8 | ||
|
|
6838a0793b | ||
|
|
c45ea5c5ef | ||
|
|
41dca76232 | ||
|
|
8c2b6e8945 | ||
|
|
90979e9abd | ||
|
|
f6aafc34b6 | ||
|
|
0c964fe87c | ||
|
|
c6e9700797 | ||
|
|
cab4af2e02 | ||
|
|
51d6ba5b6c | ||
|
|
1686e8a692 | ||
|
|
fb0cf744e7 | ||
|
|
89dbffbee5 | ||
|
|
201a2ebee4 | ||
|
|
134702499b | ||
|
|
b8c2c4b14d | ||
|
|
8d380fe7d1 | ||
|
|
0e7c6effa8 | ||
|
|
4ed8196c6d | ||
|
|
e118f02238 | ||
|
|
1cfb805d94 | ||
|
|
af37dadef4 | ||
|
|
6780a67b53 | ||
|
|
26190d82c3 | ||
|
|
f1ee606e3a | ||
|
|
79ca4f498a | ||
|
|
f584ab658d | ||
|
|
202322f93d | ||
|
|
b7ab04d726 | ||
|
|
cfff2e84d4 | ||
|
|
ee23a50124 | ||
|
|
a4363903c1 | ||
|
|
ce5f60b7ca | ||
|
|
948bd56469 | ||
|
|
b90620b0d9 | ||
|
|
87a28bab93 | ||
|
|
54a356a60a | ||
|
|
162437a227 | ||
|
|
7828b5e291 | ||
|
|
095f1a1a74 | ||
|
|
25bab869a4 | ||
|
|
c7e0bc4cf8 | ||
|
|
62333310e3 | ||
|
|
5f86ebe6ee | ||
|
|
075163202f | ||
|
|
d436dafd2c | ||
|
|
6694870932 | ||
|
|
e9f6c507db | ||
|
|
50585b3189 | ||
|
|
a14e5f75bf | ||
|
|
e23bd004e2 | ||
|
|
7393892bff | ||
|
|
a9841dad20 | ||
|
|
ed00dfd3ce | ||
|
|
65bdbe6e04 | ||
|
|
5317db6d60 | ||
|
|
b378247ca2 | ||
|
|
7232d91a4e | ||
|
|
77fb4fceb6 | ||
|
|
43a7c3f641 | ||
|
|
092a4fb63a | ||
|
|
ac9ba610ba | ||
|
|
8b1ffdf094 | ||
|
|
6be94ca238 | ||
|
|
9f00d56275 | ||
|
|
d96814e204 | ||
|
|
515111f761 | ||
|
|
d8843159f6 | ||
|
|
e96c532f8c | ||
|
|
106686bca9 | ||
|
|
b8c549b938 | ||
|
|
bd3fa8c064 | ||
|
|
b350934a12 | ||
|
|
bcc0b566b1 | ||
|
|
53d97cc29c | ||
|
|
401d7dbc38 | ||
|
|
df2e240446 | ||
|
|
5300031161 | ||
|
|
02039eebb9 | ||
|
|
bc59e29174 | ||
|
|
f2d207df03 | ||
|
|
e655081bc6 | ||
|
|
7d76ab179f | ||
|
|
2f8a7c697e | ||
|
|
21aff9dc7a | ||
|
|
80b7dcbb29 | ||
|
|
5f6b9ecb17 | ||
|
|
3990a6ea06 | ||
|
|
f1e738fc34 | ||
|
|
8513bc970a | ||
|
|
66e2910241 | ||
|
|
69802d15ec | ||
|
|
3f2f855cd0 | ||
|
|
79858b9fa2 | ||
|
|
918925ad60 | ||
|
|
379cf342d3 | ||
|
|
64219be813 | ||
|
|
43ffbf0b24 | ||
|
|
5fb95767da | ||
|
|
1ac47c7425 | ||
|
|
b4f057ab47 | ||
|
|
3a5a7f385e | ||
|
|
3e3f408c09 | ||
|
|
0002f20c6d | ||
|
|
e96e46015d | ||
|
|
55a4540329 | ||
|
|
12f85cbb79 | ||
|
|
fbd2a24d0a | ||
|
|
9ed2c3a26f | ||
|
|
e900711e8d | ||
|
|
9bd17d26f7 | ||
|
|
23cc30fe17 | ||
|
|
47d81c46bc | ||
|
|
6895e51d4e | ||
|
|
5bbb9f847a | ||
|
|
893e297e0d | ||
|
|
1ecd0da57f | ||
|
|
aa140ef998 | ||
|
|
c7bb60c811 | ||
|
|
824545546a | ||
|
|
e2522f4fa7 | ||
|
|
5be9510069 | ||
|
|
731497f63f | ||
|
|
0b09b76ace | ||
|
|
52d223d44b | ||
|
|
964d31ec8d | ||
|
|
409c93833f | ||
|
|
06fef3905a | ||
|
|
3f77c0c480 | ||
|
|
17bb910200 | ||
|
|
ceba6e407c | ||
|
|
077236f2da | ||
|
|
667c3f93ef | ||
|
|
320f0907cc | ||
|
|
1a421b3ad5 | ||
|
|
42013c4e1d | ||
|
|
1ab3e4e9d6 | ||
|
|
0c442b6222 | ||
|
|
4ab6c6eb42 | ||
|
|
2be5130e7c | ||
|
|
21ae344b09 | ||
|
|
b3a46a7791 | ||
|
|
ab60efa430 | ||
|
|
d291c1509e | ||
|
|
5203a15cdc | ||
|
|
552cf921ff | ||
|
|
c8aa0a5420 | ||
|
|
ef09cc16c3 | ||
|
|
17887dcd2c | ||
|
|
7951b71137 | ||
|
|
7d8f8a889b | ||
|
|
1ea5557754 | ||
|
|
520db04167 | ||
|
|
09483a66d3 | ||
|
|
b9bc8c1c21 | ||
|
|
4d5aa8053a | ||
|
|
ed893e19b2 | ||
|
|
bc3c54b6b1 | ||
|
|
13eb9ae2f1 | ||
|
|
6c0d44d1ca | ||
|
|
5475a123b8 | ||
|
|
e85e79c80d | ||
|
|
4a63f1aff6 | ||
|
|
dd068ca4bd | ||
|
|
86f2266739 | ||
|
|
9fb6328cfb | ||
|
|
07dfbc2b2d | ||
|
|
f767715a72 | ||
|
|
ee3ccf1432 | ||
|
|
f49c703daf | ||
|
|
290165d966 | ||
|
|
113d75ce93 | ||
|
|
bffdfada3d | ||
|
|
f707115294 | ||
|
|
87e3b95b1b | ||
|
|
87204effb2 | ||
|
|
4761766738 | ||
|
|
e27d304930 | ||
|
|
94ac40e640 | ||
|
|
70ea4a0ab0 | ||
|
|
aaedddf828 | ||
|
|
4aaa13a857 | ||
|
|
9ae02bef47 | ||
|
|
200c69373d | ||
|
|
00737e9910 | ||
|
|
473c4cd89e | ||
|
|
39f8f6a6ea | ||
|
|
4418173684 | ||
|
|
85161494a9 | ||
|
|
d0020aae8c | ||
|
|
0434d5ad87 | ||
|
|
e150fafa85 | ||
|
|
a31ff2e5d8 | ||
|
|
03af173dbc | ||
|
|
1204554eea | ||
|
|
b1ad9a1a30 | ||
|
|
69f6527edd | ||
|
|
8eb105c7d6 | ||
|
|
db0f9119fc | ||
|
|
00dd363bcc | ||
|
|
8fc9892750 | ||
|
|
a9819e8cac | ||
|
|
d2d95df948 | ||
|
|
c2735f6dbb | ||
|
|
d8ef4d3818 | ||
|
|
8c6c93c724 | ||
|
|
a6a1e56a12 | ||
|
|
1baecd8b52 | ||
|
|
6f0d3aac8d | ||
|
|
90d88fa634 | ||
|
|
a5a03934d6 | ||
|
|
09ee5aa2e8 | ||
|
|
7d6d88969b | ||
|
|
f9447d7435 | ||
|
|
dffe10a284 | ||
|
|
02e50c2771 | ||
|
|
ec3091f6da | ||
|
|
c73fd9e67c | ||
|
|
4850a85b7c | ||
|
|
f1cf4abbc7 | ||
|
|
dbf9bfffca | ||
|
|
fb1e407f46 | ||
|
|
3f9ac93432 | ||
|
|
5da6fb67a1 | ||
|
|
f9efc2127d | ||
|
|
e5f93b0772 | ||
|
|
2aadf71ea6 | ||
|
|
a2a4e7a56c | ||
|
|
63ca4c1744 | ||
|
|
bb0c4a9c48 | ||
|
|
f9ac943512 | ||
|
|
7a16dce71e | ||
|
|
0d67c7c918 | ||
|
|
d189040aec | ||
|
|
ad97273959 | ||
|
|
34827169dd | ||
|
|
a66a69e425 | ||
|
|
4b7141f979 | ||
|
|
1233547f77 | ||
|
|
02b09153ba | ||
|
|
df321012c3 | ||
|
|
9d013a5f2d | ||
|
|
88b03e22cd | ||
|
|
946afe2916 | ||
|
|
6c8edfa7d3 | ||
|
|
8d8ae87899 | ||
|
|
1eb307a55e | ||
|
|
1b7c16c9e8 | ||
|
|
57d786df8b | ||
|
|
cd68d42db7 | ||
|
|
f340a3aecb | ||
|
|
c4868c667e | ||
|
|
5331d3816f | ||
|
|
7348161cc4 | ||
|
|
75d2498163 | ||
|
|
7ffdac9257 | ||
|
|
96f9898d40 | ||
|
|
c57b3a38e0 | ||
|
|
df23ed88ce | ||
|
|
809d568858 | ||
|
|
ab5f9266e0 | ||
|
|
dd50957580 | ||
|
|
652fafea3c | ||
|
|
a4828dc9e2 | ||
|
|
1815b5248f | ||
|
|
977429c46f | ||
|
|
6bf6a5de38 | ||
|
|
63151f4e23 | ||
|
|
3953460236 | ||
|
|
ce19393b37 | ||
|
|
1a921a831a | ||
|
|
dba17e6c36 | ||
|
|
012e0c5f78 | ||
|
|
240634d336 | ||
|
|
17c271d87f | ||
|
|
f6b8e1e8a3 | ||
|
|
ebf8bb9215 | ||
|
|
35d89b052e | ||
|
|
8766bfa37e | ||
|
|
46191072d0 | ||
|
|
82728422c3 | ||
|
|
d477b55947 | ||
|
|
6452cd3c17 | ||
|
|
3e33ab4cb9 | ||
|
|
a0598e466a | ||
|
|
34ec746983 | ||
|
|
00d5c7178b | ||
|
|
71520bcc23 | ||
|
|
632e138681 | ||
|
|
b0eb248971 | ||
|
|
e8e77d643e | ||
|
|
839b713f50 | ||
|
|
f1a6b53f5a | ||
|
|
5dd1cca580 | ||
|
|
11324019e3 | ||
|
|
9f49d1aa14 | ||
|
|
fddd02bdc1 | ||
|
|
13bc2e1b65 | ||
|
|
4dce302c1a | ||
|
|
7991f9619e | ||
|
|
8ed623adf8 | ||
|
|
c1862eeada | ||
|
|
060baf0ce4 | ||
|
|
518e79b8fb | ||
|
|
e840233a4f | ||
|
|
924c6d3153 | ||
|
|
516f03f510 | ||
|
|
bd0a008013 | ||
|
|
6bffd075d7 | ||
|
|
e005f7bb76 | ||
|
|
89ad60ae1a | ||
|
|
d82015eb22 | ||
|
|
bfe568e8a1 | ||
|
|
1923709c5f | ||
|
|
4162c2f0a4 | ||
|
|
de559f49d6 | ||
|
|
089fb7000c | ||
|
|
d5377880e4 | ||
|
|
403c260eca | ||
|
|
06dd8dcffb | ||
|
|
4a6c1d268e | ||
|
|
896c516d98 | ||
|
|
9cfc06eff2 | ||
|
|
afeeab14aa | ||
|
|
972ef2b8a1 | ||
|
|
db82ec7146 | ||
|
|
9fcfc5b5e7 | ||
|
|
6742879b84 | ||
|
|
f1fc4f3ac9 | ||
|
|
5bbafa83f5 | ||
|
|
5879f90bfa | ||
|
|
ff0aa11054 | ||
|
|
47a87dee16 | ||
|
|
7e3ddd69c3 | ||
|
|
039046a8e4 | ||
|
|
74ff7169c4 | ||
|
|
50a1cdbbe9 | ||
|
|
a4d50c7482 | ||
|
|
cf934f928d | ||
|
|
f40dc5f25e | ||
|
|
6923ccb0fb | ||
|
|
741b1bd4e7 | ||
|
|
537228e1d5 | ||
|
|
54ec54b75c | ||
|
|
91a7e4d910 | ||
|
|
5ad318b006 | ||
|
|
c7231ee7d0 | ||
|
|
c01d67df0e | ||
|
|
516ac41f95 | ||
|
|
d50fb86a2b | ||
|
|
83f0efc8c3 | ||
|
|
e3d1b619ee | ||
|
|
31b8daf1b3 | ||
|
|
08cf3417c0 | ||
|
|
ad8ba4bdcf | ||
|
|
c56ec99934 | ||
|
|
fedd146699 | ||
|
|
216d887955 | ||
|
|
318e448959 | ||
|
|
9ab8d426c3 | ||
|
|
38a9eb3a72 | ||
|
|
6f7a54ad31 | ||
|
|
3fa450e20e | ||
|
|
548a9a7433 | ||
|
|
35d99ba88b | ||
|
|
a122a6b7cc | ||
|
|
14433723a8 | ||
|
|
842f3f358f | ||
|
|
53518074ff | ||
|
|
19680bf09b | ||
|
|
d23d7a3a03 | ||
|
|
32cb5b785b | ||
|
|
d053ef08e9 | ||
|
|
8f3a30c5a5 | ||
|
|
3ed6cb81f8 | ||
|
|
c3f9a20ea8 | ||
|
|
16a4ac4aae | ||
|
|
a223f819c7 | ||
|
|
28b0e3c5b5 | ||
|
|
32f9d0f2cf | ||
|
|
58dab8c9fa | ||
|
|
98cdc6dcc8 | ||
|
|
617d21025f | ||
|
|
70904e8cd9 | ||
|
|
9b4d3d2b2e | ||
|
|
abc35fe8b6 | ||
|
|
b465d938bb | ||
|
|
b35755f9e0 | ||
|
|
3ea2530ca8 | ||
|
|
e2036b6142 | ||
|
|
6a3fe64e3f | ||
|
|
1bb08949d2 | ||
|
|
006dbdecde | ||
|
|
372cbd3e5d | ||
|
|
81e57dedae | ||
|
|
7d4bfaaee6 | ||
|
|
a22441d500 | ||
|
|
ec6c0880d0 | ||
|
|
0532b7b1dc | ||
|
|
727731bb13 | ||
|
|
6d7bc0684c | ||
|
|
0c40e7562f | ||
|
|
a85f7507b3 | ||
|
|
5929e66476 | ||
|
|
d616baf693 | ||
|
|
0a455d9a68 | ||
|
|
e20c00b155 | ||
|
|
c6683ce7a0 | ||
|
|
6a927deefb | ||
|
|
f022ed8198 | ||
|
|
d7e56b2641 | ||
|
|
9a455d6332 | ||
|
|
ea8328f2bb | ||
|
|
2fd311c521 | ||
|
|
cca66d443c | ||
|
|
0c90ddfa09 | ||
|
|
e99c67a153 | ||
|
|
ae92d2817f | ||
|
|
bf10c9b6fc | ||
|
|
82cf05cea8 | ||
|
|
82c4a949d0 | ||
|
|
a94d58fc52 | ||
|
|
c6ac90b483 | ||
|
|
16181dce67 | ||
|
|
0a1eca6b25 | ||
|
|
1c01afcbcb | ||
|
|
5294948e6a | ||
|
|
9ae3c870c0 | ||
|
|
df158d8896 | ||
|
|
df31f565bc | ||
|
|
5c198037de | ||
|
|
b7e1ef6f4f | ||
|
|
b96f55194c | ||
|
|
b94da7585b | ||
|
|
7c0023fe1a | ||
|
|
94f582662e | ||
|
|
c9bfb047ea | ||
|
|
94081aeadd | ||
|
|
7d61485bc8 | ||
|
|
988514f03c | ||
|
|
434703431f | ||
|
|
bcf0a42f9a | ||
|
|
5d81bdc44d | ||
|
|
3a05e07fe1 | ||
|
|
d4bfd14d6f | ||
|
|
dbdef76e63 | ||
|
|
f537c80069 | ||
|
|
f9e6dfc686 | ||
|
|
3bf8ba58e5 | ||
|
|
e3158b0bdc | ||
|
|
d03df1309d | ||
|
|
bdc9c5a943 | ||
|
|
313f13f9aa | ||
|
|
f573f9dddc | ||
|
|
5752a704cc | ||
|
|
6805734db4 | ||
|
|
ef4dd69a8d | ||
|
|
23338803f9 | ||
|
|
cf2dd2c997 | ||
|
|
a0025d0df9 | ||
|
|
5df7d88d78 | ||
|
|
4be3342175 | ||
|
|
6deb7b700c | ||
|
|
80af6c8616 | ||
|
|
0cf6d56e61 | ||
|
|
a1eeb98175 | ||
|
|
1c9e93f917 | ||
|
|
221a498a1f | ||
|
|
25683917bb | ||
|
|
d4c49a85af | ||
|
|
09f5a72ffe | ||
|
|
290845ef8c | ||
|
|
001e0886b4 | ||
|
|
4dc135ac95 | ||
|
|
d1d4d7131d | ||
|
|
7d87d7cf49 | ||
|
|
c712c35cb5 | ||
|
|
78d29c9b06 | ||
|
|
afcb2b472d | ||
|
|
1b833d29fd | ||
|
|
a31dd8bd70 | ||
|
|
34a15cbab6 | ||
|
|
b261643a8f | ||
|
|
ac2552fbbb | ||
|
|
53813b94d7 | ||
|
|
bb397f792f | ||
|
|
7be52702e4 | ||
|
|
c92e8c993f | ||
|
|
716fc312d3 | ||
|
|
1d1951136a | ||
|
|
a249c0bc37 | ||
|
|
aa72eb83ae | ||
|
|
6a0b46e54d | ||
|
|
2882692b71 | ||
|
|
619202e3d4 | ||
|
|
ab604f2972 | ||
|
|
63a3b4b3f5 | ||
|
|
2cf1486f76 | ||
|
|
c1cdce9698 | ||
|
|
b853f9d0e0 | ||
|
|
5dab3610bf | ||
|
|
405ed53baa | ||
|
|
d91bbcd489 | ||
|
|
9ffc1851ea | ||
|
|
f481cad337 | ||
|
|
6db1495263 | ||
|
|
6ccadee046 | ||
|
|
e094c38bfe | ||
|
|
eefd754357 | ||
|
|
fe8642dad5 | ||
|
|
7925599ed3 | ||
|
|
4fb45165d5 | ||
|
|
c42d411cab | ||
|
|
816a1c11bb | ||
|
|
f47eafd36f | ||
|
|
004848ae9d | ||
|
|
af760c29fc | ||
|
|
deac5cbcc7 | ||
|
|
00100b1cb5 | ||
|
|
94496eb579 | ||
|
|
e878691190 | ||
|
|
29bbf6faf0 | ||
|
|
7e13d9bec5 | ||
|
|
0fb1063d1a | ||
|
|
e883cdfffc | ||
|
|
6a01238f67 | ||
|
|
6ca8939993 | ||
|
|
302a994654 | ||
|
|
31622ad3b3 | ||
|
|
534e679ef3 | ||
|
|
b607af0849 | ||
|
|
344dba38df | ||
|
|
73d13e8019 | ||
|
|
d4def48591 | ||
|
|
595f302e3d | ||
|
|
e5c181bdc3 | ||
|
|
8e950e8c1c | ||
|
|
54b141c724 | ||
|
|
880119e76b | ||
|
|
8d52a03f0a | ||
|
|
ba06b99e2c | ||
|
|
b8997a1efd | ||
|
|
caf4284014 | ||
|
|
46af3b4c07 | ||
|
|
1a2a9c8132 | ||
|
|
dcb843bf9a | ||
|
|
86ff88a113 | ||
|
|
a1d8face34 | ||
|
|
188ad3f074 | ||
|
|
71c506a4fd | ||
|
|
9b5ecc0530 | ||
|
|
3fcdf9d593 | ||
|
|
84330bf3d1 | ||
|
|
c5ac891d2a | ||
|
|
fc64d930f2 | ||
|
|
6024bf019c | ||
|
|
3b4a578689 | ||
|
|
464902f886 | ||
|
|
c172fe43ee | ||
|
|
6007bccaaf | ||
|
|
187e9508a9 | ||
|
|
8aa3342e6f | ||
|
|
bd318208f9 | ||
|
|
a288c15e57 | ||
|
|
cd2cd950d0 | ||
|
|
4a509927d7 | ||
|
|
980291218d | ||
|
|
b1c644f9a4 | ||
|
|
d1798f1051 | ||
|
|
5e57ffccdb | ||
|
|
cbbb11be4e | ||
|
|
a207b5c02b | ||
|
|
39df704f51 | ||
|
|
a03ea880e1 | ||
|
|
74a14bba68 | ||
|
|
2880304fd8 | ||
|
|
068d5536fa | ||
|
|
989f595dfc | ||
|
|
09c57642c6 | ||
|
|
e4192dd585 | ||
|
|
5dc06d13d8 | ||
|
|
c16d05a018 | ||
|
|
0cec8d7d2b | ||
|
|
2410012a5f | ||
|
|
3fe1ef7cb6 | ||
|
|
03b6584bda | ||
|
|
63425f5b66 | ||
|
|
fd0987b26f | ||
|
|
d6314cc476 | ||
|
|
29a24980f1 | ||
|
|
fc43d3cd7f | ||
|
|
6324f9481f | ||
|
|
10fc583f40 | ||
|
|
9e6c8a0595 | ||
|
|
53d7fc7e22 | ||
|
|
01a9255def | ||
|
|
5ce94838a4 | ||
|
|
8f112be58c | ||
|
|
0f3497726f | ||
|
|
d68fbb3acb | ||
|
|
35a5df38a1 | ||
|
|
000dfe1bf4 | ||
|
|
e423bc34f8 | ||
|
|
51cecaf448 | ||
|
|
4a1327283b | ||
|
|
1b28389c80 | ||
|
|
77cb69f88e | ||
|
|
89e9200331 | ||
|
|
16044dbcb6 | ||
|
|
291384d1f0 | ||
|
|
5fd75e0d06 | ||
|
|
c6b0b2b722 | ||
|
|
62861cc74f | ||
|
|
b817282924 | ||
|
|
372d529bee | ||
|
|
9df336d051 | ||
|
|
cdea683a7a | ||
|
|
662bf17c92 | ||
|
|
1f733b9849 | ||
|
|
20cfb42399 | ||
|
|
3a0a96909a | ||
|
|
173227ae9f | ||
|
|
4aa67506aa | ||
|
|
2ec9fdb178 | ||
|
|
0b7bf918c4 | ||
|
|
537ba4172e | ||
|
|
f03e6d8caa | ||
|
|
724958737d | ||
|
|
74be2dcce5 | ||
|
|
f6aab536e0 | ||
|
|
9f50306f2a | ||
|
|
cd4d764632 | ||
|
|
cffae16871 | ||
|
|
4a6700f2ce | ||
|
|
de50ba7164 | ||
|
|
39ba5b866d | ||
|
|
6bcd9acf05 | ||
|
|
e0984e2a85 | ||
|
|
eaabfa7929 | ||
|
|
d6eeaf1ec6 | ||
|
|
0988835652 | ||
|
|
217597420a | ||
|
|
b5954d603f | ||
|
|
7c3f18ddca | ||
|
|
4fa5aa7299 | ||
|
|
2fb8287acc | ||
|
|
55a42c7e80 | ||
|
|
4e343c1da5 | ||
|
|
313fde9879 | ||
|
|
4cfabbecc1 | ||
|
|
e5fcbc4b3f | ||
|
|
154e62921d | ||
|
|
d4f9a2045c | ||
|
|
7ed9dbd34d | ||
|
|
2451a779ab | ||
|
|
2603f2402e | ||
|
|
3c16a1bdb0 | ||
|
|
40ed53ef8e | ||
|
|
aee56f5892 | ||
|
|
dbb6df1814 | ||
|
|
b1493c27c0 | ||
|
|
f256171055 | ||
|
|
a44015ae4c | ||
|
|
205f2239bd | ||
|
|
0d27f8749c | ||
|
|
70a8ab70a8 | ||
|
|
fd615bf20a | ||
|
|
65841e8440 | ||
|
|
ed3ce1e618 | ||
|
|
bb24220a1e | ||
|
|
9e09a6d1da | ||
|
|
24232c6736 | ||
|
|
e2b74d79f6 | ||
|
|
a8f48df215 | ||
|
|
61e610b3b9 | ||
|
|
3fd17081b2 | ||
|
|
5faa6f367a | ||
|
|
a1093dd15a | ||
|
|
7764892c86 | ||
|
|
825e19b83e | ||
|
|
23c85cf032 | ||
|
|
ae8f28abac | ||
|
|
7821f9829f | ||
|
|
10e8b58506 | ||
|
|
67fc1c91b5 | ||
|
|
66f8f30c21 | ||
|
|
3a3785d27b | ||
|
|
670ec10011 | ||
|
|
b85167704d | ||
|
|
bc96b28870 | ||
|
|
f39c331ddc | ||
|
|
f14bfd4ad3 | ||
|
|
46a91cc4f6 | ||
|
|
e46b627347 | ||
|
|
21fb561ea5 | ||
|
|
4b278779ac | ||
|
|
abe04bc24e | ||
|
|
9861c417ad | ||
|
|
c5f27d495f | ||
|
|
24c5e69d8a | ||
|
|
896af8a312 | ||
|
|
e8756d9d9d | ||
|
|
b105525834 | ||
|
|
424134263f | ||
|
|
8b984479e9 | ||
|
|
62ca675b3a | ||
|
|
33fb74e083 | ||
|
|
b28aa417be | ||
|
|
012408eb2a | ||
|
|
e98c0e38bc | ||
|
|
688b9ad95d | ||
|
|
3716a0a51b | ||
|
|
7420aa6065 | ||
|
|
2c3b5838c6 | ||
|
|
a5466e05c6 | ||
|
|
76d8b61867 | ||
|
|
8ab526f2e9 | ||
|
|
0ef2052fb9 | ||
|
|
1dd41ef5d0 | ||
|
|
dcc33cebdf | ||
|
|
474b137abb | ||
|
|
e8307b280e | ||
|
|
268b6c48ad | ||
|
|
e12e36044e | ||
|
|
e8deecc58f | ||
|
|
93cd63aca9 | ||
|
|
1ab2ce5948 | ||
|
|
c20874b131 | ||
|
|
015a176b08 | ||
|
|
983593ef44 | ||
|
|
66772671c1 | ||
|
|
b1a7b8bc57 | ||
|
|
026adec1ea |
@@ -1,31 +1,69 @@
|
||||
;; -*- comment-column: 100; -*-
|
||||
{:config-paths ["macros" "src"]
|
||||
:linters
|
||||
{:aliased-namespace-symbol {:level :warning}
|
||||
:invalid-arity {:skip-args [metabase.lib.util.match/match]} ; TODO (cam): can we fix these?
|
||||
{
|
||||
;;
|
||||
;; enabled optional linters (these are disabled by default)
|
||||
;;
|
||||
|
||||
:aliased-namespace-symbol {:level :warning}
|
||||
:case-symbol-test {:level :warning}
|
||||
:condition-always-true {:level :warning}
|
||||
:def-fn {:level :warning}
|
||||
:dynamic-var-not-earmuffed {:level :warning}
|
||||
:equals-expected-position {:level :warning, :only-in-test-assertion true}
|
||||
:keyword-binding {:level :warning}
|
||||
:main-without-gen-class {:level :warning}
|
||||
:minus-one {:level :warning}
|
||||
:misplaced-docstring {:level :warning}
|
||||
:missing-body-in-when {:level :warning}
|
||||
:missing-docstring {:level :warning}
|
||||
:missing-else-branch {:level :warning}
|
||||
:namespace-name-mismatch {:level :warning}
|
||||
:non-arg-vec-return-type-hint {:level :warning}
|
||||
:plus-one {:level :warning}
|
||||
:reduce-without-init {:level :warning}
|
||||
:redundant-call {:level :warning}
|
||||
:redundant-fn-wrapper {:level :warning}
|
||||
:refer-all {:level :warning, :exclude [clojure.test]}
|
||||
:self-requiring-namespace {:level :warning}
|
||||
:single-key-in {:level :warning}
|
||||
:unsorted-imports {:level :warning}
|
||||
:unsorted-required-namespaces {:level :warning}
|
||||
:unused-referred-var {:exclude {compojure.core [GET DELETE POST PUT]}}
|
||||
:unused-alias {:level :warning}
|
||||
:use {:level :warning}
|
||||
:warn-on-reflection {:level :warning}
|
||||
|
||||
;;
|
||||
;; other disabled-by-default linters it would be nice to enable soon
|
||||
;;
|
||||
|
||||
;; TODO (cam): most of these either have a ton of things that need to be fixed or cause issues
|
||||
;; with [[metabase.lib.util.match/match]] and friends -- we need to write a custom hook for those macros so Kondo
|
||||
;; can understand them.
|
||||
|
||||
#_:docstring-leading-trailing-whitespace
|
||||
#_:equals-false
|
||||
#_:equals-true
|
||||
#_:used-underscored-binding
|
||||
|
||||
;;
|
||||
;; disabled linters
|
||||
;;
|
||||
|
||||
: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?
|
||||
|
||||
;;
|
||||
;; globally-enabled custom linters
|
||||
;;
|
||||
:metabase/defsetting-must-specify-export {:level :warning}
|
||||
:metabase/mbql-query-first-arg {:level :warning}
|
||||
:metabase/missing-test-expr-requires-in-cljs {:level :warning}
|
||||
:metabase/require-shape-checker {:level :warning}
|
||||
:metabase/test-helpers-use-non-thread-safe-functions {:level :warning}
|
||||
:metabase/validate-logging {:level :warning}
|
||||
:metabase/validate-mb-driver-tests {:level :warning}
|
||||
:metabase/validate-mb-once {:level :warning}
|
||||
|
||||
:metabase/validate-deftest
|
||||
{:level :warning
|
||||
@@ -127,8 +165,12 @@
|
||||
clojure.core.async/to-chan!!
|
||||
metabase.channel.core/send!
|
||||
metabase.driver.sql-jdbc.execute/execute-prepared-statement!
|
||||
metabase.pulse/send-pulse!
|
||||
metabase.models.notification/create-notification!
|
||||
metabase.pulse.send/send-pulse!
|
||||
metabase.query-processor.store/store-database!
|
||||
;; Safe in tests, where we typically use a private, temporary index per thread.
|
||||
metabase.search.core/reindex!
|
||||
metabase.util/run-count!
|
||||
next.jdbc/execute!}}
|
||||
|
||||
:metabase/i-like-making-cams-eyes-bleed-with-horrifically-long-tests
|
||||
@@ -150,6 +192,7 @@
|
||||
:druid
|
||||
:druid-jdbc
|
||||
:googleanalytics
|
||||
:hive-like
|
||||
:mongo
|
||||
:oracle
|
||||
:presto-jdbc
|
||||
@@ -161,20 +204,12 @@
|
||||
:vertica}}
|
||||
|
||||
;;
|
||||
;; disabled linters
|
||||
;; misc config for built-in linters
|
||||
;;
|
||||
|
||||
:unexpected-recur {:level :off} ; TODO (cam): I think we just need to tell it how to handle MBQL match and we can enable this?
|
||||
:used-underscored-binding {:level :off} ; false positives: see https://github.com/clj-kondo/clj-kondo/issues/2152
|
||||
|
||||
;;
|
||||
;; TODO (cam): here are some more linters we should experiment with enabling -- some might be useful.
|
||||
;;
|
||||
|
||||
;; :docstring-leading-trailing-whitespace {:level :warning}
|
||||
;; :docstring-no-summary {:level :warning}
|
||||
;; :shadowed-var {:level :warning}
|
||||
;; :def-fn {:level :warning}
|
||||
: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]}}
|
||||
|
||||
:unresolved-symbol
|
||||
{:exclude
|
||||
@@ -244,6 +279,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."}
|
||||
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+."}
|
||||
@@ -294,7 +330,9 @@
|
||||
metabase.audit #{metabase.audit}
|
||||
metabase.bootstrap #{metabase.bootstrap}
|
||||
metabase.cmd #{} ; there are no namespaces here since you shouldn't be using this in any other module.
|
||||
metabase.channel #{metabase.channel.core}
|
||||
metabase.channel #{metabase.channel.core
|
||||
metabase.channel.render.core
|
||||
metabase.channel.template.core}
|
||||
metabase.config #{metabase.config}
|
||||
metabase.core #{metabase.core.initialization-status} ; TODO -- only namespace used outside of EE, this probably belongs in `metabase.server` anyway since that's the only place it's used.
|
||||
metabase.db #{metabase.db
|
||||
@@ -303,7 +341,8 @@
|
||||
metabase.db.setup} ; TODO these are only calling `metabase.db.setup/setup-db!` and there's a slightly different version in `metabase.db`
|
||||
metabase.driver :any ; TODO -- 19 namespaces!!!! CRY
|
||||
metabase.email #{metabase.email
|
||||
metabase.email.messages} ; TODO -- consolidate these into a real API namespace.
|
||||
metabase.email.messages
|
||||
metabase.email.result-attachment} ; TODO -- consolidate these into a real API namespace.
|
||||
metabase.embed #{metabase.embed.settings}
|
||||
metabase.events #{metabase.events}
|
||||
metabase.formatter #{metabase.formatter}
|
||||
@@ -321,47 +360,38 @@
|
||||
metabase.metabot #{metabase.metabot}
|
||||
metabase.models :any ; TODO -- scream, 62 namespaces used elsewhere, but to be fair a lot of these don't *need* to be required.
|
||||
metabase.moderation #{metabase.moderation}
|
||||
metabase.notification #{metabase.notification.core
|
||||
metabase.notification.payload.core}
|
||||
metabase.permissions #{metabase.permissions.util} ; TODO -- this is currently the only namespace in this module. Give it a real API namespace?
|
||||
metabase.plugins #{metabase.plugins
|
||||
metabase.plugins.classloader} ; TODO -- not 100% sure the classloader belongs here
|
||||
metabase.public-settings #{metabase.public-settings
|
||||
metabase.public-settings.premium-features}
|
||||
metabase.pulse #{metabase.pulse
|
||||
metabase.pulse.markdown
|
||||
metabase.pulse.parameters
|
||||
metabase.pulse.preview
|
||||
metabase.pulse.render
|
||||
metabase.pulse.render.image-bundle
|
||||
metabase.pulse.render.js-svg
|
||||
metabase.pulse.render.style} ; TODO -- consolidate these into a real API namespace.
|
||||
metabase.pulse #{metabase.pulse.core}
|
||||
metabase.query-processor :any ; TODO omg scream, 29 namespaces used outside of the module. WHAT THE HECC
|
||||
metabase.query-analysis #{metabase.query-analysis
|
||||
metabase.query-analysis.failure-map}
|
||||
metabase.related #{metabase.related}
|
||||
metabase.request #{metabase.request.core}
|
||||
metabase.sample-data #{metabase.sample-data}
|
||||
metabase.search #{metabase.search}
|
||||
metabase.server #{metabase.server
|
||||
metabase.server.handler
|
||||
metabase.server.middleware.auth
|
||||
metabase.server.middleware.exceptions
|
||||
metabase.search #{metabase.search.core
|
||||
;; Need to expose this submodule, to break circular dependencies with models.
|
||||
metabase.search.spec}
|
||||
metabase.server #{metabase.server.core
|
||||
;;
|
||||
;; TODO FIXME -- this is loaded for side effects since it contains the JSON
|
||||
;; encoder logic for stuff like `java.time` classes. As a
|
||||
;; result, [[metabase.models.setting]] (and thus the `metabase.models` module)
|
||||
;; has to depend on the `metabase.server` module...we should create either a new
|
||||
;; `metabase.json` or `metabase.encoders` module for stuff like this to live. Or
|
||||
;; maybe it just belongs in a generic `metabase.config` module.
|
||||
metabase.server.middleware.json
|
||||
metabase.server.middleware.misc
|
||||
metabase.server.middleware.offset-paging
|
||||
metabase.server.middleware.session
|
||||
metabase.server.protocols
|
||||
metabase.server.request.util} ; TODO -- consolidate these into a real API namespace.
|
||||
;;
|
||||
;; TODO -- we can't make this part of [[metabase.server.core]] YET because it
|
||||
;; causes circular dependencies. Maybe in the future once we tease apart more of
|
||||
;; the modules tangle we can.
|
||||
metabase.server.protocols}
|
||||
metabase.setup #{metabase.setup}
|
||||
metabase.shared #{metabase.shared.dashboards.constants
|
||||
metabase.shared.formatting.constants
|
||||
metabase.shared.formatting.date
|
||||
metabase.shared.formatting.numbers
|
||||
metabase.shared.models.visualization-settings
|
||||
metabase.shared.parameters.parameters
|
||||
metabase.shared.util.currency
|
||||
metabase.shared.util.i18n
|
||||
metabase.shared.util.internal.time-common
|
||||
metabase.shared.util.namespaces
|
||||
metabase.shared.util.time} ; TODO -- consolidate these into a real API namespace.
|
||||
metabase.sync #{metabase.sync
|
||||
metabase.sync.analyze
|
||||
metabase.sync.concurrent
|
||||
@@ -399,7 +429,7 @@
|
||||
metabase.api :any
|
||||
metabase.async :any
|
||||
metabase.audit :any
|
||||
metabase.auth-provider #{metabase.util}
|
||||
metabase.auth-provider #{metabase.util metabase.public-settings}
|
||||
metabase.bootstrap #{}
|
||||
metabase.cmd :any
|
||||
metabase.compatibility :any
|
||||
@@ -420,6 +450,7 @@
|
||||
metabase.metabot :any
|
||||
metabase.models :any
|
||||
metabase.moderation :any
|
||||
metabase.notification :any
|
||||
metabase.permissions :any
|
||||
metabase.plugins :any
|
||||
metabase.public-settings :any
|
||||
@@ -434,17 +465,20 @@
|
||||
metabase.util}
|
||||
metabase.query-processor :any
|
||||
metabase.related :any
|
||||
metabase.request #{metabase.config
|
||||
metabase.models
|
||||
metabase.public-settings
|
||||
metabase.util}
|
||||
metabase.sample-data :any
|
||||
metabase.search :any
|
||||
metabase.server :any
|
||||
metabase.setup :any
|
||||
metabase.shared :any
|
||||
metabase.sync :any
|
||||
metabase.task :any
|
||||
metabase.troubleshooting :any
|
||||
metabase.types #{metabase.util}
|
||||
metabase.upload :any
|
||||
metabase.util :any
|
||||
metabase.util :any ; TODO -- this should probably be #{}
|
||||
metabase.xrays :any}
|
||||
|
||||
;; namespaces matching these patterns (with `re-find`) are excluded from the module linter. Since regex literals
|
||||
@@ -482,7 +516,6 @@
|
||||
clojure.tools.namespace.parse ns.parse
|
||||
colorize.core colorize
|
||||
environ.core env
|
||||
hf.depstar.api depstar
|
||||
hiccup.core hiccup
|
||||
hiccup.util hiccup.util
|
||||
honey.sql sql
|
||||
@@ -502,6 +535,8 @@
|
||||
metabase-enterprise.test met
|
||||
metabase.analytics.sdk sdk
|
||||
metabase.analytics.stats stats
|
||||
metabase.analysis.native-query-analyzer nqa
|
||||
metabase.analysis.native-query-analyzer.parameter-substitution nqa.sub
|
||||
metabase.analyze.query-results qr
|
||||
metabase.analyze.classifiers.category classifiers.category
|
||||
metabase.analyze.classifiers.core classifiers
|
||||
@@ -556,6 +591,7 @@
|
||||
metabase.api.util api.util
|
||||
metabase.async.streaming-response.thread-pool thread-pool
|
||||
metabase.channel.core channel
|
||||
metabase.channel.render.core channel.render
|
||||
metabase.cmd.copy.h2 copy.h2
|
||||
metabase.config config
|
||||
metabase.config.file config.file
|
||||
@@ -595,6 +631,7 @@
|
||||
metabase.driver.sql-jdbc.test-util sql-jdbc.tu
|
||||
metabase.driver.sql.parameters.substitute sql.params.substitute
|
||||
metabase.driver.sql.parameters.substitution sql.params.substitution
|
||||
metabase.eid-translation eid-translation
|
||||
metabase.email-test et
|
||||
metabase.email.messages messages
|
||||
metabase.formatter formatter
|
||||
@@ -618,26 +655,26 @@
|
||||
metabase.models.interface mi
|
||||
metabase.models.moderation-review moderation-review
|
||||
metabase.models.native-query-snippet native-query-snippet
|
||||
metabase.models.notification models.notification
|
||||
metabase.models.params params
|
||||
metabase.models.permissions perms
|
||||
metabase.models.permissions-group perms-group
|
||||
metabase.models.permissions-group-membership perms-group-membership
|
||||
metabase.models.permissions-revision perms-revision
|
||||
metabase.models.permissions.parse perms-parse
|
||||
metabase.models.pulse pulse
|
||||
metabase.models.pulse models.pulse
|
||||
metabase.models.pulse-channel pulse-channel
|
||||
metabase.models.pulse-channel-recipient pulse-channel-recipient
|
||||
metabase.models.query.permissions query-perms
|
||||
metabase.models.setting.cache setting.cache
|
||||
metabase.models.timeline timeline
|
||||
metabase.models.timeline-event timeline-event
|
||||
metabase.analysis.native-query-analyzer nqa
|
||||
metabase.analysis.native-query-analyzer.parameter-substitution nqa.sub
|
||||
metabase.notification.core notification
|
||||
metabase.notification.test-util notification.tu
|
||||
metabase.plugins.initialize plugins.init
|
||||
metabase.public-settings public-settings
|
||||
metabase.public-settings.premium-features premium-features
|
||||
metabase.pulse pulse ; NB some conflicts with metabase.models.pulse
|
||||
metabase.pulse.markdown markdown
|
||||
metabase.pulse.core pulse
|
||||
metabase.pulse.render render
|
||||
metabase.pulse.render.body body
|
||||
metabase.pulse.render.style style
|
||||
@@ -668,26 +705,16 @@
|
||||
metabase.query-processor.timezone qp.timezone
|
||||
metabase.query-processor.util qp.util
|
||||
metabase.related related
|
||||
metabase.request.core request
|
||||
metabase.search.config search.config
|
||||
metabase.search.filter search.filter
|
||||
metabase.search.util search.util
|
||||
metabase.search.scoring scoring
|
||||
metabase.server.middleware.auth mw.auth
|
||||
metabase.server.middleware.browser-cookie mw.browser-cookie
|
||||
metabase.server.middleware.exceptions mw.exceptions
|
||||
metabase.server.middleware.json mw.json
|
||||
metabase.server.middleware.log mw.log
|
||||
metabase.server.middleware.misc mw.misc
|
||||
metabase.server.middleware.offset-paging mw.offset-paging
|
||||
metabase.server.middleware.security mw.security
|
||||
metabase.server.middleware.session mw.session
|
||||
metabase.server.middleware.ssl mw.ssl
|
||||
metabase.server.request.util req.util
|
||||
metabase.search.in-place.filter search.in-place.filter
|
||||
metabase.search.in-place.util search.util
|
||||
metabase.search.in-place.scoring scoring
|
||||
metabase.server.core server
|
||||
metabase.server.protocols server.protocols
|
||||
metabase.shared.util shared.u
|
||||
metabase.shared.util.currency currency
|
||||
metabase.sync.analyze.fingerprint sync.fingerprint
|
||||
metabase.sync.field-values field-values
|
||||
metabase.sync.field-values sync.field-values
|
||||
metabase.sync.interface i
|
||||
metabase.sync.schedules sync.schedules
|
||||
metabase.sync.sync-metadata.fields.our-metadata fields.our-metadata
|
||||
@@ -707,6 +734,7 @@
|
||||
metabase.test.util.timezone test.tz
|
||||
metabase.timeseries-query-processor-test.util tqpt
|
||||
metabase.util.cron u.cron
|
||||
metabase.util.currency currency
|
||||
metabase.util.date-2 u.date
|
||||
metabase.util.date-2.common u.date.common
|
||||
metabase.util.date-2.parse u.date.parse
|
||||
@@ -723,6 +751,7 @@
|
||||
metabase.util.macros u.macros
|
||||
metabase.util.malli mu
|
||||
metabase.util.malli.schema ms
|
||||
metabase.util.markdown markdown
|
||||
metabase.util.password u.password
|
||||
metabase.util.schema su
|
||||
metabase.util.ui-logic ui-logic
|
||||
@@ -754,8 +783,8 @@
|
||||
metabase.api.search-test/do-test-users clojure.core/let
|
||||
metabase.async.api-response-test/with-response clojure.core/let
|
||||
metabase.dashboard-subscription-test/with-dashboard-sub-for-card clojure.core/let
|
||||
metabase.channel.http-test/with-captured-http-requests clojure.core/fn
|
||||
metabase.channel.http-test/with-server clojure.core/let
|
||||
metabase.channel.impl.http-test/with-captured-http-requests clojure.core/fn
|
||||
metabase.channel.impl.http-test/with-server clojure.core/let
|
||||
metabase.db.custom-migrations/define-migration clj-kondo.lint-as/def-catch-all
|
||||
metabase.db.custom-migrations/define-reversible-migration clj-kondo.lint-as/def-catch-all
|
||||
metabase.db.data-migrations/defmigration clojure.core/def
|
||||
@@ -774,14 +803,13 @@
|
||||
metabase.models.setting/defsetting clj-kondo.lint-as/def-catch-all
|
||||
metabase.public-settings.premium-features/defenterprise-schema clj-kondo.lint-as/def-catch-all
|
||||
metabase.public-settings.premium-features/define-premium-feature clojure.core/def
|
||||
metabase.pulse-test/with-pulse-for-card clojure.core/let
|
||||
metabase.pulse.send-test/with-pulse-for-card clojure.core/let
|
||||
metabase.query-processor-test.pipeline-queries-test/pmbql-query clojure.core/->
|
||||
metabase.query-processor-test.pipeline-queries-test/run-pmbql-query clojure.core/->
|
||||
metabase.query-processor.error-type/deferror clojure.core/def
|
||||
metabase.query-processor.middleware.cache.impl/with-reducible-deserialized-results clojure.core/let
|
||||
metabase.query-processor.middleware.process-userland-query-test/with-query-execution! clojure.core/let
|
||||
metabase.query-processor.setup/with-qp-setup clojure.core/let
|
||||
metabase.shared.util.namespaces/import-fns potemkin/import-vars
|
||||
metabase.sync.util/sum-for clojure.core/for
|
||||
metabase.sync.util/with-emoji-progress-bar clojure.core/let
|
||||
metabase.test.data.interface/defdataset clojure.core/def
|
||||
@@ -805,8 +833,11 @@
|
||||
metabase.util.malli/defn schema.core/defn
|
||||
metabase.util.malli/defn- schema.core/defn
|
||||
metabase.util.malli/fn schema.core/fn
|
||||
metabase.util.namespaces/import-fns potemkin/import-vars
|
||||
metabase.util.ssh/with-ssh-tunnel clojure.core/let
|
||||
metabase.xrays.domain-entities.malli/defn schema.core/defn
|
||||
metabuild-common.core/with-open-jar-file-system clojure.core/let
|
||||
metabuild-common.files/with-open-jar-file-system clojure.core/let
|
||||
monger.operators/defoperator clojure.core/def
|
||||
potemkin.types/defprotocol+ clojure.core/defprotocol
|
||||
potemkin.types/defrecord+ clojure.core/defrecord
|
||||
@@ -857,9 +888,12 @@
|
||||
metabase.api.search-test/with-search-items-in-root-collection hooks.common/do*
|
||||
metabase.api.user-test/with-temp-user-email hooks.common/with-one-binding
|
||||
metabase.async.streaming-response-test/with-start-execution-chan hooks.common/with-one-binding
|
||||
metabase.channel.template.handlebars-test/with-temp-template! hooks.common/with-vec-first-binding
|
||||
metabase.channel.template.handlebars-helper/defhelper hooks.metabase.channel.template.handlebars-helper/defhelper
|
||||
metabase.dashboard-subscription-test/with-link-card-fixture-for-dashboard hooks.common/let-second
|
||||
metabase.db.schema-migrations-test.impl/test-migrations hooks.metabase.db.schema-migrations-test.impl/test-migrations
|
||||
metabase.driver.bigquery-cloud-sdk-test/calculate-bird-scarcity hooks.metabase.query-processor-test.expressions-test/calculate-bird-scarcity
|
||||
metabase.driver.oracle-test/with-temp-user hooks.common/let-one-with-optional-value
|
||||
metabase.driver/register! hooks.metabase.driver/register!
|
||||
metabase.legacy-mbql.schema.macros/defclause hooks.metabase.legacy-mbql.schemas.macros/defclause
|
||||
metabase.lib.schema.mbql-clause/define-catn-mbql-clause hooks.metabase.lib.schema.mbql-clause/define-mbql-clause
|
||||
@@ -883,8 +917,13 @@
|
||||
metabase.query-processor-test.expressions-test/calculate-bird-scarcity hooks.metabase.query-processor-test.expressions-test/calculate-bird-scarcity
|
||||
metabase.query-processor-test.filter-test/count-with-filter-clause hooks.metabase.test.data/$ids
|
||||
metabase.query-processor.middleware.cache-test/with-mock-cache! hooks.common/with-two-bindings
|
||||
metabase.request.core/with-current-request hooks.common/with-used-first-arg
|
||||
metabase.request.core/with-current-user hooks.common/with-used-first-arg
|
||||
metabase.request.core/with-limit-and-offset hooks.common/with-used-first-two-args
|
||||
metabase.sample-data-test/with-temp-sample-database-db hooks.common/with-one-binding
|
||||
metabase.stale-test/with-stale-items hooks.toucan2.tools.with-temp/with-temp
|
||||
metabase.test.data.datasets/test-driver hooks.metabase.test.data.datasets/test-driver
|
||||
metabase.test.data.datasets/test-drivers hooks.metabase.test.data.datasets/test-drivers
|
||||
metabase.test.data.users/with-group hooks.common/let-one-with-optional-value
|
||||
metabase.test.data/$ids hooks.metabase.test.data/$ids
|
||||
metabase.test.data/dataset hooks.metabase.test.data/dataset
|
||||
@@ -903,7 +942,8 @@
|
||||
metabase.test/mbql-query hooks.metabase.test.data/mbql-query
|
||||
metabase.test/query hooks.metabase.test.data/mbql-query
|
||||
metabase.test/run-mbql-query hooks.metabase.test.data/mbql-query
|
||||
metabase.test/test-drivers hooks.common/do*
|
||||
metabase.test/test-driver hooks.metabase.test.data.datasets/test-driver
|
||||
metabase.test/test-drivers hooks.metabase.test.data.datasets/test-drivers
|
||||
metabase.test/with-column-remappings hooks.common/with-ignored-first-arg
|
||||
metabase.test/with-group hooks.common/let-one-with-optional-value
|
||||
metabase.test/with-log-level hooks.common/with-ignored-first-arg
|
||||
@@ -926,6 +966,7 @@
|
||||
metabase.util.log/warn hooks.metabase.util.log/info
|
||||
metabase.util.log/warnf hooks.metabase.util.log/infof
|
||||
metabase.util.malli.registry/def hooks.metabase.util.malli.registry/def
|
||||
metabase.util/case-enum hooks.metabase.util/case-enum
|
||||
metabase.util/format-color hooks.metabase.util/format-color}
|
||||
|
||||
:macroexpand
|
||||
@@ -956,7 +997,6 @@
|
||||
metabase.models.user-test/with-groups macros.metabase.models.user-test/with-groups
|
||||
metabase.query-processor.streaming/streaming-response macros.metabase.query-processor.streaming/streaming-response
|
||||
metabase.related-test/with-world macros.metabase.related-test/with-world
|
||||
metabase.shared.util.namespaces/import-fn macros.metabase.shared.util.namespaces/import-fn
|
||||
metabase.task.setup.query-analysis-setup/with-test-setup! macros.metabase.task.setup.query-analysis-setup/with-test-setup!
|
||||
metabase.test.data.users/with-group-for-user macros.metabase.test.data.users/with-group-for-user
|
||||
metabase.test.util/with-temp-env-var-value! macros.metabase.test.util/with-temp-env-var-value!
|
||||
@@ -965,6 +1005,7 @@
|
||||
metabase.test/with-persistence-enabled! macros.metabase.test.persistence/with-persistence-enabled!
|
||||
metabase.test/with-temp-env-var-value! macros.metabase.test.util/with-temp-env-var-value!
|
||||
metabase.test/with-temporary-raw-setting-values macros.metabase.test.util/with-temporary-raw-setting-values
|
||||
metabase.util.namespaces/import-fn macros.metabase.util.namespaces/import-fn
|
||||
metabase.xrays.domain-entities.malli/define-getters-and-setters macros.metabase.xrays.domain-entities.malli/define-getters-and-setters}}
|
||||
|
||||
:config-in-comment
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns macros.metabase.shared.util.namespaces)
|
||||
(ns macros.metabase.util.namespaces)
|
||||
|
||||
(defmacro import-fn
|
||||
"Kondo macro replacement for [[metabase.shared.util.namespaces/import-fn]]."
|
||||
"Kondo macro replacement for [[metabase.util.namespaces/import-fn]]."
|
||||
([sym]
|
||||
`(def ~(-> sym name symbol) "docstring" ~sym))
|
||||
([sym name]
|
||||
@@ -85,15 +85,14 @@
|
||||
metabase.models.permissions/update-data-perms-graph!
|
||||
metabase.models.permissions/update-group-permissions!
|
||||
metabase.models.persisted-info/ready-database!
|
||||
metabase.models.revision/revert!
|
||||
metabase.models.setting-test/test-user-local-allowed-setting!
|
||||
metabase.models.setting-test/test-user-local-only-setting!
|
||||
metabase.models.setting.cache/restore-cache!
|
||||
metabase.models.setting/set!
|
||||
metabase.models.setting/validate-settings-formatting!
|
||||
metabase.permissions.test-util/with-restored-perms!
|
||||
metabase.pulse/send-notifications!
|
||||
metabase.pulse/send-pulse!
|
||||
metabase.pulse.send/send-notifications!
|
||||
metabase.pulse.send/send-pulse!
|
||||
metabase.query-processor.streaming.interface/begin!
|
||||
metabase.query-processor.streaming.interface/finish!
|
||||
metabase.query-processor.streaming.interface/write-row!
|
||||
@@ -140,6 +139,17 @@
|
||||
[s]
|
||||
(str/ends-with? s "!"))
|
||||
|
||||
(defn- explicitly-safe? [qualified-symbol]
|
||||
(contains? symbols-allowed-in-fns-not-ending-in-an-exclamation-point qualified-symbol))
|
||||
|
||||
(defn- explicitly-unsafe? [config qualified-symbol]
|
||||
(contains? (get-in config [:linters :metabase/validate-deftest :parallel/unsafe]) qualified-symbol))
|
||||
|
||||
(defn- unsafe? [config qualified-symbol]
|
||||
(and (or (end-with-exclamation? qualified-symbol)
|
||||
(explicitly-unsafe? config qualified-symbol))
|
||||
(not (explicitly-safe? qualified-symbol))))
|
||||
|
||||
(defn- non-thread-safe-form-should-end-with-exclamation*
|
||||
[{[defn-or-defmacro form-name] :children, :as node} config]
|
||||
(when-not (and (:string-value form-name)
|
||||
@@ -147,17 +157,16 @@
|
||||
(letfn [(walk [f form]
|
||||
(f form)
|
||||
(doseq [child (:children form)]
|
||||
(walk f child)))]
|
||||
(walk (fn [form]
|
||||
(walk f child)))
|
||||
(check-node [form]
|
||||
(when-let [qualified-symbol (hooks.common/node->qualified-symbol form)]
|
||||
(when (and (not (contains? symbols-allowed-in-fns-not-ending-in-an-exclamation-point qualified-symbol))
|
||||
(or (end-with-exclamation? qualified-symbol)
|
||||
(contains? (get-in config [:linters :metabase/validate-deftest :parallel/unsafe]) qualified-symbol)))
|
||||
(hooks/reg-finding! (assoc (meta form-name)
|
||||
:message (format "The name of this %s should end with `!` because it contains calls to non thread safe form `%s`. [:metabase/test-helpers-use-non-thread-safe-functions]"
|
||||
(:string-value defn-or-defmacro) qualified-symbol)
|
||||
:type :metabase/test-helpers-use-non-thread-safe-functions)))))
|
||||
node))
|
||||
(when (unsafe? config qualified-symbol)
|
||||
(hooks/reg-finding!
|
||||
(assoc (meta form-name)
|
||||
:message (format "The name of this %s should end with `!` because it contains calls to non thread safe form `%s`. [:metabase/test-helpers-use-non-thread-safe-functions]"
|
||||
(:string-value defn-or-defmacro) qualified-symbol)
|
||||
:type :metabase/test-helpers-use-non-thread-safe-functions)))))]
|
||||
(walk check-node node))
|
||||
node))
|
||||
|
||||
(defn non-thread-safe-form-should-end-with-exclamation
|
||||
@@ -172,29 +181,29 @@
|
||||
{:node node})
|
||||
|
||||
(comment
|
||||
(require '[clj-kondo.core :as clj-kondo])
|
||||
(def form (str '(defmacro a
|
||||
[x]
|
||||
`(fun-call x))))
|
||||
(require '[clj-kondo.core :as clj-kondo])
|
||||
(def form (str '(defmacro a
|
||||
[x]
|
||||
`(fun-call x))))
|
||||
|
||||
(def form "(defmacro a
|
||||
(def form "(defmacro a
|
||||
[x]
|
||||
`(some! ~x))")
|
||||
|
||||
(def form "(defun f
|
||||
(def form "(defun f
|
||||
[x]
|
||||
(let [g! (fn [] 1)]
|
||||
(g!)))")
|
||||
|
||||
(str (hooks/parse-string form))
|
||||
(hooks/sexpr (hooks/parse-string form))
|
||||
(str (hooks/parse-string form))
|
||||
(hooks/sexpr (hooks/parse-string form))
|
||||
|
||||
(binding [hooks/*reload* true]
|
||||
(-> form
|
||||
(with-in-str (clj-kondo/run! {:lint ["-"]}))
|
||||
:findings))
|
||||
(binding [hooks/*reload* true]
|
||||
(-> form
|
||||
(with-in-str (clj-kondo/run! {:lint ["-"]}))
|
||||
:findings))
|
||||
|
||||
(do (non-thread-safe-form-should-end-with-exclamation* (hooks/parse-string form)) nil))
|
||||
(do (non-thread-safe-form-should-end-with-exclamation* (hooks/parse-string form)) nil))
|
||||
|
||||
(defn- ns-form-node->require-node [ns-form-node]
|
||||
(some (fn [node]
|
||||
@@ -229,11 +238,12 @@
|
||||
(cond
|
||||
(hooks/vector-node? node)
|
||||
;; propagate the metadata attached to this vector in case there's a `:clj-kondo/ignore` form.
|
||||
(vary-meta (first (:children node)) (partial merge (meta require-node) (meta node)))
|
||||
(let [symbol-node (first (:children node))]
|
||||
(hooks.common/merge-ignored-linters symbol-node require-node node))
|
||||
|
||||
;; this should also be dead code since we require requires to be vectors
|
||||
(hooks/token-node? node)
|
||||
(vary-meta node (partial merge (meta require-node)))
|
||||
(hooks.common/merge-ignored-linters node require-node)
|
||||
|
||||
:else
|
||||
(printf "Don't know how to figure out what namespace is being required in %s\n" (pr-str node)))))
|
||||
@@ -285,8 +295,7 @@
|
||||
ns-form-node->require-node
|
||||
require-node->namespace-symb-nodes)]
|
||||
(doseq [node required-namespace-symb-nodes
|
||||
:let [clj-kondo-ignore (some-> (meta node) :clj-kondo/ignore hooks/sexpr set)]
|
||||
:when (not (contains? clj-kondo-ignore :metabase/ns-module-checker))
|
||||
:when (not (contains? (hooks.common/ignored-linters node) :metabase/ns-module-checker))
|
||||
:let [required-namespace (hooks/sexpr node)
|
||||
required-module (module required-namespace)]
|
||||
;; ignore stuff not in a module i.e. non-Metabase stuff.
|
||||
|
||||
@@ -71,11 +71,7 @@
|
||||
:type :metabase/i-like-making-cams-eyes-bleed-with-horrifically-long-tests)))))))
|
||||
|
||||
(defn- ignore? [node error-type]
|
||||
(when-let [ignores (some-> node meta :clj-kondo/ignore hooks/sexpr)]
|
||||
(when-let [ignores (cond
|
||||
(coll? ignores) (set ignores)
|
||||
(keyword? ignores) #{ignores})]
|
||||
(contains? ignores error-type))))
|
||||
(contains? (hooks.common/ignored-linters node) error-type))
|
||||
|
||||
(defn deftest-check-no-driver-keywords [node {:keys [drivers], :as _config}]
|
||||
;; fail fast after we see the first error, where we see one hardcoded driver name there are likely several more and we
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns hooks.common
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as hooks]
|
||||
[clojure.pprint]))
|
||||
[clojure.pprint]
|
||||
[clojure.set :as set]))
|
||||
|
||||
(defn with-macro-meta
|
||||
"When introducing internal nodes (let, defn, etc) it is important to provide a meta of an existing token
|
||||
@@ -9,10 +10,83 @@
|
||||
[new-node hook-node]
|
||||
(with-meta new-node (meta (first (:children hook-node)))))
|
||||
|
||||
;;; Kondo stores information about ignored linters as rewrite-clj forms matching how they are specified in the code, so
|
||||
;;; either
|
||||
;;;
|
||||
;;; <vector-node [<token-node :discouraged-namespace>]>
|
||||
;;;
|
||||
;;; or
|
||||
;;;
|
||||
;;; <token-node :discouraged-namespace>
|
||||
;;;
|
||||
;;; these are stored in
|
||||
;;;
|
||||
;;; (-> node meta :clj-kondo/ignore :linters).
|
||||
;;;
|
||||
;;; These are not a convenient shape(s) to work with, so the next few functions abstract that shape out and work with a
|
||||
;;; set of keywords like
|
||||
;;;
|
||||
;;; #{:discouraged-namespace}
|
||||
;;;
|
||||
;;; instead.
|
||||
|
||||
(defn- unwrap-ignored-linters [linters]
|
||||
(cond
|
||||
(or (hooks/vector-node? linters)
|
||||
(hooks/list-node? linters))
|
||||
(into #{}
|
||||
(map hooks/sexpr)
|
||||
(:children linters))
|
||||
|
||||
(hooks/keyword-node? linters)
|
||||
#{(hooks/sexpr linters)}
|
||||
|
||||
(and (set? linters)
|
||||
(every? keyword? linters))
|
||||
linters
|
||||
|
||||
(and (sequential? linters)
|
||||
(every? keyword? linters))
|
||||
(into #{} linters)
|
||||
|
||||
(keyword? linters)
|
||||
#{linters}))
|
||||
|
||||
(defn- wrap-ignored-linters [linters]
|
||||
(hooks/vector-node (mapv hooks/keyword-node linters)))
|
||||
|
||||
(defn ignored-linters
|
||||
"Return a set of keywords all ignored linters associated with a node by looking at its metadata."
|
||||
[node]
|
||||
(or (some-> node meta :clj-kondo/ignore :linters unwrap-ignored-linters)
|
||||
;; deal with the old pre-2024.09 shape mentioned in https://github.com/clj-kondo/clj-kondo/issues/2414
|
||||
(some-> node :meta first hooks/sexpr :clj-kondo/ignore unwrap-ignored-linters)))
|
||||
|
||||
(defn update-ignored-linters
|
||||
"Update the `:clj-kondo/ignore` linters in `node`'s metadata. `linters` should be a set of keywords."
|
||||
[node f & args]
|
||||
(letfn [(apply-f [linters]
|
||||
(apply f linters args))
|
||||
(update-linters [linters]
|
||||
(-> (or (unwrap-ignored-linters linters)
|
||||
#{})
|
||||
apply-f
|
||||
wrap-ignored-linters))]
|
||||
(vary-meta node update-in [:clj-kondo/ignore :linters] update-linters)))
|
||||
|
||||
(defn merge-ignored-linters
|
||||
"Merge the ignored linters from `source-nodes` into `node`. You can use this to propagate
|
||||
ignored linters from parent nodes to child nodes."
|
||||
[node & source-nodes]
|
||||
(if-let [linters (not-empty (transduce (map ignored-linters) set/union #{} source-nodes))]
|
||||
(update-ignored-linters node set/union linters)
|
||||
node))
|
||||
|
||||
;;; This stuff is to help debug hooks. Trace a function and it will pretty-print the before & after sexprs.
|
||||
;;;
|
||||
;;; (hooks.common/trace #'calculate-bird-scarcity)
|
||||
|
||||
#_{:clj-kondo/ignore [:discouraged-var]}
|
||||
(defn- trace* [f]
|
||||
{:pre [(fn? f)]}
|
||||
(fn traced-fn [node]
|
||||
@@ -42,13 +116,14 @@
|
||||
;;;; Common hook definitions
|
||||
|
||||
(defn do*
|
||||
"This is the same idea as [[clojure.core/do]] but doesn't cause Kondo to complain about redundant dos or unused values."
|
||||
"This is the same idea as [[clojure.core/do]] but doesn't cause Kondo to complain about redundant dos or unused
|
||||
values."
|
||||
[{{[_ & args] :children, :as node} :node}]
|
||||
(let [node* (-> (hooks/list-node
|
||||
(list*
|
||||
(with-meta (hooks/token-node 'do) {:clj-kondo/ignore [:redundant-do]})
|
||||
(update-ignored-linters (hooks/token-node 'do) conj :redundant-do)
|
||||
(for [arg args]
|
||||
(vary-meta arg update :clj-kondo/ignore #(conj (vec %) :unused-value)))))
|
||||
(update-ignored-linters arg conj :unused-value))))
|
||||
(with-meta (meta node)))]
|
||||
{:node node*}))
|
||||
|
||||
@@ -371,7 +446,51 @@
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn node->qualified-symbol [node]
|
||||
(defn with-used-first-two-args
|
||||
"For macros like
|
||||
|
||||
(with-limit-and-offset limit offset
|
||||
...)
|
||||
|
||||
=>
|
||||
|
||||
(let [_123 limit
|
||||
[_456 offset]
|
||||
...)
|
||||
|
||||
where the first arg should be linted and appear to be used."
|
||||
[{{[_ x y & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node [(hooks/token-node (gensym "_")) x
|
||||
(hooks/token-node (gensym "_")) y])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn with-vec-first-binding
|
||||
"For macros like
|
||||
|
||||
(with-temp-file [binding \"temp.txt\" \"content\"]
|
||||
(slurp binding))
|
||||
|
||||
=>
|
||||
(let [binding nil]
|
||||
(slurp binding))
|
||||
|
||||
where the first arg is a vector of bindings."
|
||||
[{{[_ {[x & _args] :children} & body] :children} :node}]
|
||||
(let [node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[(or x (hooks/token-node '_)) (hooks/token-node 'nil)])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
(defn node->qualified-symbol
|
||||
"If the node is a symbol, return it as a qualified symbol if it's not already. Otherwise return nil."
|
||||
[node]
|
||||
(try
|
||||
(when (hooks/token-node? node)
|
||||
(let [sexpr (hooks/sexpr node)]
|
||||
@@ -381,8 +500,8 @@
|
||||
(and resolved (:ns resolved))
|
||||
(symbol (name (:ns resolved)) (name (:name resolved)))
|
||||
|
||||
;; if it wasn't resolved but is still qualified it's probably using the full namespace name rather than an
|
||||
;; alias.
|
||||
;; if it wasn't resolved but is still qualified it's probably using the full namespace name rather than an
|
||||
;; alias.
|
||||
(qualified-symbol? sexpr)
|
||||
sexpr)))))
|
||||
;; some symbols like `*count/Integer` aren't resolvable.
|
||||
@@ -415,9 +534,4 @@
|
||||
|
||||
metadata to a node to suppress LSP warnings."
|
||||
[node]
|
||||
(letfn [(update-ignores [existing-ignores]
|
||||
(hooks/vector-node
|
||||
(cons
|
||||
(hooks/keyword-node :clojure-lsp/unused-public-var)
|
||||
(:children existing-ignores))))]
|
||||
(vary-meta node update :clj-kondo/ignore update-ignores)))
|
||||
(update-ignored-linters node conj :clojure-lsp/unused-public-var))
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
(ns hooks.metabase.channel.template.handlebars-helper
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as hooks]
|
||||
[hooks.common]))
|
||||
|
||||
(defn defhelper
|
||||
"defhelper hook"
|
||||
[{:keys [node]}]
|
||||
(let [[_ helper-name description argvec & body] (:children node)
|
||||
helper-fn-name (symbol (str (hooks/sexpr helper-name) "*"))]
|
||||
{:node (-> (hooks/list-node
|
||||
(list (hooks/token-node 'do)
|
||||
(hooks/list-node
|
||||
(list (hooks/token-node 'defn)
|
||||
(hooks/token-node helper-fn-name)
|
||||
description
|
||||
argvec
|
||||
(hooks/list-node body)))
|
||||
(hooks/list-node
|
||||
(list (hooks/token-node 'defn)
|
||||
helper-name
|
||||
description
|
||||
argvec
|
||||
(hooks/list-node body)))))
|
||||
(with-meta (meta node)))}))
|
||||
@@ -4,9 +4,9 @@
|
||||
(defn with-testing-against-standard-queries [{{[_ & args] :children} :node}]
|
||||
(let [[query-sym & body] args
|
||||
node* (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[query-sym (hooks/token-node 'nil)])
|
||||
body))]
|
||||
(list*
|
||||
(hooks/token-node 'let)
|
||||
(hooks/vector-node
|
||||
[query-sym (hooks/token-node 'nil)])
|
||||
body))]
|
||||
{:node node*}))
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
database-enable-actions
|
||||
deprecation-notice-version
|
||||
dismissed-custom-dashboard-toast
|
||||
dismissed-onboarding-sidebar-link
|
||||
email-configured?
|
||||
email-from-address
|
||||
email-from-name
|
||||
@@ -161,6 +162,7 @@
|
||||
token-features
|
||||
token-status
|
||||
toucan-name
|
||||
trial-banner-dismissal-timestamp
|
||||
uncached-setting
|
||||
user-visibility
|
||||
version
|
||||
|
||||
58
.clj-kondo/src/hooks/metabase/test/data/datasets.clj
Normal file
@@ -0,0 +1,58 @@
|
||||
(ns hooks.metabase.test.data.datasets
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as hooks]
|
||||
[clojure.set :as set]
|
||||
[hooks.common]))
|
||||
|
||||
(defn- only-core-drivers?
|
||||
"Whether we're for sure only testing against the 'core' drivers that are also app DB types: `:postgres`, `:mysql`, or
|
||||
`:h2`. Tests like these are ok to mark `:mb/once` or `:mb/driver-tests` since we always run the full test suite
|
||||
against app DB drivers anyway."
|
||||
[node]
|
||||
(let [drivers (hooks/sexpr (second (:children node)))
|
||||
drivers (cond
|
||||
(keyword? drivers) #{drivers}
|
||||
(set? drivers) drivers
|
||||
:else nil)]
|
||||
(when drivers
|
||||
(empty? (set/difference drivers #{:h2 :mysql :postgres})))))
|
||||
|
||||
(defn- validate-mb-once [x]
|
||||
(when (:mb/once (meta (:ns x)))
|
||||
(hooks/reg-finding!
|
||||
(assoc (meta (:ns x))
|
||||
:message (str "You should not use test-driver or test-drivers in a namespace marked ^:mb/once"
|
||||
" [:metabase/validate-mb-once]")
|
||||
:type :metabase/validate-mb-once))))
|
||||
|
||||
(defn- validate-mb-driver-tests [x]
|
||||
(when-not (:mb/driver-tests (meta (:ns x)))
|
||||
(hooks/reg-finding!
|
||||
(assoc (meta (:ns x))
|
||||
:message (str "Namespaces that run driver tests (test-driver or test-drivers) should be marked"
|
||||
" ^:mb/driver-tests [:metabase/validate-mb-driver-tests]")
|
||||
:type :metabase/validate-mb-driver-tests))))
|
||||
|
||||
(defn- validate-ns-tags [x]
|
||||
(when-not (only-core-drivers? (:node x))
|
||||
(validate-mb-once x)
|
||||
(validate-mb-driver-tests x)))
|
||||
|
||||
(defn test-drivers [x]
|
||||
(validate-ns-tags x)
|
||||
(letfn [(update-node [node]
|
||||
(let [[test-drivers drivers-expr & body] (:children node)]
|
||||
(-> (hooks/list-node
|
||||
(list*
|
||||
(hooks/token-node 'do)
|
||||
test-drivers
|
||||
(-> drivers-expr
|
||||
(hooks.common/update-ignored-linters conj :unused-value))
|
||||
body))
|
||||
(with-meta (meta node)))))]
|
||||
(update x :node update-node)))
|
||||
|
||||
(defn test-driver
|
||||
"We can use the same hook for `test-driver` as we use for `test-drivers`."
|
||||
[x]
|
||||
(test-drivers x))
|
||||
@@ -27,11 +27,11 @@
|
||||
(hooks/vector-node (into []
|
||||
(mapcat (fn [[setting-name v]]
|
||||
(concat
|
||||
[(with-meta (hooks/token-node '_) (meta setting-name)) v]
|
||||
[(with-meta (hooks/token-node '_) (meta setting-name)) v]
|
||||
;; if the setting name is namespace-qualified add a `_`
|
||||
;; entry for it too.
|
||||
(when (namespaced-symbol-node? setting-name)
|
||||
[(with-meta (hooks/token-node '_) (meta setting-name)) setting-name]))))
|
||||
(when (namespaced-symbol-node? setting-name)
|
||||
[(with-meta (hooks/token-node '_) (meta setting-name)) setting-name]))))
|
||||
(partition 2 (:children bindings))))
|
||||
bindings)]
|
||||
{:node (-> (list*
|
||||
|
||||
@@ -15,3 +15,17 @@
|
||||
actual-arg-count)
|
||||
:type :format))))))
|
||||
x)
|
||||
|
||||
(defn case-enum
|
||||
"Lint `(case-enum ...)` like `(condp = ...)`."
|
||||
[x]
|
||||
(letfn [(update-node [node]
|
||||
(let [[_case-enum x & more] (:children node)]
|
||||
(-> (api/list-node
|
||||
(list*
|
||||
(api/token-node 'clojure.core/condp)
|
||||
(api/token-node 'clojure.core/=)
|
||||
x
|
||||
more))
|
||||
(with-meta (meta node)))))]
|
||||
(update x :node update-node)))
|
||||
|
||||
@@ -109,8 +109,6 @@
|
||||
actual-arg-count)
|
||||
:type :metabase/validate-logging)))))
|
||||
|
||||
|
||||
|
||||
(defn infof
|
||||
"Valid logf, debugf, etc."
|
||||
[{:keys [node], :as x}]
|
||||
|
||||
54
.clj-kondo/test/hooks/clojure/core_test.clj
Normal file
@@ -0,0 +1,54 @@
|
||||
(ns hooks.clojure.core-test
|
||||
(:require
|
||||
[clj-kondo.hooks-api :as hooks]
|
||||
[clojure.test :refer :all]
|
||||
[hooks.clojure.core]))
|
||||
|
||||
(deftest module-checker-allowed-modules-test
|
||||
(let [findings (atom [])]
|
||||
(with-redefs [hooks/reg-finding! (fn [node]
|
||||
(swap! findings conj node))]
|
||||
(hooks.clojure.core/lint-ns
|
||||
{:node (hooks/parse-string "
|
||||
(ns metabase.api.search
|
||||
(:require
|
||||
[metabase.request.core :as request]
|
||||
[metabase.task :as task]))")
|
||||
:config '{:linters {:metabase/ns-module-checker {:allowed-modules {metabase.api #{metabase.request}}
|
||||
:api-namespaces {metabase.request #{metabase.request.core}}}}}})
|
||||
(is (=? [{:message (str "Module metabase.task should not be used in the metabase.api module."
|
||||
" [:metabase/ns-module-checker :allowed-modules metabase.api]")
|
||||
:type :metabase/ns-module-checker}]
|
||||
@findings)))))
|
||||
|
||||
(deftest module-checker-api-namespaces-test
|
||||
(let [findings (atom [])]
|
||||
(with-redefs [hooks/reg-finding! (fn [node]
|
||||
(swap! findings conj node))]
|
||||
(hooks.clojure.core/lint-ns
|
||||
{:node (hooks/parse-string "
|
||||
(ns metabase.api.search
|
||||
(:require
|
||||
[metabase.search.config :as search.config]
|
||||
[metabase.search.core :as search]))")
|
||||
:config '{:linters {:metabase/ns-module-checker {:allowed-modules {metabase.api #{metabase.search}}
|
||||
:api-namespaces {metabase.search #{metabase.search.core}}}}}})
|
||||
(is (=? [{:message (str "Namespace metabase.search.config is not an allowed external API namespace for the"
|
||||
" metabase.search module. [:metabase/ns-module-checker :api-namespaces metabase.search]")
|
||||
:type :metabase/ns-module-checker}]
|
||||
@findings)))))
|
||||
|
||||
(deftest module-checker-api-namespaces-ignore-test
|
||||
(let [findings (atom [])]
|
||||
(with-redefs [hooks/reg-finding! (fn [node]
|
||||
(swap! findings conj node))]
|
||||
(hooks.clojure.core/lint-ns
|
||||
{:node (hooks/parse-string "
|
||||
(ns metabase.api.search
|
||||
(:require
|
||||
^{:clj-kondo/ignore [:metabase/ns-module-checker]}
|
||||
[metabase.search.config :as search.config]
|
||||
[metabase.search.core :as search]))")
|
||||
:config '{:linters {:metabase/ns-module-checker {:allowed-modules {metabase.api #{metabase.search}}
|
||||
:api-namespaces {metabase.search #{metabase.search.core}}}}}})
|
||||
(is (empty? @findings)))))
|
||||
@@ -3,7 +3,6 @@
|
||||
[clj-kondo.hooks-api :as api]
|
||||
[clj-kondo.impl.utils]
|
||||
[clojure.edn :as edn]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.test :refer :all]
|
||||
[hooks.clojure.test]))
|
||||
|
||||
@@ -44,9 +43,13 @@
|
||||
(testing "Make sure we keep hooks.clojure.test/driver-keywords up to date"
|
||||
(let [driver-keywords (-> (slurp ".clj-kondo/config.edn")
|
||||
edn/read-string
|
||||
(get-in [:linters :metabase/disallow-hardcoded-driver-names-in-tests :drivers]))]
|
||||
(doseq [^java.io.File file (.listFiles (io/file "modules/drivers"))
|
||||
:when (.isDirectory file)
|
||||
:let [driver (keyword (.getName file))]]
|
||||
(get-in [:linters :metabase/disallow-hardcoded-driver-names-in-tests :drivers]))
|
||||
driver-modules (->> (slurp "modules/drivers/deps.edn")
|
||||
edn/read-string
|
||||
:deps
|
||||
vals
|
||||
(keep (comp keyword :local/root))
|
||||
(into #{}))]
|
||||
(doseq [driver driver-modules]
|
||||
(is (contains? driver-keywords driver)
|
||||
(format "hooks.clojure.test/driver-keywords should contain %s, please add it" driver))))))
|
||||
|
||||
@@ -5,6 +5,35 @@
|
||||
[clojure.test :refer :all]
|
||||
[hooks.common]))
|
||||
|
||||
(deftest ^:parallel ignored-linters-test
|
||||
(doseq [ignored [":metabase/ns-module-checker"
|
||||
"[:metabase/ns-module-checker]"
|
||||
"(:metabase/ns-module-checker)"]
|
||||
prefix ["#_"
|
||||
"^"]
|
||||
:let [s (format "%s{:clj-kondo/ignore %s} [metabase.search.config :as search.config]"
|
||||
prefix
|
||||
ignored)]]
|
||||
(testing (pr-str s)
|
||||
(is (= #{:metabase/ns-module-checker}
|
||||
(hooks.common/ignored-linters (api/parse-string s)))))))
|
||||
|
||||
(deftest ^:parallel merge-ignored-linters-test
|
||||
(let [node-1 (api/parse-string "#_{:clj-kondo/ignore [:a]} [:a]")
|
||||
node-2 (api/parse-string "#_{:clj-kondo/ignore [:b]} [:b]")
|
||||
node-3 (api/parse-string "#_{:clj-kondo/ignore [:c]} [:c]")
|
||||
node-1' (hooks.common/merge-ignored-linters node-1 node-2 node-3)]
|
||||
(is (= #{:a :b :c}
|
||||
(hooks.common/ignored-linters node-1')))
|
||||
(testing "Updated metadata should match the shape Kondo expects"
|
||||
(is (=? {:clj-kondo/ignore {:linters api/vector-node?}}
|
||||
(meta node-1')))
|
||||
(let [children (-> node-1' meta :clj-kondo/ignore :linters :children)]
|
||||
(is (= (count children) 3))
|
||||
(is (every? api/keyword-node? children))
|
||||
(is (= [:a :b :c]
|
||||
(sort (map api/sexpr children))))))))
|
||||
|
||||
(deftest ^:parallel node->qualified-symbol-test
|
||||
(binding [clj-kondo.impl.utils/*ctx* {:namespaces (atom nil)}]
|
||||
(is (= 'metabase.util.i18n/tru
|
||||
|
||||
19
.cljfmt.edn
@@ -13,7 +13,11 @@
|
||||
"test"
|
||||
"enterprise/backend"
|
||||
"bin/build"
|
||||
"bin/lint-migrations-file"
|
||||
"bin/release-list"
|
||||
"modules/drivers"
|
||||
".clj-kondo/src"
|
||||
".clj-kondo/test"
|
||||
#_"dev"]
|
||||
|
||||
;; See https://github.com/weavejester/cljfmt/blob/master/cljfmt/resources/cljfmt/indents/clojure.clj for the default
|
||||
@@ -190,14 +194,15 @@
|
||||
metabase.query-processor.store/with-metadata-provider [[:inner 0]]
|
||||
metabase.query-processor.streaming/streaming-response [[:block 1]]
|
||||
metabase.query-processor.test-util/format-rows-by [[:default]]
|
||||
metabase.request.core/as-admin [[:block 0]]
|
||||
metabase.request.core/with-current-request [[:inner 0]]
|
||||
metabase.request.core/with-current-user [[:inner 0]]
|
||||
metabase.request.core/with-limit-and-offset [[:inner 0]]
|
||||
metabase.request.session/as-admin [[:block 0]]
|
||||
metabase.request.session/with-current-user [[:inner 0]]
|
||||
metabase.sample-data-test/with-temp-sample-database-db [[:block 1]]
|
||||
metabase.server.middleware.session/as-admin [[:block 0]]
|
||||
metabase.server.middleware.session/with-current-user [[:inner 0]]
|
||||
metabase.shared.util.i18n/trs [[:default]]
|
||||
metabase.shared.util.i18n/trsn [[:default]]
|
||||
metabase.shared.util.i18n/tru [[:default]]
|
||||
metabase.shared.util.i18n/trun [[:default]]
|
||||
metabase.shared.util.namespaces/import-fns [[:default]]
|
||||
metabase.sync.fetch-metadata/log-if-error [[:block 1]]
|
||||
metabase.sync.sync-metadata.fields-test/with-test-db [[:block 0]]
|
||||
metabase.sync.util/do-with-start-and-finish-debug-logging [[:default]]
|
||||
@@ -272,6 +277,7 @@
|
||||
metabase.upload.types/with-currency [[:default]]
|
||||
metabase.upload.types/with-parens [[:default]]
|
||||
metabase.util/auto-retry [[:block 1]]
|
||||
metabase.util/case-enum [[:block 1]]
|
||||
metabase.util/ignore-exceptions [[:block 0]]
|
||||
metabase.util/or-with [[:block 1]]
|
||||
metabase.util/profile [[:block 1]]
|
||||
@@ -284,13 +290,16 @@
|
||||
metabase.util.i18n/deferred-trs [[:default]]
|
||||
metabase.util.i18n/deferred-tru [[:default]]
|
||||
metabase.util.i18n/trs [[:default]]
|
||||
metabase.util.i18n/trsn [[:default]]
|
||||
metabase.util.i18n/tru [[:default]]
|
||||
metabase.util.i18n/trun [[:default]]
|
||||
metabase.util.jvm/auto-retry [[:block 1]]
|
||||
metabase.util.jvm/varargs [[:block 1]]
|
||||
metabase.util.jvm/with-us-locale [[:block 0]]
|
||||
metabase.util.malli/disable-enforcement [[:block 0]]
|
||||
metabase.util.malli/with [[:default]]
|
||||
metabase.util.malli/with-api-error-message [[:default]]
|
||||
metabase.util.namespaces/import-fns [[:default]]
|
||||
metabuild-common.core/exit-when-finished-nonzero-on-exception [[:block 0]]
|
||||
metabuild-common.core/step [[:block 1]]
|
||||
metabuild-common.entrypoint/exit-when-finished-nonzero-on-exception [[:block 0]]
|
||||
|
||||
40
.eslintrc.js
@@ -142,6 +142,7 @@ module.exports = {
|
||||
"plugin:import/warnings",
|
||||
"plugin:import/typescript",
|
||||
"plugin:depend/recommended",
|
||||
"plugin:storybook/recommended",
|
||||
],
|
||||
settings: {
|
||||
"import/internal-regex": "^metabase/|^metabase-lib/",
|
||||
@@ -234,8 +235,9 @@ module.exports = {
|
||||
"plugin:jest/recommended",
|
||||
"plugin:jest-dom/recommended",
|
||||
"plugin:testing-library/react",
|
||||
"plugin:jest-formatting/recommended",
|
||||
],
|
||||
plugins: ["jest", "jest-dom", "testing-library"],
|
||||
plugins: ["jest", "jest-dom", "testing-library", "jest-formatting"],
|
||||
files: [
|
||||
"*.unit.spec.ts",
|
||||
"*.unit.spec.tsx",
|
||||
@@ -246,5 +248,41 @@ module.exports = {
|
||||
"jest/valid-title": ["error", { ignoreTypeOfDescribeName: true }],
|
||||
},
|
||||
},
|
||||
{
|
||||
// Enable jest formatting for cypress tests too, the plugin logic just works
|
||||
extends: ["plugin:jest-formatting/recommended"],
|
||||
files: ["*.cy.spec.ts", "*.cy.spec.js"],
|
||||
},
|
||||
{
|
||||
files: ["frontend/src/**/*"],
|
||||
rules: {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
selector: "Literal[value=/mb-base-color-/]",
|
||||
message:
|
||||
"You may not use base colors in the application, use semantic colors instead. (see colors.module.css)",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["frontend/src/metabase/**/*"],
|
||||
rules: {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
selector: "Literal[value=/mb-base-color-/]",
|
||||
message:
|
||||
"You may not use base colors in the application, use semantic colors instead. (see colors.module.css)",
|
||||
},
|
||||
{
|
||||
selector:
|
||||
"CallExpression[callee.property.name='legacyQuery'] > ObjectExpression > Property[key.name='useStructuredQuery'][value.value=true]",
|
||||
message: "StructuredQuery usage is forbidden. Use MLv2",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
4
.github/CODEOWNERS
vendored
@@ -1,10 +1,6 @@
|
||||
# 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
|
||||
# TL;DR: if @camsaul hasn't been involved you're probably doing it wrong
|
||||
|
||||
src/metabase @camsaul
|
||||
modules @camsaul
|
||||
enterprise/backend @camsaul
|
||||
enterprise/backend/src/metabase_enterprise/advanced_permissions @noahmoss
|
||||
enterprise/backend/src/metabase_enterprise/audit_app @noahmoss
|
||||
enterprise/backend/src/metabase_enterprise/sso @noahmoss
|
||||
|
||||
13
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -66,12 +66,13 @@ body:
|
||||
Copy and paste the JSON from `Admin -> Troubleshooting`.
|
||||
_This will be automatically formatted into code, so no need for backticks._
|
||||
placeholder: |
|
||||
- Your browser and the version: (e.g., Chrome 52.1, Firefox 48.0, Safari 11.1, …)
|
||||
- Your operating system: (e.g., OS X 10.10, Windows 10.1809, Ubuntu 16.04, …)
|
||||
- Your databases: (e.g, MySQL, Postgres, MongoDB, …)
|
||||
- Metabase version: (e.g., 0.19.3)
|
||||
- Metabase hosting environment: (e.g., Elastic Beanstalk, Docker, Heroku, Jar-file on Ubuntu, …)
|
||||
- Metabase internal database: (e.g., H2 (default), Postgres or MySQL)
|
||||
{"browser-info": {
|
||||
"language": "en-US",
|
||||
"platform": "MacIntel",
|
||||
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
||||
"vendor": "Google Inc."},
|
||||
"metabase-info": {
|
||||
"databases": [ "postgres",...
|
||||
render: JSON
|
||||
validations:
|
||||
required: true
|
||||
|
||||
23
.github/ISSUE_TEMPLATE/epic.md
vendored
@@ -5,20 +5,19 @@ about: This issue is used to track a feature/project that may span several days
|
||||
and manage work.
|
||||
title: "[Epic] Title"
|
||||
labels: ".Epic"
|
||||
|
||||
---
|
||||
|
||||
**Links**
|
||||
- product doc: _link to product doc_
|
||||
- eng doc: _link to technical design doc, if any_
|
||||
- feature branch: `branch-name` _this should be the feature branch where this work will be done in. PRs will be delivered against this branch_
|
||||
- issue links: _related issues if any_
|
||||
### Links
|
||||
|
||||
**Implementation Plan**
|
||||
- [product doc](LINK_TO_PRODUCT_DOC)
|
||||
- [technical design doc](LINK_TO_TECHNICAL_DESIGN_DOC)
|
||||
- [testing plan](LINK_TO_TESTING_PLAN)
|
||||
- feature branch: `BRANCH_NAME`
|
||||
- issue links: _related issues, if any_
|
||||
|
||||
### Implementation Plan
|
||||
|
||||
***Milestone 1***
|
||||
_insert tasklist here_
|
||||
|
||||
***Milestone 2***
|
||||
|
||||
```[tasklist]
|
||||
#### Milestone 1
|
||||
- [ ] _Add tasks here_
|
||||
```
|
||||
|
||||
15
.github/actions/await-port/action.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
name: Wait for localhost port to be ready
|
||||
|
||||
inputs:
|
||||
port:
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Wait for port ${{ inputs.port }} to be ready
|
||||
shell: bash
|
||||
run: |
|
||||
while ! nc -z localhost ${{ inputs.port }}; do
|
||||
sleep 0.1;
|
||||
done
|
||||
70
.github/actions/build-e2e-matrix/action.yml
vendored
@@ -1,70 +0,0 @@
|
||||
name: Build E2E Matrix
|
||||
description: Build and output a custom matrix for E2E tests.
|
||||
|
||||
outputs:
|
||||
matrix:
|
||||
description: Parameterized matrix in JSON format
|
||||
value: ${{ steps.matrix.outputs.result }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
id: matrix
|
||||
with:
|
||||
script: | # js
|
||||
const java = 11;
|
||||
|
||||
const defaultRunner = "ubuntu-22.04";
|
||||
|
||||
const defaultOptions = {
|
||||
"java-version": java,
|
||||
runner: defaultRunner,
|
||||
edition: "ee",
|
||||
context: "folder"
|
||||
};
|
||||
|
||||
const testSets = [
|
||||
["actions", {} ],
|
||||
["admin", {} ],
|
||||
["admin-2", {} ],
|
||||
["binning", {} ],
|
||||
["collections", {} ],
|
||||
["custom-column", {} ],
|
||||
["dashboard", {} ],
|
||||
["dashboard-cards", {} ],
|
||||
["dashboard-filters", {} ],
|
||||
["embedding", {} ],
|
||||
["embedding-sdk", { context: "embedding-sdk" } ],
|
||||
["filters", {} ],
|
||||
["filters-reproductions", {}],
|
||||
["joins", {} ],
|
||||
["metrics", {} ],
|
||||
["models", {} ],
|
||||
["native", {} ],
|
||||
["native-filters", {} ],
|
||||
["onboarding", {} ],
|
||||
["organization", {} ],
|
||||
["permissions", {} ],
|
||||
["question", {} ],
|
||||
["question-reproductions", {} ],
|
||||
["search", {}],
|
||||
["sharing", {} ],
|
||||
["visualizations-charts", {} ],
|
||||
["visualizations-tabular", {} ],
|
||||
["oss-subset", { edition: 'oss', context: "special" } ],
|
||||
["slow", { context: "special" } ],
|
||||
["flaky", { context: "special" } ],
|
||||
["mongo", { context: "qa-database" } ],
|
||||
];
|
||||
|
||||
const config = testSets.map(([name, specialOptions]) => {
|
||||
return {
|
||||
...defaultOptions,
|
||||
...specialOptions,
|
||||
name,
|
||||
}
|
||||
});
|
||||
|
||||
const matrix = { include: config };
|
||||
return matrix;
|
||||
132
.github/actions/build-ee-extra/action.yml
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
name: Build ee-extra
|
||||
description: Build Metabase Enterprise Edition with extra features
|
||||
|
||||
inputs:
|
||||
java-version:
|
||||
required: true
|
||||
# build with Java 11 since that's still officially what we target as a minimum and we don't want Java >11 bytecode
|
||||
# sneaking in.
|
||||
default: 11
|
||||
iam-role:
|
||||
description: "The IAM role to assume"
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Prepare Java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ inputs.java-version }}
|
||||
distribution: 'temurin'
|
||||
- name: Reveal its original version.properties
|
||||
run: jar xf ./bin/docker/metabase.jar version.properties && cat version.properties
|
||||
shell: bash
|
||||
- name: get major version
|
||||
id: major_version
|
||||
run: echo "major_version=$(cat version.properties | grep 'tag=' | cut -d'.' -f2)" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
- name: get drivers registry
|
||||
run: |
|
||||
curl -OL https://raw.githubusercontent.com/metabase/metabase-registry/main/registry.yaml
|
||||
shell: bash
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/Hydrogen # 18.x.x
|
||||
- run: rm package.json && npm install yaml
|
||||
shell: bash
|
||||
- name: parse drivers registry
|
||||
uses: actions/github-script@v7
|
||||
id: drivers_registry
|
||||
with:
|
||||
script: | # js
|
||||
const { parse } = require('yaml');
|
||||
const fs = require('fs');
|
||||
const registry = parse(fs.readFileSync('registry.yaml', 'utf8'));
|
||||
|
||||
const drivers = registry.drivers;
|
||||
const majorVersion = '${{ steps.major_version.outputs.major_version }}';
|
||||
|
||||
const getDriverUrl = (driverName) => {
|
||||
const driver = drivers.find(driver => driver.name === driverName);
|
||||
|
||||
if (!driver) {
|
||||
throw new Error(`Driver ${driverName} not found in the registry`);
|
||||
}
|
||||
|
||||
const driverUrl = driver.versions[majorVersion] ?? driver.versions.default;
|
||||
|
||||
if (!driverUrl) {
|
||||
throw new Error(`Driver ${driverName} version ${majorVersion} not found in the registry`);
|
||||
}
|
||||
|
||||
return driverUrl;
|
||||
};
|
||||
|
||||
const extraDrivers = {
|
||||
firebolt: getDriverUrl('firebolt'),
|
||||
starburst: getDriverUrl('starburst'),
|
||||
exasol: getDriverUrl('exasol'),
|
||||
exasol_jdbc: drivers.find(d => d.name === 'exasol').deps[0],
|
||||
clickhouse: getDriverUrl('clickhouse'),
|
||||
ocient: getDriverUrl('ocient'),
|
||||
materialize: getDriverUrl('materialize'),
|
||||
};
|
||||
|
||||
console.log(extraDrivers);
|
||||
|
||||
return extraDrivers;
|
||||
- name: Download Firebolt driver
|
||||
run: |
|
||||
curl -OL ${{ fromJson(steps.drivers_registry.outputs.result).firebolt }}
|
||||
working-directory: modules
|
||||
shell: bash
|
||||
- name: Download Starburst driver
|
||||
run: |
|
||||
curl -OL ${{ fromJson(steps.drivers_registry.outputs.result).starburst }}
|
||||
shell: bash
|
||||
working-directory: modules
|
||||
- name: Download Exasol driver
|
||||
run: |
|
||||
curl -OL ${{ fromJson(steps.drivers_registry.outputs.result).exasol }}
|
||||
curl -OL ${{ fromJson(steps.drivers_registry.outputs.result).exasol_jdbc }}
|
||||
shell: bash
|
||||
working-directory: modules
|
||||
- name: Download Clickhouse driver
|
||||
run: |
|
||||
curl -OL ${{ fromJson(steps.drivers_registry.outputs.result).clickhouse }}
|
||||
shell: bash
|
||||
working-directory: modules
|
||||
- name: Download Ocient driver
|
||||
run: |
|
||||
curl -OL ${{ fromJson(steps.drivers_registry.outputs.result).ocient }}
|
||||
shell: bash
|
||||
working-directory: modules
|
||||
- name: Download Materialize driver
|
||||
run: |
|
||||
curl -OL ${{ fromJson(steps.drivers_registry.outputs.result).materialize }}
|
||||
shell: bash
|
||||
working-directory: modules
|
||||
- name: Bundle additional drivers into the Uberjar
|
||||
run: jar uf bin/docker/metabase.jar modules/*.jar
|
||||
shell: bash
|
||||
- name: Launch uberjar
|
||||
run: >-
|
||||
java --add-opens java.base/java.nio=ALL-UNNAMED -jar ./bin/docker/metabase.jar &
|
||||
shell: bash
|
||||
- name: Wait for Metabase to start
|
||||
run: while ! curl 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
|
||||
shell: bash
|
||||
- name: Kill the java process
|
||||
run: pkill -f metabase.jar
|
||||
shell: bash
|
||||
- name: configure aws credentials
|
||||
if: ${{ github.ref_name == 'master' }}
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: ${{ inputs.iam-role }}
|
||||
role-session-name: GitHub_to_AWS_via_FederatedOIDC
|
||||
aws-region: us-east-1
|
||||
- name: Login to Amazon ECR
|
||||
if: ${{ github.ref_name == 'master' }}
|
||||
uses: aws-actions/amazon-ecr-login@v2
|
||||
@@ -90,7 +90,7 @@ runs:
|
||||
|
||||
if ${{ inputs.webhook }}; then
|
||||
echo -e "${Y}Starting webhook test container..." &&
|
||||
docker run -d -p 9080:8080/tcp tarampampam/webhook-tester serve --create-session 00000000-0000-0000-0000-000000000000 &&
|
||||
docker run -d -p 9080:8080/tcp tarampampam/webhook-tester:1.1.0 serve --create-session 00000000-0000-0000-0000-000000000000 &&
|
||||
while ! nc -z localhost 9080; do sleep 1; done &&
|
||||
echo -e "${G}Webhook tester is up and running!"
|
||||
fi
|
||||
|
||||
4
.github/actions/prepare-backend/action.yml
vendored
@@ -2,10 +2,10 @@ name: Prepare back-end environment
|
||||
inputs:
|
||||
java-version:
|
||||
required: true
|
||||
default: '11'
|
||||
default: '21'
|
||||
clojure-version:
|
||||
required: true
|
||||
default: '1.11.1.1262'
|
||||
default: '1.12.0.1488'
|
||||
m2-cache-key:
|
||||
description: 'Key to cache M2 packages from Maven Central'
|
||||
required: true
|
||||
|
||||
4
.github/auto_request_review.yml
vendored
@@ -5,9 +5,9 @@
|
||||
files:
|
||||
# migrations related files
|
||||
'resources/migrations/**':
|
||||
- team:core-backend-components
|
||||
- team:core-workflows
|
||||
'src/metabase/db/custom_migrations.clj':
|
||||
- team:core-backend-components
|
||||
- team:core-workflows
|
||||
|
||||
options:
|
||||
ignore_draft: true
|
||||
|
||||
@@ -10,9 +10,9 @@ export PATH="$PATH:$JAVA_HOME/bin"
|
||||
which java
|
||||
|
||||
# install clojure version needed for Metabase
|
||||
curl -O https://download.clojure.org/install/linux-install-1.11.0.1100.sh
|
||||
chmod +x linux-install-1.11.0.1100.sh
|
||||
./linux-install-1.11.0.1100.sh
|
||||
curl -O https://download.clojure.org/install/linux-install-1.12.0.1488.sh
|
||||
chmod +x linux-install-1.12.0.1488.sh
|
||||
./linux-install-1.12.0.1488.sh
|
||||
|
||||
RESOURCES_DIR=/app/source/resources
|
||||
|
||||
|
||||
21
.github/team.json
vendored
@@ -7,13 +7,13 @@
|
||||
"members": [
|
||||
"ranquild",
|
||||
"kamilmielnik",
|
||||
"nemanjaglumac",
|
||||
"romeovs",
|
||||
"bshepherdson",
|
||||
"metamben",
|
||||
"lbrdnk",
|
||||
"appleby",
|
||||
"uladzimirdev"
|
||||
"uladzimirdev",
|
||||
"wzimrin"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -25,17 +25,17 @@
|
||||
"name": "Embedding",
|
||||
"label": ".Team/Embedding",
|
||||
"projectUrl": "https://github.com/orgs/metabase/projects/88/views/1",
|
||||
"members": ["WiNloSt", "deniskaber", "oisincoveney", "npretto", "heypoom"]
|
||||
"members": ["WiNloSt", "oisincoveney", "npretto", "heypoom"]
|
||||
},
|
||||
{
|
||||
"name": "BEC",
|
||||
"label": ".Team/BackendComponents",
|
||||
"name": "Workflows",
|
||||
"label": ".Team/Workflows",
|
||||
"projectUrl": "https://github.com/orgs/metabase/projects/50/views/1",
|
||||
"members": [
|
||||
"tsmacdonald",
|
||||
"qnkhuat",
|
||||
"piranha",
|
||||
"crisptrutski"
|
||||
"crisptrutski",
|
||||
"deniskaber"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -48,7 +48,8 @@
|
||||
"johnswanson",
|
||||
"rafpaf",
|
||||
"sloansparger",
|
||||
"iethree"
|
||||
"iethree",
|
||||
"nvoxland"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -56,9 +57,9 @@
|
||||
"label": ".Team/DashViz",
|
||||
"members": [
|
||||
"alxnddr",
|
||||
"EmmadUsmani",
|
||||
"kulyk",
|
||||
"adam-james-v"
|
||||
"adam-james-v",
|
||||
"tsplude"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
2
.github/workflows/backend-cloverage.yml
vendored
@@ -7,6 +7,8 @@ on:
|
||||
|
||||
jobs:
|
||||
be-linter-cloverage:
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
|
||||
11
.github/workflows/backend.yml
vendored
@@ -154,6 +154,7 @@ jobs:
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: be-tests
|
||||
java-version: "${{ matrix.java-version }}"
|
||||
# Depending on which files changed, we might either have to build static-viz
|
||||
# from scratch or download the previously built artifact
|
||||
- name: Build static-viz frontend
|
||||
@@ -168,12 +169,6 @@ jobs:
|
||||
|
||||
- name: Run tests
|
||||
id: run-java-tests
|
||||
if: matrix.java-version != 21
|
||||
run: clojure -X:dev:ci:test:${{ matrix.edition }}:${{ matrix.edition }}-dev
|
||||
|
||||
- name: If using Java 21, only run tests on `master`
|
||||
id: run-java-tests-21
|
||||
if: matrix.java-version == 21 && github.ref_name == 'master'
|
||||
run: clojure -X:dev:ci:test:${{ matrix.edition }}:${{ matrix.edition }}-dev
|
||||
|
||||
- name: Upload Test Results
|
||||
@@ -200,9 +195,9 @@ jobs:
|
||||
fail-on-error: false
|
||||
|
||||
be-tests-stub:
|
||||
needs: [be-tests]
|
||||
needs: [files-changed, static-viz-files-changed, be-tests]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
always() &&
|
||||
github.event.pull_request.draft == false && needs.be-tests.result == 'skipped'
|
||||
runs-on: ubuntu-22.04
|
||||
name: be-tests-java-${{ matrix.java-version }}-${{ matrix.edition }}
|
||||
|
||||
91
.github/workflows/backport.yml
vendored
@@ -6,25 +6,50 @@ on:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
check_pull_request_state:
|
||||
name: Checks whether the PR has been merged
|
||||
if: github.event.issue.pull_request && contains(github.event.comment.body, '@metabase-bot backport')
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
canBackport: ${{ steps.check_pull_request_state.outputs.result }}
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
id: check_pull_request_state
|
||||
with:
|
||||
script: |
|
||||
const { data: pullRequest } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.payload.issue.number
|
||||
});
|
||||
|
||||
const canBackport = pullRequest.state === "closed"
|
||||
if (!canBackport) {
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: context.payload.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: "The backport command can only be used after the pull request has been merged. Please wait until the PR is merged before attempting to backport."
|
||||
});
|
||||
}
|
||||
return canBackport
|
||||
|
||||
create_pull_request:
|
||||
name: Creates a pull request
|
||||
if: contains(github.event.comment.body, '@metabase-bot backport')
|
||||
needs: [check_pull_request_state]
|
||||
if: needs.check_pull_request_state.outputs.canBackport == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: tibdex/github-app-token@v2.1.0
|
||||
id: generate-token
|
||||
with:
|
||||
app_id: ${{ secrets.METABASE_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
|
||||
- uses: actions/checkout@v4
|
||||
name: Cherry-pick commits and create PR
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: Verify Membership
|
||||
id: verify-membership
|
||||
uses: ./.github/actions/verify-membership
|
||||
with:
|
||||
github_token: ${{ steps.generate-token.outputs.token }}
|
||||
github_token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
organization_name: metabase
|
||||
username: ${{ github.event.comment.user.login }}
|
||||
- run: |
|
||||
@@ -110,23 +135,50 @@ jobs:
|
||||
|
||||
if [ -n "${SQUASHED_COMMIT}" ]; then
|
||||
echo "found commit ${SQUASHED_COMMIT}"
|
||||
git cherry-pick ${SQUASHED_COMMIT}
|
||||
else
|
||||
echo "probably a PR wasn't merged with Squash And Merge button, searching again"
|
||||
SQUASHED_COMMIT=$(env -i git log ${ORIGINAL_BASE_REF} --grep="#${ORIGINAL_PULL_REQUEST_NUMBER}" --format="%H")
|
||||
|
||||
if [ -n "${SQUASHED_COMMIT}" ]; then
|
||||
echo "found commit ${SQUASHED_COMMIT}"
|
||||
git cherry-pick ${SQUASHED_COMMIT}
|
||||
else
|
||||
echo "No squashed commit found for PR #${ORIGINAL_PULL_REQUEST_NUMBER}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
echo "PR has not been merged, copying all commits"
|
||||
git cherry-pick ${ORIGINAL_BASE_SHA}..${ORIGINAL_HEAD_SHA}
|
||||
echo "The PR has not been merged"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git cherry-pick ${SQUASHED_COMMIT} || true
|
||||
|
||||
CONFLICTS=$(git ls-files -u | wc -l)
|
||||
if [ "$CONFLICTS" -gt 0 ]; then
|
||||
git cherry-pick --abort
|
||||
|
||||
echo "Could not cherry pick because of a conflict"
|
||||
echo "has-conflicts=true" >> $GITHUB_OUTPUT
|
||||
|
||||
# Add a shell script for resolving conflicts
|
||||
echo "git reset HEAD~1" > ./backport.sh
|
||||
echo "rm ./backport.sh" >> ./backport.sh
|
||||
echo "git cherry-pick ${SQUASHED_COMMIT}" >> ./backport.sh
|
||||
echo "echo 'Resolve conflicts and force push this branch'" >> ./backport.sh
|
||||
chmod +x ./backport.sh
|
||||
git add ./backport.sh
|
||||
git commit -m "Add backport resolution script"
|
||||
|
||||
PR_BODY=$(cat <<-END
|
||||
#${ORIGINAL_PULL_REQUEST_NUMBER}
|
||||
> [!IMPORTANT]
|
||||
> Manual conflict resolution is required.
|
||||
Checkout the branch and run \`./backport.sh\` script. Force push your changes after cherry-picking.
|
||||
END
|
||||
)
|
||||
else
|
||||
echo "has-conflicts=false" >> $GITHUB_OUTPUT
|
||||
PR_BODY="#${ORIGINAL_PULL_REQUEST_NUMBER}"
|
||||
fi
|
||||
|
||||
git push origin "${BACKPORT_BRANCH}" --force-with-lease
|
||||
@@ -134,12 +186,14 @@ jobs:
|
||||
if [[ $(gh pr list --base "${TARGET_BRANCH}" --head "${BACKPORT_BRANCH}" -s "open") ]]; then
|
||||
echo "PR already exists"
|
||||
else
|
||||
BACKPORT_PR_URL=$(gh pr create --base "${TARGET_BRANCH}" --head "${BACKPORT_BRANCH}" --label "was-backported" --assignee "${GITHUB_ACTOR}" --title "🤖 backported \"${ORIGINAL_TITLE}\"" --body "#${ORIGINAL_PULL_REQUEST_NUMBER}")
|
||||
BACKPORT_PR_URL=$(gh pr create --base "${TARGET_BRANCH}" --head "${BACKPORT_BRANCH}" --label "was-backported" --assignee "${GITHUB_ACTOR}" --title "🤖 backported \"${ORIGINAL_TITLE}\"" --body "${PR_BODY}")
|
||||
BACKPORT_PR_NUMBER=${BACKPORT_PR_URL##*/}
|
||||
|
||||
echo "backport_pr_number=$BACKPORT_PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
echo "New PR has been created"
|
||||
fi
|
||||
|
||||
git checkout master
|
||||
env:
|
||||
ORIGINAL_TITLE: ${{ fromJson(steps.branch_info.outputs.result).originalPullRequest.title }}
|
||||
ORIGINAL_BASE_REF: ${{ fromJson(steps.branch_info.outputs.result).originalPullRequest.base.ref }}
|
||||
@@ -151,18 +205,25 @@ jobs:
|
||||
BACKPORT_BRANCH: ${{ fromJson(steps.branch_info.outputs.result).backportBranch }}
|
||||
START_SHA: ${{ fromJson(steps.branch_info.outputs.result).startSha }}
|
||||
END_SHA: ${{ fromJson(steps.branch_info.outputs.result).endSha }}
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
GITHUB_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: Auto approve backport PR
|
||||
if: ${{ steps.create_backport_pull_request.outputs.has-conflicts == 'false' }}
|
||||
uses: juliangruber/approve-pull-request-action@v1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
number: ${{ steps.create_backport_pull_request.outputs.backport_pr_number }}
|
||||
- name: Enable Pull Request Automerge
|
||||
if: ${{ steps.create_backport_pull_request.outputs.has-conflicts == 'false' }}
|
||||
uses: peter-evans/enable-pull-request-automerge@v2
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
pull-request-number: ${{ steps.create_backport_pull_request.outputs.backport_pr_number }}
|
||||
merge-method: squash
|
||||
- uses: ./.github/actions/notify-pull-request
|
||||
if: ${{ steps.create_backport_pull_request.outputs.has-conflicts == 'true' }}
|
||||
with:
|
||||
include-log: false
|
||||
message: Manual conflict resolution is required
|
||||
|
||||
notify_when_failed:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
@@ -3,14 +3,13 @@ name: Bugs Slack Notification
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
- labeled
|
||||
jobs:
|
||||
on-issue-opened:
|
||||
on-issue-labeled:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
if: |
|
||||
contains(github.event.issue.labels.*.name, '.Needs Triage') &&
|
||||
contains(github.event.issue.labels.*.name, 'Type:Bug')
|
||||
github.event.label.name == '.Needs Triage' && contains(github.event.issue.labels.*.name, 'Type:Bug')
|
||||
steps:
|
||||
- name: Setting title
|
||||
uses: actions/github-script@v7
|
||||
@@ -34,7 +33,7 @@ jobs:
|
||||
- name: Send the issue ${{ github.event.issue.number }} to Slack
|
||||
id: slack
|
||||
if: steps.check_labels.outputs.has_team_label == 'false'
|
||||
uses: slackapi/slack-github-action@v1.23.0
|
||||
uses: slackapi/slack-github-action@v1.26.0
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
|
||||
40
.github/workflows/build-for-release.yml
vendored
@@ -100,21 +100,14 @@ jobs:
|
||||
oss: getCanonicalVersion(version, 'oss'),
|
||||
};
|
||||
|
||||
const ossReleased = await hasBeenReleased({
|
||||
const released = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.oss,
|
||||
});
|
||||
|
||||
const eeReleased = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.ee,
|
||||
});
|
||||
|
||||
if (ossReleased || eeReleased) {
|
||||
if (released) {
|
||||
throw new Error("This version has already been released!", version);
|
||||
}
|
||||
|
||||
@@ -243,24 +236,11 @@ jobs:
|
||||
./COMMIT-ID
|
||||
./SHA256.sum
|
||||
|
||||
trigger-tests:
|
||||
needs: [build-uberjar-for-release]
|
||||
permissions:
|
||||
actions: write
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: trigger pre-release testing
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
github.rest.actions.createWorkflowDispatch({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
workflow_id: 'pre-release.yml',
|
||||
ref: '${{ github.ref }}',
|
||||
inputs: {
|
||||
commit: '${{ inputs.commit }}',
|
||||
version: '${{ inputs.version }}',
|
||||
}
|
||||
});
|
||||
run-pre-release-tests:
|
||||
name: Run pre-release tests for ${{ inputs.version }}
|
||||
needs: build-uberjar-for-release
|
||||
uses: ./.github/workflows/pre-release.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
commit: ${{ inputs.commit }}
|
||||
version: ${{ inputs.version }}
|
||||
|
||||
48
.github/workflows/check-milestone.yml
vendored
@@ -1,16 +1,24 @@
|
||||
name: Automatically set milestone
|
||||
run-name: Set milestone for ${{ github.event.head_commit.message }}
|
||||
run-name: Set milestone for ${{ github.event.head_commit.message || inputs.version }}
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- release-x.**
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Major version number (e.g. 52, 78, 109)'
|
||||
type: number
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
set-milestone:
|
||||
name: Automatically set milestone
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
isNewReleaseBranch: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
@@ -19,10 +27,13 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
fetch-depth: ${{ env.isNewReleaseBranch == 'false' && 3 || 0 }} # we need the full history to get all the commit messages
|
||||
ref: master # we want the logic from master, even though we're triggering on a release branch
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- uses: actions/github-script@v7
|
||||
if: ${{ env.isNewReleaseBranch == 'false' }}
|
||||
name: Set milestone for single commit
|
||||
with:
|
||||
script: | # js
|
||||
const { setMilestoneForCommits } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
@@ -39,3 +50,36 @@ jobs:
|
||||
branchName,
|
||||
commitMessages: [commitMessage],
|
||||
});
|
||||
- name: Get commit messages for release branch
|
||||
if: ${{ env.isNewReleaseBranch == 'true' }}
|
||||
run: |
|
||||
npm i -g tsx
|
||||
tsx release/src/release-branch-commits.ts ${{ inputs.version }} > commit-messages.json
|
||||
- uses: actions/github-script@v7
|
||||
if: ${{ env.isNewReleaseBranch == 'true' }}
|
||||
name: Set milestones for new release branch
|
||||
env:
|
||||
# this token has a higher rate limit than the default token, and
|
||||
# we will need it for this workflow to work
|
||||
GITHUB_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
with:
|
||||
script: | # js
|
||||
const { setMilestoneForCommits } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const commitMessages = require('${{ github.workspace }}/commit-messages.json');
|
||||
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
|
||||
const versionNumber = context.payload.inputs.version;
|
||||
const branchName = `release-x.${versionNumber}.x`;
|
||||
|
||||
console.log(`Found ${commitMessages.length} new commits for ${branchName}`);
|
||||
|
||||
await setMilestoneForCommits({
|
||||
github,
|
||||
owner,
|
||||
repo,
|
||||
branchName,
|
||||
commitMessages: commitMessages,
|
||||
ignoreExistingMilestones: true,
|
||||
});
|
||||
|
||||
18
.github/workflows/doc-md-links.yml
vendored
@@ -1,18 +0,0 @@
|
||||
name: Lint doc Markdown links
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- docs/**
|
||||
pull_request:
|
||||
paths:
|
||||
- docs/**
|
||||
jobs:
|
||||
markdown-link-check:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Lint doc links
|
||||
run: yarn run docs-lint-links
|
||||
297
.github/workflows/drivers.yml
vendored
@@ -49,7 +49,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-athena-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -82,7 +83,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-bigquery-cloud-sdk-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -116,7 +118,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-druid-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -141,13 +144,16 @@ jobs:
|
||||
MB_DATABRICKS_TEST_HTTP_PATH: ${{ secrets.MB_DATABRICKS_JDBC_TEST_HTTP_PATH }}
|
||||
MB_DATABRICKS_TEST_TOKEN: ${{ secrets.MB_DATABRICKS_JDBC_TEST_TOKEN }}
|
||||
MB_DATABRICKS_TEST_CATALOG: 'metabase_ci'
|
||||
MB_DATABRICKS_TEST_CLIENT_ID: ${{ secrets.MB_DATABRICKS_JDBC_TEST_CLIENT_ID }}
|
||||
MB_DATABRICKS_TEST_OAUTH_SECRET: ${{ secrets.MB_DATABRICKS_JDBC_TEST_OAUTH_SECRET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test Databricks driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-databricks-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -181,7 +187,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-druid-jdbc-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -199,6 +206,10 @@ jobs:
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
partition-index: [0, 1, 2, 3]
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
@@ -219,6 +230,9 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mariadb-10-2-ee'
|
||||
test-args: >-
|
||||
:partition/total 4
|
||||
:partition/index ${{ matrix.partition-index }}
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -236,6 +250,10 @@ jobs:
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
partition-index: [0, 1, 2, 3]
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
@@ -256,6 +274,9 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mariadb-latest-ee'
|
||||
test-args: >-
|
||||
:partition/total 4
|
||||
:partition/index ${{ matrix.partition-index }}
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -289,7 +310,9 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-4-4-ee'
|
||||
test-args: ":exclude-tags '[:mb/once :mongo-sharded-cluster-tests]'"
|
||||
test-args: >-
|
||||
:exclude-tags [:mongo-sharded-cluster-tests]
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -316,9 +339,19 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Spin up Mongo docker container
|
||||
run: docker run -d -p 27017:27017 --name metamongo metabase/qa-databases:mongo-sample-4.4 mongod --dbpath /data/db2/ --tlsMode requireTLS --tlsCertificateKeyFile /etc/mongo/metamongo.pem --tlsCAFile /etc/mongo/metaca.crt
|
||||
- name: Wait until the port 27017 is ready
|
||||
run: while ! nc -z localhost 27017; do sleep 1; done
|
||||
run: >-
|
||||
docker run -d
|
||||
-p 27017:27017
|
||||
--name metamongo
|
||||
metabase/qa-databases:mongo-sample-4.4
|
||||
mongod
|
||||
--dbpath /data/db2/
|
||||
--tlsMode requireTLS
|
||||
--tlsCertificateKeyFile /etc/mongo/metamongo.pem
|
||||
--tlsCAFile /etc/mongo/metaca.crt
|
||||
- uses: ./.github/actions/await-port
|
||||
with:
|
||||
port: 27017
|
||||
timeout-minutes: 5
|
||||
- name: Make SSL certificates for Mongo available
|
||||
run: |
|
||||
@@ -330,12 +363,13 @@ jobs:
|
||||
|
||||
curl https://raw.githubusercontent.com/metabase/metabase-qa/master/dbs/mongo/certificates/metaca.crt \
|
||||
-o ./test_resources/ssl/mongo/metaca.crt
|
||||
|
||||
- name: Test MongoDB SSL driver (4.4)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-4-4-ee'
|
||||
test-args: ":exclude-tags '[:mb/once :mongo-sharded-cluster-tests]'"
|
||||
test-args: >-
|
||||
:exclude-tags [:mongo-sharded-cluster-tests]
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -369,7 +403,9 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-5-0-ee'
|
||||
test-args: ":exclude-tags '[:mb/once :mongo-sharded-cluster-tests]'"
|
||||
test-args: >-
|
||||
:exclude-tags [:mongo-sharded-cluster-tests]
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -396,9 +432,19 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Spin up Mongo docker container
|
||||
run: docker run -d -p 27017:27017 --name metamongo metabase/qa-databases:mongo-sample-5.0 mongod --dbpath /data/db2/ --tlsMode requireTLS --tlsCertificateKeyFile /etc/mongo/metamongo.pem --tlsCAFile /etc/mongo/metaca.crt
|
||||
- name: Wait until the port 27017 is ready
|
||||
run: while ! nc -z localhost 27017; do sleep 1; done
|
||||
run: >-
|
||||
docker run -d
|
||||
-p 27017:27017
|
||||
--name metamongo
|
||||
metabase/qa-databases:mongo-sample-5.0
|
||||
mongod
|
||||
--dbpath /data/db2/
|
||||
--tlsMode requireTLS
|
||||
--tlsCertificateKeyFile /etc/mongo/metamongo.pem
|
||||
--tlsCAFile /etc/mongo/metaca.crt
|
||||
- uses: ./.github/actions/await-port
|
||||
with:
|
||||
port: 27017
|
||||
timeout-minutes: 5
|
||||
- name: Make SSL certificates for Mongo available
|
||||
run: |
|
||||
@@ -410,12 +456,13 @@ jobs:
|
||||
|
||||
curl https://raw.githubusercontent.com/metabase/metabase-qa/master/dbs/mongo/certificates/metaca.crt \
|
||||
-o ./test_resources/ssl/mongo/metaca.crt
|
||||
|
||||
- name: Test MongoDB SSL driver (5.0)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-5-0-ee'
|
||||
test-args: ":exclude-tags '[:mb/once :mongo-sharded-cluster-tests]'"
|
||||
test-args: >-
|
||||
:exclude-tags [:mongo-sharded-cluster-tests]
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -452,7 +499,9 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mongo-latest-ee'
|
||||
test-args: ":exclude-tags '[:mb/once :mongo-sharded-cluster-tests]'"
|
||||
test-args: >-
|
||||
:exclude-tags [:mongo-sharded-cluster-tests]
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -502,6 +551,10 @@ jobs:
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
partition-index: [0, 1, 2, 3]
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
@@ -522,12 +575,30 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mysql-8-0-ee'
|
||||
test-args: >-
|
||||
:partition/total 4
|
||||
:partition/index ${{ matrix.partition-index }}
|
||||
- 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-mysql-latest-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
partition-index: [0, 1, 2, 3]
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: mysql
|
||||
@@ -563,6 +634,9 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-mysql-latest-ee'
|
||||
test-args: >-
|
||||
:partition/total 4
|
||||
:partition/index ${{ matrix.partition-index }}
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -600,7 +674,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-oracle-18-4-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -647,7 +722,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-oracle-21-3-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -665,6 +741,28 @@ jobs:
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- name: Postgres 12.x
|
||||
junit-name: postgres-ee
|
||||
docker-image: postgres:12-alpine
|
||||
env:
|
||||
enable-ssl-tests: 'false'
|
||||
- name: Postgres Latest
|
||||
junit-name: postgres-latest-ee
|
||||
docker-image: postgres:latest
|
||||
env:
|
||||
enable-ssl-tests: 'true'
|
||||
job:
|
||||
- name: Driver Tests
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: App DB Tests
|
||||
test-args: >-
|
||||
:exclude-tags [:mb/driver-tests]
|
||||
name: Test ${{ matrix.version.name }} (${{ matrix.job.name }})
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: postgres
|
||||
@@ -674,9 +772,13 @@ jobs:
|
||||
MB_DB_DBNAME: mb_test
|
||||
MB_DB_USER: mb_test
|
||||
MB_POSTGRESQL_TEST_USER: mb_test
|
||||
# SSL tests are only enabled for the postgres-latest job.
|
||||
MB_POSTGRES_SSL_TEST_SSL: ${{ matrix.version.env.enable-ssl-tests }}
|
||||
MB_POSTGRES_SSL_TEST_SSL_MODE: verify-full
|
||||
MB_POSTGRES_SSL_TEST_SSL_ROOT_CERT_PATH: 'test-resources/certificates/us-east-2-bundle.pem'
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:12-alpine
|
||||
image: ${{ matrix.version.docker-image }}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
@@ -684,55 +786,24 @@ jobs:
|
||||
POSTGRES_DB: mb_test
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test Postgres driver (12)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-postgres-ee'
|
||||
|
||||
be-tests-postgres-latest-ee:
|
||||
needs: files-changed
|
||||
if: github.event.pull_request.draft == false && needs.files-changed.outputs.backend_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
CI: 'true'
|
||||
DRIVERS: postgres
|
||||
MB_DB_TYPE: postgres
|
||||
MB_DB_PORT: 5432
|
||||
MB_DB_HOST: localhost
|
||||
MB_DB_DBNAME: circle_test
|
||||
MB_DB_USER: circle_test
|
||||
MB_POSTGRESQL_TEST_USER: circle_test
|
||||
MB_POSTGRES_SSL_TEST_SSL: true
|
||||
MB_POSTGRES_SSL_TEST_SSL_MODE: verify-full
|
||||
MB_POSTGRES_SSL_TEST_SSL_ROOT_CERT_PATH: 'test-resources/certificates/us-east-2-bundle.pem'
|
||||
services:
|
||||
postgres:
|
||||
image: circleci/postgres:latest
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env:
|
||||
POSTGRES_USER: circle_test
|
||||
POSTGRES_DB: circle_test
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test Postgres driver (latest)
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-postgres-latest-ee'
|
||||
- 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 }}
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test ${{ matrix.version.name }} (${{ matrix.job.name }})
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-${{ matrix.version.junit-name }}'
|
||||
test-args: >-
|
||||
${{ matrix.job.test-args }}
|
||||
- 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-presto-jdbc-ee:
|
||||
needs: files-changed
|
||||
@@ -759,30 +830,37 @@ jobs:
|
||||
JAVA_TOOL_OPTIONS: "-Xmx2g"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Wait for port ${{ env.MB_PRESTO_JDBC_TEST_PORT }} to be ready
|
||||
run: while ! nc -z localhost ${{ env.MB_PRESTO_JDBC_TEST_PORT }}; do sleep 0.1; done
|
||||
timeout-minutes: 15
|
||||
- uses: ./.github/actions/await-port
|
||||
with:
|
||||
port: ${{ env.MB_PRESTO_JDBC_TEST_PORT }}
|
||||
timeout-minutes: 5
|
||||
- name: Create temp cacerts file based on bundled JDK one
|
||||
run: cp $JAVA_HOME/lib/security/cacerts /tmp/cacerts-with-presto-ssl.jks
|
||||
- name: Capture Presto server self signed CA
|
||||
run: |
|
||||
while [[ ! -s /tmp/presto-ssl-ca.pem ]];
|
||||
do echo "Waiting to capture SSL CA" \
|
||||
while [[ ! -s /tmp/presto-ssl-ca.pem ]]; do
|
||||
echo "Waiting to capture SSL CA" \
|
||||
&& openssl s_client -connect localhost:8443 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/presto-ssl-ca.pem \
|
||||
&& sleep 1; done
|
||||
&& sleep 1;
|
||||
done
|
||||
- name: Convert Presto CA from PEM to DER
|
||||
run: openssl x509 -outform der -in /tmp/presto-ssl-ca.pem -out /tmp/presto-ssl-ca.der
|
||||
- name: Add write permission on cacerts file
|
||||
run: chmod u+w /tmp/cacerts-with-presto-ssl.jks
|
||||
- name: Import Presto CA into temp cacerts file
|
||||
run: |
|
||||
keytool -noprompt -import -alias presto -keystore /tmp/cacerts-with-presto-ssl.jks \
|
||||
-storepass changeit -file /tmp/presto-ssl-ca.der -trustcacerts
|
||||
run: >-
|
||||
keytool -noprompt -import
|
||||
-alias presto
|
||||
-keystore /tmp/cacerts-with-presto-ssl.jks
|
||||
-storepass changeit
|
||||
-file /tmp/presto-ssl-ca.der
|
||||
-trustcacerts
|
||||
- name: Test Presto JDBC driver
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-presto-jdbc-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -813,7 +891,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-redshift-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -851,7 +930,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-snowflake-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -883,7 +963,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-sparksql-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -910,7 +991,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-sqlite-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -949,7 +1031,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-sqlserver-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -988,7 +1071,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-sqlserver-2022-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -1022,7 +1106,8 @@ jobs:
|
||||
uses: ./.github/actions/test-driver
|
||||
with:
|
||||
junit-name: 'be-tests-vertica-ee'
|
||||
test-args: ":exclude-tags '[:mb/once]'"
|
||||
test-args: >-
|
||||
:only-tags [:mb/driver-tests]
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
@@ -1034,3 +1119,41 @@ jobs:
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
# Dummy job generator to spit out fake runs for matrix jobs we skipped. See
|
||||
# https://github.com/orgs/community/discussions/9141 and
|
||||
# https://metaboat.slack.com/archives/C0669P4AF9N/p1732315370301059
|
||||
be-driver-tests-skipped-stub:
|
||||
needs: files-changed
|
||||
if: |
|
||||
!cancelled() &&
|
||||
(github.event.pull_request.draft == true ||
|
||||
needs.files-changed.outputs.backend_all == 'false')
|
||||
strategy:
|
||||
matrix:
|
||||
job:
|
||||
- "Test Postgres 12.x (App DB Tests)"
|
||||
- "Test Postgres 12.x (Driver Tests)"
|
||||
- "Test Postgres Latest (App DB Tests)"
|
||||
- "Test Postgres Latest (Driver Tests)"
|
||||
- "be-tests-mariadb-10-2-ee (0)"
|
||||
- "be-tests-mariadb-10-2-ee (1)"
|
||||
- "be-tests-mariadb-10-2-ee (2)"
|
||||
- "be-tests-mariadb-10-2-ee (3)"
|
||||
- "be-tests-mariadb-latest-ee (0)"
|
||||
- "be-tests-mariadb-latest-ee (1)"
|
||||
- "be-tests-mariadb-latest-ee (2)"
|
||||
- "be-tests-mariadb-latest-ee (3)"
|
||||
- "be-tests-mysql-8-0-ee (0)"
|
||||
- "be-tests-mysql-8-0-ee (1)"
|
||||
- "be-tests-mysql-8-0-ee (2)"
|
||||
- "be-tests-mysql-8-0-ee (3)"
|
||||
- "be-tests-mysql-latest-ee (0)"
|
||||
- "be-tests-mysql-latest-ee (1)"
|
||||
- "be-tests-mysql-latest-ee (2)"
|
||||
- "be-tests-mysql-latest-ee (3)"
|
||||
name: ${{ matrix.job }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- run: >-
|
||||
echo 'Skipping job due to conditional filtering'
|
||||
|
||||
250
.github/workflows/e2e-component-tests-embedding-sdk-cross-version.yml
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
name: E2E Cross-version Component Tests for Embedding SDK
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "release-**"
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
branches:
|
||||
- "release-**"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
e2e_all: ${{ steps.changes.outputs.e2e_all }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test which files changed
|
||||
uses: dorny/paths-filter@v3.0.0
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
# if this is a test on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
if: |
|
||||
!cancelled()
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
|
||||
node_version: ${{ fromJson(steps.dependencies.outputs.result).node_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get build dependencies
|
||||
uses: actions/github-script@v7
|
||||
id: dependencies
|
||||
with:
|
||||
script: | # js
|
||||
const {
|
||||
getBuildRequirements,
|
||||
getVersionFromReleaseBranch,
|
||||
} = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const targetBranchName = '${{ github.base_ref || github.ref }}';
|
||||
|
||||
const version = getVersionFromReleaseBranch(targetBranchName);
|
||||
const requirements = getBuildRequirements(version);
|
||||
|
||||
return {
|
||||
java_version: requirements.java,
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
build:
|
||||
needs: [files-changed, get-build-requirements]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
INTERACTIVE: false
|
||||
# make sure that builds on release branches get licenses, because we use them for releases
|
||||
SKIP_LICENSES: ${{ github.event_name == 'pull_request' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
with:
|
||||
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: uberjar
|
||||
java-version: "${{ needs.get-build-requirements.outputs.java_version || 11 }}"
|
||||
|
||||
- name: Build uberjar with ./bin/build.sh
|
||||
run: ./bin/build.sh
|
||||
|
||||
- name: Prepare uberjar artifact
|
||||
uses: ./.github/actions/prepare-uberjar-artifact
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
resolve-sdk-version:
|
||||
if: |
|
||||
!cancelled()
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
sdk_version: ${{ fromJson(steps.dependencies.outputs.result).sdk_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get latest SDK release for this branch
|
||||
uses: actions/github-script@v7
|
||||
id: dependencies
|
||||
with:
|
||||
script: | # js
|
||||
const { getSdkVersionFromReleaseBranchName } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const branchName = '${{ github.base_ref || github.ref }}';
|
||||
|
||||
const sdk_version = await getSdkVersionFromReleaseBranchName({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
branchName,
|
||||
});
|
||||
|
||||
return {
|
||||
sdk_version,
|
||||
};
|
||||
|
||||
e2e-tests:
|
||||
needs: [get-build-requirements, build, resolve-sdk-version]
|
||||
if: |
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
name: e2e-tests-embedding-sdk
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
DISPLAY: ""
|
||||
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
|
||||
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
|
||||
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
|
||||
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
|
||||
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
|
||||
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
|
||||
TZ: US/Pacific # to make node match the instance tz
|
||||
CYPRESS_CI: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Docker containers
|
||||
uses: ./.github/actions/e2e-prepare-containers
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Needed to omit newly added tests for functionality that is not yet released
|
||||
- name: Sparse checkout tests from SDK release commit
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: embedding-sdk-${{ needs.resolve-sdk-version.outputs.sdk_version }}
|
||||
path: sdk-release-e2e
|
||||
sparse-checkout: e2e
|
||||
|
||||
- name: Move tests from the release commit into the repo
|
||||
run: |
|
||||
rm -rf ./e2e/support/helpers/*
|
||||
mv ./sdk-release-e2e/e2e/support/helpers/* ./e2e/support/helpers
|
||||
rm -rf ./e2e/test-component/*
|
||||
mv ./sdk-release-e2e/e2e/test-component/* ./e2e/test-component
|
||||
shell: bash
|
||||
|
||||
- name: Retrieve uberjar artifact for ee
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
- name: Get the version info
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar version.properties
|
||||
mv version.properties resources/
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
|
||||
- name: Prepare JDK ${{ needs.get-build-requirements.outputs.java_version || 11 }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ needs.get-build-requirements.outputs.java_version || 11 }}
|
||||
distribution: "temurin"
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
|
||||
- name: Install Embedding SDK package v${{ needs.resolve-sdk-version.outputs.sdk_version }}
|
||||
run: yarn add @metabase/embedding-sdk-react@${{ needs.resolve-sdk-version.outputs.sdk_version }}
|
||||
|
||||
- name: Run E2E tests for Embedding SDK
|
||||
run: yarn run test-cypress-run-component-sdk --browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit
|
||||
output-name: e2e-embedding-sdk
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
- name: Upload Cypress Artifacts upon failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: cypress-recording-embedding-sdk-cross-version
|
||||
path: |
|
||||
./cypress
|
||||
./logs/test.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Publish Summary
|
||||
if: failure()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | #js
|
||||
const {
|
||||
parseReport,
|
||||
formatSummary
|
||||
} = require("./.github/scripts/handle-mochawesome-report.js");
|
||||
|
||||
const report = parseReport();
|
||||
const summary = formatSummary(report);
|
||||
|
||||
await core.summary.addRaw(summary).write();
|
||||
|
||||
e2e-tests-skipped-stub:
|
||||
needs: [e2e-tests]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.e2e-tests.result == 'skipped'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
name: e2e-component-tests-embedding-sdk-cross-version
|
||||
steps:
|
||||
- run: |
|
||||
echo "Didn't run due to conditional filtering"
|
||||
212
.github/workflows/e2e-component-tests-embedding-sdk.yml
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
name: E2E Component Tests for Embedding SDK
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "release-**"
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
e2e_all: ${{ steps.changes.outputs.e2e_all }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test which files changed
|
||||
uses: dorny/paths-filter@v3.0.0
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
# if this is a test on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
if: |
|
||||
!cancelled() &&
|
||||
contains(github.base_ref || github.ref, 'release-x')
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
java_version: ${{ fromJson(steps.dependencies.outputs.result).java_version }}
|
||||
node_version: ${{ fromJson(steps.dependencies.outputs.result).node_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Get build dependencies
|
||||
uses: actions/github-script@v7
|
||||
id: dependencies
|
||||
with:
|
||||
script: | # js
|
||||
const {
|
||||
getBuildRequirements,
|
||||
getVersionFromReleaseBranch,
|
||||
} = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const targetBranchName = '${{ github.base_ref || github.ref }}';
|
||||
|
||||
const version = getVersionFromReleaseBranch(targetBranchName);
|
||||
const requirements = getBuildRequirements(version);
|
||||
|
||||
return {
|
||||
java_version: requirements.java,
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
build:
|
||||
needs: [files-changed, get-build-requirements]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
github.event.pull_request.draft == false &&
|
||||
needs.files-changed.outputs.e2e_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
INTERACTIVE: false
|
||||
# make sure that builds on release branches get licenses, because we use them for releases
|
||||
SKIP_LICENSES: ${{ github.event_name == 'pull_request' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
with:
|
||||
node-version: "${{ needs.get-build-requirements.outputs.node_version }}"
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
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
|
||||
|
||||
e2e-tests:
|
||||
needs: [get-build-requirements, build]
|
||||
if: |
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
name: e2e-tests-embedding-sdk
|
||||
env:
|
||||
MB_EDITION: ee
|
||||
DISPLAY: ""
|
||||
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
|
||||
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
|
||||
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
|
||||
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
|
||||
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
|
||||
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
|
||||
TZ: US/Pacific # to make node match the instance tz
|
||||
CYPRESS_CI: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Docker containers
|
||||
uses: ./.github/actions/e2e-prepare-containers
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Retrieve uberjar artifact for ee
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-ee-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
- name: Get the version info
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar version.properties
|
||||
mv version.properties resources/
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
|
||||
- name: Prepare JDK ${{ needs.get-build-requirements.outputs.java_version || 11 }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ needs.get-build-requirements.outputs.java_version || 11 }}
|
||||
distribution: "temurin"
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: "cljs"
|
||||
|
||||
- name: Compile CLJS
|
||||
run: yarn build-pure:cljs
|
||||
shell: bash
|
||||
|
||||
- name: Build Embedding SDK package
|
||||
run: yarn build-embedding-sdk
|
||||
|
||||
- name: Run E2E tests for Embedding SDK
|
||||
run: yarn run test-cypress-run-component-sdk --browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit
|
||||
output-name: e2e-embedding-sdk
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
- name: Upload Cypress Artifacts upon failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: cypress-recording-embedding-sdk-latest
|
||||
path: |
|
||||
./cypress
|
||||
./logs/test.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Publish Summary
|
||||
if: failure()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | #js
|
||||
const {
|
||||
parseReport,
|
||||
formatSummary
|
||||
} = require("./.github/scripts/handle-mochawesome-report.js");
|
||||
|
||||
const report = parseReport();
|
||||
const summary = formatSummary(report);
|
||||
|
||||
await core.summary.addRaw(summary).write();
|
||||
|
||||
e2e-tests-skipped-stub:
|
||||
needs: [e2e-tests]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.e2e-tests.result == 'skipped'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
name: e2e-component-tests-embedding-sdk
|
||||
steps:
|
||||
- run: |
|
||||
echo "Didn't run due to conditional filtering"
|
||||
2
.github/workflows/e2e-cross-version.yml
vendored
@@ -9,6 +9,8 @@ on:
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Check which files changed
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 3
|
||||
outputs:
|
||||
|
||||
91
.github/workflows/e2e-matrix-builder.yml
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
name: E2E Matrix Builder
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
chunks:
|
||||
required: true
|
||||
type: number
|
||||
default: 30
|
||||
outputs:
|
||||
matrix:
|
||||
value: ${{ jobs.build-matrix.outputs.matrix }}
|
||||
|
||||
jobs:
|
||||
build-matrix:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
matrix: ${{ steps.matrix.outputs.config }}
|
||||
steps:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '20.x'
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: e2e
|
||||
- name: get test file names
|
||||
id: test-files
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::set-output name=filenames::$(find e2e/test/scenarios -name '*.cy.spec.*' | tr '\n' ',')"
|
||||
- run: yarn add underscore
|
||||
- uses: actions/github-script@v7
|
||||
id: matrix
|
||||
with:
|
||||
script: | # js
|
||||
const _ = require('underscore');
|
||||
|
||||
const java = 21;
|
||||
const defaultRunner = "ubuntu-22.04";
|
||||
|
||||
// these are special and shouldn't be chunked out arbitrarily
|
||||
const blacklist = [
|
||||
"/embedding-sdk/",
|
||||
"/cross-version/"
|
||||
];
|
||||
|
||||
const defaultOptions = {
|
||||
"java-version": java,
|
||||
runner: defaultRunner,
|
||||
specs: "./e2e/test/scenarios/**/*.cy.spec.*",
|
||||
edition: "ee",
|
||||
};
|
||||
|
||||
const specialTests = [
|
||||
{ name: "embedding-sdk", specs: "./e2e/test/scenarios/embedding-sdk/**.cy.spec.*" },
|
||||
{ name: "oss-subset", edition: 'oss', tags: "@OSS" },
|
||||
{ name: "slow", tags: "@slow" },
|
||||
{ name: "mongo", tags: "@mongo" },
|
||||
];
|
||||
|
||||
const fileNames = "${{ steps.test-files.outputs.filenames }}"
|
||||
.split(",")
|
||||
.filter(Boolean)
|
||||
.filter(testPath => !blacklist.some(blacklisted => testPath.includes(blacklisted)));
|
||||
|
||||
const fileCount = fileNames.length;
|
||||
|
||||
// subtract the special tests since they all get their own runners
|
||||
const chunkSize = fileCount / (Number('${{ inputs.chunks }}') - specialTests.length);
|
||||
|
||||
|
||||
|
||||
const chunkedFiles = _.chunk(fileNames, chunkSize);
|
||||
|
||||
const regularTests = chunkedFiles.map((files, index) => ({
|
||||
name: `e2e-group-${index + 1}`,
|
||||
specs: files.join(","),
|
||||
tags: '',
|
||||
}));
|
||||
|
||||
const testSets = [...regularTests, ...specialTests];
|
||||
|
||||
const config = testSets.map((options) => ({
|
||||
...defaultOptions,
|
||||
...options,
|
||||
}));
|
||||
|
||||
console.log("matrix config", config);
|
||||
|
||||
core.setOutput("config", JSON.stringify({ include: config }));
|
||||
@@ -87,10 +87,10 @@ jobs:
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Prepare JDK 11
|
||||
- name: Prepare JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 21
|
||||
distribution: "temurin"
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
|
||||
151
.github/workflows/e2e-test.yml
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
name: E2E Test
|
||||
run-name: E2E Test - ${{ inputs.name }}
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
name:
|
||||
required: true
|
||||
type: string
|
||||
edition: # oss | ee
|
||||
required: false
|
||||
type: string
|
||||
default: ee
|
||||
specs:
|
||||
required: false
|
||||
default: ./e2e/test/scenarios/**/*.cy.spec.*
|
||||
type: string
|
||||
tags:
|
||||
required: false
|
||||
type: string
|
||||
runner:
|
||||
required: false
|
||||
type: string
|
||||
default: ubuntu-22.04
|
||||
|
||||
jobs:
|
||||
e2e-tests:
|
||||
runs-on: ${{ inputs.runner }}
|
||||
timeout-minutes: 45
|
||||
name: e2e-tests-${{ inputs.name }}-${{ inputs.edition }}
|
||||
env:
|
||||
MB_EDITION: ${{ inputs.edition }}
|
||||
DISPLAY: ""
|
||||
QA_DB_ENABLED: true
|
||||
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
|
||||
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
|
||||
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
|
||||
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
|
||||
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
|
||||
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.event.head.sha }}
|
||||
MB_SNOWPLOW_AVAILABLE: true
|
||||
MB_SNOWPLOW_URL: "http://localhost:9090" # Snowplow micro
|
||||
TZ: US/Pacific # to make node match the instance tz
|
||||
CYPRESS_CI: true
|
||||
CYPRESS_QA_DB_MONGO: ${{ inputs.name == 'mongo' }}
|
||||
CYPRESS_IS_EMBEDDING_SDK: ${{ inputs.name == 'embedding-sdk' }}
|
||||
mongo: ${{ inputs.name == 'mongo' }}
|
||||
postgres: ${{ inputs.name != 'mongo' }}
|
||||
mysql: ${{ inputs.name != 'mongo' }}
|
||||
openldap: ${{ contains(inputs.specs, 'ldap') }}
|
||||
maildev: true
|
||||
webhook: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Docker containers
|
||||
uses: ./.github/actions/e2e-prepare-containers
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
maildev: true
|
||||
openldap: ${{ env.openldap }}
|
||||
postgres: ${{ env.postgres }}
|
||||
mysql: ${{ env.mysql }}
|
||||
mongo: ${{ env.mongo }}
|
||||
webhook: ${{ env.webhook }}
|
||||
|
||||
- name: Run Embedding SDK Storybook
|
||||
if: inputs.name == 'embedding-sdk'
|
||||
uses: ./.github/actions/run-embedding-sdk-storybook
|
||||
|
||||
- name: Retrieve uberjar artifact for ${{ inputs.edition }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-${{ inputs.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
- name: Get the version info
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar version.properties
|
||||
mv version.properties resources/
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
|
||||
- name: Prepare JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 21
|
||||
distribution: "temurin"
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
|
||||
- name: Run Snowplow micro
|
||||
uses: ./.github/actions/run-snowplow-micro
|
||||
|
||||
- name: Run EE Cypress tests on ${{ inputs.name }}
|
||||
if: ${{ !inputs.tags }}
|
||||
shell: bash
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="-@slow+-@mongo+-@flaky+-@OSS --@quarantine",grepOmitFiltered=true \
|
||||
--spec '${{ inputs.specs }}' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run Tagged EE Cypress tests on ${{ inputs.name }}
|
||||
if: ${{ inputs.tags }}
|
||||
shell: bash
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="${{inputs.tags}} --@quarantine",grepOmitFiltered=true \
|
||||
--spec '${{ inputs.specs }}' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit
|
||||
output-name: e2e-${{ inputs.name }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
- name: Upload Cypress Artifacts upon failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: cypress-recording-${{ inputs.name }}-${{ inputs.edition }}
|
||||
path: |
|
||||
./cypress
|
||||
./logs/test.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Publish Summary
|
||||
if: failure()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | #js
|
||||
const {
|
||||
parseReport,
|
||||
formatSummary
|
||||
} = require("./.github/scripts/handle-mochawesome-report.js");
|
||||
|
||||
const report = parseReport();
|
||||
const summary = formatSummary(report);
|
||||
|
||||
await core.summary.addRaw(summary).write();
|
||||
221
.github/workflows/e2e-tests.yml
vendored
@@ -29,15 +29,9 @@ jobs:
|
||||
filters: .github/file-paths.yaml
|
||||
|
||||
e2e-matrix-builder:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
matrix: ${{ steps.e2e-matrix.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Generate matrix for E2E tests
|
||||
id: e2e-matrix
|
||||
uses: ./.github/actions/build-e2e-matrix
|
||||
uses: ./.github/workflows/e2e-matrix-builder.yml
|
||||
with:
|
||||
chunks: 50
|
||||
|
||||
# if this is a test on a release branch, we need to check the build requirements
|
||||
get-build-requirements:
|
||||
@@ -70,12 +64,12 @@ jobs:
|
||||
node_version: requirements.node,
|
||||
};
|
||||
|
||||
|
||||
build:
|
||||
needs: [files-changed, e2e-matrix-builder, get-build-requirements]
|
||||
needs: [files-changed, get-build-requirements]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
github.event.pull_request.draft == false &&
|
||||
needs.e2e-matrix-builder.result == 'success' &&
|
||||
needs.files-changed.outputs.e2e_all == 'true'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 25
|
||||
@@ -108,179 +102,58 @@ jobs:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
e2e-tests:
|
||||
name: ${{ matrix.name }}-${{ matrix.edition }}
|
||||
uses: ./.github/workflows/e2e-test.yml
|
||||
needs: [build, e2e-matrix-builder]
|
||||
if: |
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 45
|
||||
name: e2e-tests-${{ matrix.name }}-${{ matrix.edition }}
|
||||
env:
|
||||
MB_EDITION: ${{ matrix.edition }}
|
||||
DISPLAY: ""
|
||||
QA_DB_ENABLED: true
|
||||
# Any env starting with `CYPRESS_` will be available to all Cypress tests via `Cypress.env()`
|
||||
# Example: you can get `CYPRESS_FOO` with `Cypress.env("FOO")`
|
||||
CYPRESS_ALL_FEATURES_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }}
|
||||
CYPRESS_NO_FEATURES_TOKEN: ${{ secrets.E2E_STARTER_TOKEN }}
|
||||
CYPRESS_PULL_REQUEST_ID: ${{ github.event.pull_request.number || '' }}
|
||||
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title || github.event.head_commit.message || github.even.head.sha }}
|
||||
MB_SNOWPLOW_AVAILABLE: true
|
||||
MB_SNOWPLOW_URL: "http://localhost:9090" # Snowplow micro
|
||||
TZ: US/Pacific # to make node match the instance tz
|
||||
CYPRESS_CI: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJSON(needs.e2e-matrix-builder.outputs.matrix) }}
|
||||
matrix: ${{ fromJson(needs.e2e-matrix-builder.outputs.matrix) }}
|
||||
secrets: inherit
|
||||
with:
|
||||
name: ${{ matrix.name }}
|
||||
edition: ${{ matrix.edition }}
|
||||
specs: ${{ matrix.specs }}
|
||||
tags: ${{ matrix.tags }}
|
||||
runner: ${{ matrix.runner }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare Docker containers
|
||||
uses: ./.github/actions/e2e-prepare-containers
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
maildev: true
|
||||
openldap: ${{ startsWith(matrix.name, 'admin') }}
|
||||
postgres: ${{ matrix.name != 'mongo'}}
|
||||
mysql: ${{ matrix.name != 'mongo'}}
|
||||
mongo: ${{ matrix.name == 'mongo'}}
|
||||
webhook: true
|
||||
|
||||
- name: Retrieve uberjar artifact for ${{ matrix.edition }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
|
||||
|
||||
- name: Get the version info
|
||||
run: |
|
||||
jar xf target/uberjar/metabase.jar version.properties
|
||||
mv version.properties resources/
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
|
||||
- name: Prepare JDK ${{ matrix.java-version }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ matrix.java-version }}
|
||||
distribution: "temurin"
|
||||
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
uses: ./.github/actions/prepare-cypress
|
||||
|
||||
- name: Run Snowplow micro
|
||||
uses: ./.github/actions/run-snowplow-micro
|
||||
|
||||
- name: Run OSS-specific Cypress tests
|
||||
if: matrix.edition == 'oss' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags=@OSS,grepOmitFiltered=true \
|
||||
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run slow and resource-intensive Cypress tests
|
||||
if: matrix.name == 'slow' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="@slow",grepOmitFiltered=true \
|
||||
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run Flaky Cypress tests
|
||||
if: matrix.name == 'flaky' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="@flaky --@quarantine",grepOmitFiltered=true \
|
||||
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run EE Cypress tests on ${{ matrix.name }}
|
||||
if: matrix.context == 'folder' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="-@slow+-@mongo+-@flaky --@quarantine",grepOmitFiltered=true \
|
||||
--folder ${{ matrix.name }} \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
|
||||
- name: Run E2E tests that depend on Mongo
|
||||
if: matrix.name == 'mongo'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="@mongo --@quarantine",grepOmitFiltered=true \
|
||||
--spec './e2e/test/scenarios/**/*.cy.spec.(js|ts)' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
env:
|
||||
CYPRESS_QA_DB_MONGO: true
|
||||
|
||||
- name: Run Embedding SDK Storybook
|
||||
if: matrix.context == 'embedding-sdk' && github.event_name != 'schedule'
|
||||
uses: ./.github/actions/run-embedding-sdk-storybook
|
||||
|
||||
- name: Run E2E tests for Embedding SDK
|
||||
if: matrix.context == 'embedding-sdk' && github.event_name != 'schedule'
|
||||
run: |
|
||||
yarn run test-cypress-run \
|
||||
--env grepTags="-@slow+-@flaky --@quarantine",grepOmitFiltered=true \
|
||||
--folder 'embedding-sdk' \
|
||||
--browser ${{ steps.cypress-prep.outputs.chrome-path }}
|
||||
env:
|
||||
CYPRESS_IS_EMBEDDING_SDK: true
|
||||
shell: bash
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: ./.github/actions/upload-test-results
|
||||
if: always()
|
||||
with:
|
||||
input-path: ./target/junit
|
||||
output-name: e2e-${{ matrix.name }}
|
||||
bucket: ${{ vars.AWS_S3_TEST_RESULTS_BUCKET }}
|
||||
aws-access-key-id: ${{ secrets.AWS_TEST_RESULTS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_TEST_RESULTS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
trunk-api-token: ${{ secrets.TRUNK_API_TOKEN }}
|
||||
|
||||
- name: Upload Cypress Artifacts upon failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: cypress-recording-${{ matrix.name }}-${{ matrix.edition }}
|
||||
path: |
|
||||
./cypress
|
||||
./logs/test.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Publish Summary
|
||||
if: failure()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | #js
|
||||
const {
|
||||
parseReport,
|
||||
formatSummary
|
||||
} = require("./.github/scripts/handle-mochawesome-report.js");
|
||||
|
||||
const report = parseReport();
|
||||
const summary = formatSummary(report);
|
||||
|
||||
await core.summary.addRaw(summary).write();
|
||||
|
||||
e2e-tests-skipped-stub:
|
||||
needs: [e2e-tests, e2e-matrix-builder]
|
||||
# run this separately to make it non-blocking
|
||||
flaky-e2e-tests:
|
||||
name: Flaky e2e Tests
|
||||
uses: ./.github/workflows/e2e-test.yml
|
||||
needs: build
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.e2e-tests.result == 'skipped'
|
||||
runs-on: ${{ matrix.runner }}
|
||||
!cancelled() && needs.build.result == 'success'
|
||||
secrets: inherit
|
||||
with:
|
||||
name: Flaky
|
||||
tags: "@flaky"
|
||||
|
||||
e2e-tests-result:
|
||||
needs: [e2e-tests, flaky-e2e-tests]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
name: e2e-tests-${{ matrix.name }}-${{ matrix.edition }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJSON(needs.e2e-matrix-builder.outputs.matrix) }}
|
||||
name: e2e-tests-result
|
||||
if: always() && !cancelled()
|
||||
env:
|
||||
E2E_TESTS_RESULT: ${{ needs.e2e-tests.result }}
|
||||
FLAKY_E2E_TESTS_RESULT: ${{ needs.flaky-e2e-tests.result }}
|
||||
steps:
|
||||
- run: |
|
||||
- name: Stub
|
||||
if: ${{ needs.e2e-tests.result == 'skipped' }}
|
||||
run: |
|
||||
echo "Didn't run due to conditional filtering"
|
||||
- name: Test results
|
||||
if: ${{ needs.e2e-tests.result != 'skipped' }}
|
||||
run: | # sh
|
||||
echo "E2E Tests: ${{ needs.e2e-tests.result }}"
|
||||
echo "Flaky E2E Tests: ${{ needs.flaky-e2e-tests.result }}"
|
||||
|
||||
if [ "${{ needs.e2e-tests.result }}" != "success" ]; then
|
||||
echo "E2E Tests failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pr-env:
|
||||
needs: [build]
|
||||
|
||||
2
.github/workflows/flake-issue-creator.yml
vendored
@@ -7,6 +7,8 @@ on:
|
||||
|
||||
jobs:
|
||||
flake-issue-creator:
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
|
||||
2
.github/workflows/flake-status.yml
vendored
@@ -7,6 +7,8 @@ on:
|
||||
|
||||
jobs:
|
||||
flake-status-report:
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
|
||||
32
.github/workflows/links.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Links
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 0 * * 0"
|
||||
|
||||
jobs:
|
||||
linkChecker:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write # required for peter-evans/create-issue-from-file
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Link Checker
|
||||
id: lychee
|
||||
uses: lycheeverse/lychee-action@v2
|
||||
with:
|
||||
fail: false
|
||||
args: docs --config ./lychee/config.toml --verbose --no-progress
|
||||
format: markdown
|
||||
|
||||
- name: Create Issue From File
|
||||
if: steps.lychee.outputs.exit_code != 0
|
||||
uses: peter-evans/create-issue-from-file@v5
|
||||
with:
|
||||
title: Link Checker Report
|
||||
content-filepath: ./lychee/out.md
|
||||
labels: "Type:Documentation"
|
||||
assignees: jeff-bruemmer
|
||||
4
.github/workflows/loki-update.yml
vendored
@@ -61,9 +61,9 @@ jobs:
|
||||
with:
|
||||
github-token: ${{secrets.METABASE_AUTOMATION_USER_TOKEN}}
|
||||
script: |
|
||||
github.issues.removeLabel({
|
||||
github.rest.issues.removeLabel({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: 'loki-update'
|
||||
})
|
||||
});
|
||||
|
||||
1
.github/workflows/loki.yml
vendored
@@ -83,5 +83,6 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: loki-report
|
||||
include-hidden-files: true
|
||||
path: .loki/
|
||||
if-no-files-found: ignore
|
||||
|
||||
38
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Slack Notification for New Feature Requests
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- labeled
|
||||
jobs:
|
||||
on-issue-labeled:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
if: |
|
||||
contains(github.event.issue.labels.*.name, 'Type:New Feature')
|
||||
steps:
|
||||
- name: Setting title
|
||||
uses: actions/github-script@v7
|
||||
id: vars
|
||||
with:
|
||||
script: |
|
||||
core.setOutput('issue_title', ${{ toJson(github.event.issue.title) }}.replaceAll(/"/g, '\\"'));
|
||||
- name: Send the issue ${{ github.event.issue.number }} to Slack
|
||||
id: slack
|
||||
uses: slackapi/slack-github-action@v1.26.0
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "New incoming feature request: ${{ steps.vars.outputs.issue_title }}\n${{ github.event.issue.html_url }}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_FEATURE_REQUEST_TRIAGE_WEBHOOK_URL }}
|
||||
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|
||||
64
.github/workflows/pre-release.yml
vendored
@@ -10,11 +10,18 @@ on:
|
||||
required: true
|
||||
commit:
|
||||
description: "A full-length commit SHA-1 hash"
|
||||
type: string
|
||||
required: true
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
description: "Metabase version (e.g. v0.46.3)"
|
||||
type: string
|
||||
required: true
|
||||
commit:
|
||||
description: "A full-length commit SHA-1 hash"
|
||||
type: string
|
||||
required: true
|
||||
auto:
|
||||
description: 'auto-patch release DO NOT SET MANUALLY'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
release-artifact:
|
||||
@@ -79,7 +86,7 @@ jobs:
|
||||
- name: Upload Metabase ${{ matrix.edition }} JAR as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-uberjar
|
||||
name: metabase-test-${{ matrix.edition }}-uberjar
|
||||
path: |
|
||||
./metabase.jar
|
||||
./COMMIT-ID
|
||||
@@ -93,7 +100,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [oss, ee]
|
||||
java-version: [11, 17]
|
||||
java-version: [11, 17, 21]
|
||||
steps:
|
||||
- name: Prepare JRE (Java Run-time Environment)
|
||||
uses: actions/setup-java@v4
|
||||
@@ -105,9 +112,10 @@ jobs:
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Retrieve uberjar artifact
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-uberjar
|
||||
name: metabase-test-${{ matrix.edition }}-uberjar
|
||||
- name: Launch uberjar (and keep it running)
|
||||
run: java -jar ./metabase.jar &
|
||||
run: >-
|
||||
java --add-opens java.base/java.nio=ALL-UNNAMED -jar ./metabase.jar &
|
||||
- name: Wait for Metabase to start
|
||||
run: while ! curl -s 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
|
||||
|
||||
@@ -142,10 +150,10 @@ jobs:
|
||||
maildev: true
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Prepare JDK 11
|
||||
- name: Prepare JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 21
|
||||
distribution: "temurin"
|
||||
- name: Prepare Cypress environment
|
||||
id: cypress-prep
|
||||
@@ -155,7 +163,7 @@ jobs:
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Retrieve uberjar artifact for ${{ matrix.edition }}
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-uberjar
|
||||
name: metabase-test-${{ matrix.edition }}-uberjar
|
||||
- name: Get the version info
|
||||
run: |
|
||||
jar xf metabase.jar version.properties
|
||||
@@ -207,16 +215,16 @@ jobs:
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Retrieve uberjar artifact
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-uberjar
|
||||
name: metabase-test-${{ matrix.edition }}-uberjar
|
||||
- name: Move the Uberjar to the context dir
|
||||
run: mv metabase.jar bin/docker/.
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver-opts: network=host
|
||||
- name: Build ${{ matrix.edition }} container
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: bin/docker/.
|
||||
platforms: linux/amd64
|
||||
@@ -233,7 +241,7 @@ jobs:
|
||||
timeout-minutes: 3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_RELEASE_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_RELEASE_TOKEN }}
|
||||
@@ -270,7 +278,7 @@ jobs:
|
||||
IMAGE_TAG: ${{ needs.containerize.outputs.image_tag }}
|
||||
steps:
|
||||
- name: Login to Docker Hub # authenticated, to avoid being rate-throttled
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_RELEASE_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_RELEASE_TOKEN }}
|
||||
@@ -289,30 +297,6 @@ jobs:
|
||||
run: while ! curl -s 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
|
||||
timeout-minutes: 3
|
||||
|
||||
trigger-auto-publish:
|
||||
if: ${{ inputs.auto }}
|
||||
needs: [run-sanity-check, check-uberjar-health, verify-docker-pull]
|
||||
permissions:
|
||||
actions: write
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: trigger auto publish
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
await github.rest.actions.createWorkflowDispatch({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
workflow_id: 'release.yml',
|
||||
ref: '${{ github.ref }}',
|
||||
inputs: {
|
||||
commit: '${{ inputs.commit }}',
|
||||
version: '${{ inputs.version }}',
|
||||
auto: true,
|
||||
}
|
||||
});
|
||||
|
||||
tests-complete-message:
|
||||
if: always()
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
183
.github/workflows/release-embedding-sdk.yml
vendored
@@ -1,35 +1,97 @@
|
||||
name: Release Metabase Embedding SDK for React
|
||||
run-name: Release SDK from ${{ inputs.branch }}
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
# TODO: Add a version validation, so the workflow won't fail when publishing to npm
|
||||
sdk_version:
|
||||
description: 'SDK version (e.g. 0.1.3)'
|
||||
type: string
|
||||
required: true
|
||||
git_ref:
|
||||
description: 'A git commit hash that will be used to build the SDK'
|
||||
type: string
|
||||
branch:
|
||||
description: "Branch we want to release the SDK from"
|
||||
type: choice
|
||||
required: true
|
||||
default: "master"
|
||||
options:
|
||||
- master
|
||||
- release-x.51.x
|
||||
- release-x.52.x
|
||||
|
||||
concurrency:
|
||||
# We want to ensure only one job is running at a time because
|
||||
# We want to ensure only one job is running at a time per branch because
|
||||
# there could be a conflict when updating the readme file.
|
||||
group: ${{ github.workflow }}
|
||||
group: ${{ github.workflow }}-${{ inputs.branch }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
workflow-summary:
|
||||
name: Log inputs
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Generate workflow summary
|
||||
run: |
|
||||
tee -a $GITHUB_STEP_SUMMARY << EOF
|
||||
**Inputs:**
|
||||
|
||||
- \`branch\`: ${{ inputs.branch }}
|
||||
|
||||
triggered by: @${{ github.event.sender.login }}
|
||||
EOF
|
||||
|
||||
determine-version:
|
||||
name: Determine SDK version
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
outputs:
|
||||
sdk_version: ${{ steps.new-sdk-version.outputs.result }}
|
||||
steps:
|
||||
- name: Check out the code using the provided branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.branch }}
|
||||
|
||||
- name: Get current SDK version
|
||||
id: current-sdk-version
|
||||
run: |
|
||||
VERSION=$(jq -r .version ./enterprise/frontend/src/embedding-sdk/package.template.json)
|
||||
echo "sdk_current_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get next SDK patch version
|
||||
id: new-sdk-version
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
result-encoding: string
|
||||
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(".");
|
||||
|
||||
if (!suffix) {
|
||||
return newVersion;
|
||||
}
|
||||
|
||||
return `${newVersion}-${suffix}`
|
||||
|
||||
- name: Append workflow summary
|
||||
run: |
|
||||
tee -a $GITHUB_STEP_SUMMARY << EOF
|
||||
**Derived inputs:**
|
||||
|
||||
- \`current_version\`: "${{ steps.current-sdk-version.outputs.sdk_current_version }}"
|
||||
- \`next_version\`: "${{ steps.new-sdk-version.outputs.result }}"
|
||||
EOF
|
||||
|
||||
check-git-tag:
|
||||
needs: determine-version
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
tag: embedding-sdk-${{ inputs.sdk_version }}
|
||||
tag: embedding-sdk-${{ needs.determine-version.outputs.sdk_version }}
|
||||
steps:
|
||||
- name: Check out the code using the provided ref
|
||||
- name: Check out the code using the provided branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.git_ref }}
|
||||
ref: ${{ inputs.branch }}
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
@@ -48,10 +110,10 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Check out the code using the provided ref
|
||||
- name: Check out the code using the provided branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.git_ref }}
|
||||
ref: ${{ inputs.branch }}
|
||||
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
@@ -65,14 +127,14 @@ jobs:
|
||||
run: yarn embedding-sdk:test-unit
|
||||
|
||||
build-sdk:
|
||||
needs: test
|
||||
needs: [test, determine-version]
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Check out the code using the provided ref
|
||||
- name: Check out the code using the provided branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.git_ref }}
|
||||
ref: ${{ inputs.branch }}
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
@@ -84,14 +146,10 @@ jobs:
|
||||
with:
|
||||
m2-cache-key: "release-sdk"
|
||||
|
||||
- name: Update readme
|
||||
run: |
|
||||
./bin/embedding-sdk/release_utils.bash update_readme ${{ inputs.sdk_version }}
|
||||
|
||||
- name: Bump published npm package version
|
||||
# NOTE: this should happen before "Build SDK bundle" as we inject SDK version into the code during build step
|
||||
run: |
|
||||
./bin/embedding-sdk/release_utils.bash update_package_json_template ${{ inputs.sdk_version }}
|
||||
./bin/embedding-sdk/release_utils.bash update_package_json_template ${{ needs.determine-version.outputs.sdk_version }}
|
||||
|
||||
- name: Update changelog
|
||||
run: |
|
||||
@@ -115,50 +173,18 @@ jobs:
|
||||
name: sdk-changelog-diff
|
||||
path: ./changelog-diff
|
||||
|
||||
build-jar:
|
||||
needs: test
|
||||
uses: ./.github/workflows/uberjar-sdk.yml
|
||||
with:
|
||||
git_ref: ${{ inputs.git_ref }}
|
||||
image_name: embedding-sdk-${{ inputs.sdk_version }}
|
||||
secrets: inherit
|
||||
|
||||
upload-jar:
|
||||
needs: build-jar
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Retrieve uberjar artifact
|
||||
with:
|
||||
name: metabase-ee-uberjar
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_S3_RELEASE_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_S3_RELEASE_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
|
||||
- name: Upload uberjar to S3
|
||||
env:
|
||||
BUCKET: ${{ vars.AWS_S3_DOWNLOADS_BUCKET }}
|
||||
BUCKET_PATH: sdk/v${{ inputs.sdk_version }}/metabase.jar
|
||||
FILE: ./target/uberjar/metabase.jar
|
||||
shell: bash
|
||||
run: |
|
||||
aws s3 cp $FILE s3://$BUCKET/$BUCKET_PATH
|
||||
|
||||
publish-npm:
|
||||
needs: [build-sdk, upload-jar]
|
||||
needs: [build-sdk, determine-version]
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
sdk_version: ${{ needs.determine-version.outputs.sdk_version }}
|
||||
steps:
|
||||
- name: Check out master to prepare for a SDK version bump PR
|
||||
- name: Check out branch to prepare for a SDK version bump PR
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# when we created version update PR, it would only have diff from 2 files SDK readme and SDK package.json template
|
||||
ref: master
|
||||
ref: ${{ inputs.branch}}
|
||||
|
||||
- name: Setup git user
|
||||
run: |
|
||||
@@ -167,11 +193,11 @@ jobs:
|
||||
|
||||
- name: Update readme
|
||||
run: |
|
||||
bash ./bin/embedding-sdk/release_utils.bash update_readme ${{ inputs.sdk_version }}
|
||||
bash ./bin/embedding-sdk/release_utils.bash update_readme ${{ env.sdk_version }}
|
||||
|
||||
- name: Bump published npm package version
|
||||
run: |
|
||||
bash ./bin/embedding-sdk/release_utils.bash update_package_json_template ${{ inputs.sdk_version }}
|
||||
bash ./bin/embedding-sdk/release_utils.bash update_package_json_template ${{ env.sdk_version }}
|
||||
|
||||
- name: Retrieve SDK changelog diff
|
||||
uses: actions/download-artifact@v4
|
||||
@@ -185,13 +211,13 @@ jobs:
|
||||
|
||||
- name: Create a PR updating readme + published version, and changelog (using GitHub Metabase Automation account)
|
||||
run: |
|
||||
git checkout -b update-sdk-version-${{ inputs.sdk_version }}
|
||||
git commit -a -m 'Update Readme version references and published npm version to ${{ inputs.sdk_version }}'
|
||||
git checkout -b update-sdk-version-${{ env.sdk_version }}
|
||||
git commit -a -m 'Update Readme version references and published npm version to ${{ env.sdk_version }}'
|
||||
git push origin HEAD
|
||||
gh pr create --base master\
|
||||
gh pr create --base ${{ inputs.branch }}\
|
||||
--assignee "${GITHUB_ACTOR}"\
|
||||
--title "Update SDK version to ${{ inputs.sdk_version }}"\
|
||||
--body "Update Readme version references and published npm package version to ${{ inputs.sdk_version }}"
|
||||
--title "Update SDK version to ${{ env.sdk_version }}"\
|
||||
--body "Update Readme version references and published npm package version to ${{ env.sdk_version }}"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
|
||||
@@ -203,7 +229,7 @@ jobs:
|
||||
|
||||
- name: Edit PR adding useful information (using Metabase bot app)
|
||||
run: |
|
||||
gh pr edit --add-reviewer @metabase/embedding --add-label no-backport
|
||||
gh pr edit --add-reviewer @metabase/embedding,albertoperdomo --add-label no-backport
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
@@ -226,22 +252,29 @@ jobs:
|
||||
path: sdk
|
||||
|
||||
- name: Publish to NPM
|
||||
working-directory: sdk
|
||||
run: |
|
||||
cd sdk
|
||||
echo //registry.npmjs.org/:_authToken=${{ secrets.NPM_RELEASE_TOKEN }} > .npmrc
|
||||
npm publish
|
||||
# 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"}')[inputs.branch]}}
|
||||
|
||||
- name: Add `latest` tag to the latest release branch (`release-x.52.x`) deployment
|
||||
if: ${{ inputs.branch == 'release-x.52.x' }}
|
||||
working-directory: sdk
|
||||
run: |
|
||||
npm dist-tag add @metabase/embedding-sdk-react@${{ env.sdk_version }} latest
|
||||
|
||||
git-tag:
|
||||
needs: publish-npm
|
||||
needs: [publish-npm, determine-version]
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
tag: embedding-sdk-${{ inputs.sdk_version }}
|
||||
tag: embedding-sdk-${{ needs.determine-version.outputs.sdk_version }}
|
||||
steps:
|
||||
- name: Check out the code using the provided ref
|
||||
- name: Check out the code using the provided branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.git_ref }}
|
||||
ref: ${{ inputs.branch }}
|
||||
|
||||
# Lightweight tags don't need committer name and email
|
||||
- name: Create a new git tag
|
||||
@@ -249,6 +282,6 @@ jobs:
|
||||
git tag ${{ env.tag }}
|
||||
|
||||
- name: Push the new tag
|
||||
id : push-tag
|
||||
id: push-tag
|
||||
run: |
|
||||
git push origin ${{ env.tag }}
|
||||
|
||||
45
.github/workflows/release-log.yml
vendored
@@ -1,15 +1,21 @@
|
||||
name: Update Release Log
|
||||
run-name: Update Release Log ${{ inputs.version }}
|
||||
run-name: Update Release Log ${{ inputs.version || github.ref_name }}
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- release-x.*
|
||||
tags:
|
||||
- v*
|
||||
- nightly-*
|
||||
- latest-*
|
||||
- beta-*
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Major Metabase version (e.g. 45, 52, 68)'
|
||||
type: number
|
||||
required: true
|
||||
schedule:
|
||||
- cron: '45 * * * *' # hourly
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
@@ -21,9 +27,8 @@ jobs:
|
||||
update-release-log:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
env:
|
||||
VERSION: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call')
|
||||
&& inputs.version || vars.CURRENT_VERSION }}
|
||||
# don't run this workflow for forks
|
||||
if: ${{ github.event_name != 'push' || github.repository == 'metabase/metabase' }}
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
@@ -33,9 +38,37 @@ jobs:
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master # this only works on master
|
||||
fetch-depth: 0 # we want all branches and tags
|
||||
- name: Install Dependencies
|
||||
run: yarn --cwd release --frozen-lockfile && npm i -g tsx
|
||||
- name: Build release scripts
|
||||
run: yarn --cwd release build
|
||||
- name: Get version number
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const {
|
||||
getVersionFromReleaseBranch,
|
||||
getMajorVersion,
|
||||
} = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
console.log({ context });
|
||||
|
||||
// if the version is explicitly set, use that
|
||||
if (context.payload?.inputs?.version) {
|
||||
core.exportVariable('VERSION', context.payload.inputs.version);
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, get the version from the release branch name
|
||||
const branch = context.payload.ref;
|
||||
const version = getVersionFromReleaseBranch(branch);
|
||||
const majorVersion = getMajorVersion(version);
|
||||
|
||||
console.log({ branch, version, majorVersion });
|
||||
core.exportVariable('VERSION', majorVersion);
|
||||
|
||||
- name: generate release Log
|
||||
run: cd release && tsx ./src/release-log-run.ts $VERSION > v$VERSION.html
|
||||
- name: generate release channel log
|
||||
|
||||
2
.github/workflows/release-patch.yml
vendored
@@ -13,6 +13,8 @@ on:
|
||||
|
||||
jobs:
|
||||
auto-patch-trigger:
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
|
||||
2
.github/workflows/release-status.yml
vendored
@@ -7,6 +7,8 @@ on:
|
||||
|
||||
jobs:
|
||||
check-release-status:
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
|
||||
45
.github/workflows/release-tag.yml
vendored
@@ -39,6 +39,7 @@ on:
|
||||
# - nightly
|
||||
# - beta
|
||||
# - latest
|
||||
# - none (skips everything)
|
||||
required: true
|
||||
tag_rollout:
|
||||
description: Rollout % (0-100)
|
||||
@@ -54,7 +55,15 @@ on:
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
green-check-stub:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 2
|
||||
steps:
|
||||
- name: Stub
|
||||
run: echo "Stub to make this job successful even if all the rest of the steps are skipped"
|
||||
check-version:
|
||||
# skips everything if the tag_name is 'none' because all later jobs depend on this job
|
||||
if: ${{ inputs.tag_name != 'none' }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
@@ -92,21 +101,14 @@ jobs:
|
||||
oss: getCanonicalVersion(version, 'oss'),
|
||||
};
|
||||
|
||||
const ossReleased = await hasBeenReleased({
|
||||
const released = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.oss,
|
||||
});
|
||||
|
||||
const eeReleased = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.ee,
|
||||
});
|
||||
|
||||
if (!ossReleased || !eeReleased) {
|
||||
if (!released) {
|
||||
throw new Error("This version has not been released yet!", version);
|
||||
}
|
||||
|
||||
@@ -185,7 +187,7 @@ jobs:
|
||||
|
||||
return upload_path;
|
||||
|
||||
- name: Upload to s3 latest path
|
||||
- name: Upload to s3 ${{ inputs.tag_name }} path
|
||||
run: | # sh
|
||||
aws s3 cp \
|
||||
s3://${{ vars.AWS_S3_DOWNLOADS_BUCKET }}/${{ steps.source_path.outputs.result }}/metabase.jar \
|
||||
@@ -270,25 +272,19 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # fetch all history
|
||||
fetch-depth: 0 # we want all branches and tags
|
||||
fetch-tags: true
|
||||
- name: Add and push git tag
|
||||
run: | # sh
|
||||
|
||||
if [[ "${{ matrix.edition }}" == "ee" ]]; then
|
||||
git tag -f ${{ inputs.tag_name }}-ee ${{ needs.check-version.outputs.ee }}
|
||||
git tag -f ${{ inputs.tag_name }}-ee ${{ needs.check-version.outputs.oss }}
|
||||
git push origin -f ${{ inputs.tag_name }}-ee
|
||||
elif [[ "${{ matrix.edition }}" == "oss" ]]; then
|
||||
git tag -f ${{ inputs.tag_name }}-oss ${{ needs.check-version.outputs.oss }}
|
||||
git push origin -f ${{ inputs.tag_name }}-oss
|
||||
fi
|
||||
|
||||
update-release-log:
|
||||
needs: check-version
|
||||
uses: ./.github/workflows/release-log.yml
|
||||
with:
|
||||
version: ${{ fromJSON(vars.CURRENT_VERSION) }} # cast string to number
|
||||
secrets: inherit
|
||||
|
||||
update-version-info:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: check-version
|
||||
@@ -314,11 +310,10 @@ jobs:
|
||||
- name: Generate new version info
|
||||
uses: actions/github-script@v7
|
||||
id: new_version_info
|
||||
if: ${{ inputs.tag_name }} == "latest"
|
||||
with:
|
||||
result-encoding: string
|
||||
script: | # js
|
||||
const { updateVersionInfoLatest } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const { updateVersionInfoChannel } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const fs = require('fs');
|
||||
|
||||
const edition = '${{ matrix.edition }}';
|
||||
@@ -327,15 +322,14 @@ jobs:
|
||||
? '${{ needs.check-version.outputs.ee }}'
|
||||
: '${{ needs.check-version.outputs.oss }}';
|
||||
|
||||
const newVersionInfo = await updateVersionInfoLatest({
|
||||
newLatestVersion: canonical_version,
|
||||
const newVersionInfo = await updateVersionInfoChannel({
|
||||
channel: '${{ inputs.tag_name }}',
|
||||
newVersion: canonical_version,
|
||||
rollout: ${{ inputs.tag_rollout }},
|
||||
});
|
||||
|
||||
fs.writeFileSync('version-info.json', JSON.stringify(newVersionInfo));
|
||||
|
||||
- name: Upload new version-info.json to S3
|
||||
if: ${{ inputs.tag_name }} == "latest"
|
||||
run: |
|
||||
if [[ "${{ matrix.edition }}" == "ee" ]]; then
|
||||
aws s3 cp version-info.json s3://${{ vars.AWS_S3_STATIC_BUCKET }}/version-info-ee.json
|
||||
@@ -343,7 +337,6 @@ jobs:
|
||||
aws s3 cp version-info.json s3://${{ vars.AWS_S3_STATIC_BUCKET }}/version-info.json
|
||||
fi
|
||||
- name: Create cloudfront invalidation for version-info.json and version-info-ee.json
|
||||
if: ${{ inputs.tag_name }} == "latest"
|
||||
run: |
|
||||
aws cloudfront create-invalidation \
|
||||
--distribution-id ${{ vars.AWS_CLOUDFRONT_STATIC_ID }} \
|
||||
|
||||
236
.github/workflows/release.yml
vendored
@@ -11,26 +11,40 @@ on:
|
||||
commit:
|
||||
description: 'A full-length commit SHA-1 hash'
|
||||
required: true
|
||||
skip-docker:
|
||||
description: 'Skip Docker image publishing'
|
||||
type: boolean
|
||||
default: false
|
||||
skip-s3:
|
||||
description: 'Skip S3 artifact publishing'
|
||||
type: boolean
|
||||
default: false
|
||||
skip-version-info:
|
||||
description: 'Skip publishing version-info.json'
|
||||
type: boolean
|
||||
default: false
|
||||
skip-tag:
|
||||
description: 'Skip tagging the release'
|
||||
type: boolean
|
||||
default: false
|
||||
skip-release-notes:
|
||||
description: 'Skip publishing release notes'
|
||||
release-channel:
|
||||
description: 'The release channel to publish to (optional)'
|
||||
type: choice
|
||||
options:
|
||||
- none
|
||||
- latest
|
||||
- beta
|
||||
- nightly
|
||||
required: true
|
||||
default: 'none'
|
||||
auto:
|
||||
description: 'auto-patch release DO NOT SET MANUALLY'
|
||||
type: boolean
|
||||
default: false
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Metabase version (e.g. v0.46.3)'
|
||||
type: string
|
||||
required: true
|
||||
commit:
|
||||
description: 'A full-length commit SHA-1 hash'
|
||||
type: string
|
||||
required: true
|
||||
release-channel:
|
||||
description: 'The release channel to publish to (optional)'
|
||||
type: string
|
||||
# options:
|
||||
# - none
|
||||
# - latest
|
||||
# - beta
|
||||
# - nightly
|
||||
required: true
|
||||
default: 'none'
|
||||
auto:
|
||||
description: 'auto-patch release DO NOT SET MANUALLY'
|
||||
type: boolean
|
||||
@@ -74,21 +88,14 @@ jobs:
|
||||
oss: getCanonicalVersion(version, 'oss'),
|
||||
};
|
||||
|
||||
const ossReleased = await hasBeenReleased({
|
||||
const released = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.oss,
|
||||
});
|
||||
|
||||
const eeReleased = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.ee,
|
||||
});
|
||||
|
||||
if (ossReleased || eeReleased) {
|
||||
if (released) {
|
||||
throw new Error("This version has already been released!", version);
|
||||
}
|
||||
|
||||
@@ -185,6 +192,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-uberjar
|
||||
overwrite: true
|
||||
path: |
|
||||
./metabase.jar
|
||||
./COMMIT-ID
|
||||
@@ -192,7 +200,6 @@ jobs:
|
||||
./version.properties
|
||||
|
||||
upload-to-s3:
|
||||
if: ${{ inputs.skip-s3 != true }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: download-uberjar
|
||||
timeout-minutes: 15
|
||||
@@ -242,7 +249,6 @@ jobs:
|
||||
|
||||
|
||||
verify-s3-download:
|
||||
if: ${{ inputs.skip-s3 != true }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: upload-to-s3
|
||||
timeout-minutes: 15
|
||||
@@ -276,7 +282,6 @@ jobs:
|
||||
run: grep -q $(sha256sum ./metabase-downloaded.jar) SHA256.sum && echo "checksums match" || exit 1
|
||||
|
||||
containerize:
|
||||
if: ${{ inputs.skip-docker != true }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [check-version, download-uberjar]
|
||||
timeout-minutes: 15
|
||||
@@ -291,6 +296,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# checkout the commit that was tagged so we get the right dockerfile
|
||||
ref: ${{ inputs.commit }}
|
||||
fetch-depth: 0 # IMPORTANT! to get all the tags
|
||||
- name: prepare release scripts
|
||||
run: cd release && yarn && yarn build
|
||||
@@ -361,7 +368,6 @@ jobs:
|
||||
echo "Finished!"
|
||||
|
||||
verify-docker-pull:
|
||||
if: ${{ inputs.skip-docker != true }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: containerize
|
||||
timeout-minutes: 15
|
||||
@@ -410,7 +416,6 @@ jobs:
|
||||
timeout-minutes: 3
|
||||
|
||||
push-tags:
|
||||
if: ${{ inputs.skip-tag != true }}
|
||||
permissions: write-all
|
||||
needs: [verify-s3-download, verify-docker-pull, check-version]
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -429,21 +434,7 @@ jobs:
|
||||
const { tagRelease } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
const OSSversion = '${{ needs.check-version.outputs.oss }}';
|
||||
const EEversion = '${{ needs.check-version.outputs.ee }}';
|
||||
|
||||
// push EE tag
|
||||
await tagRelease({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: EEversion,
|
||||
commitHash: '${{ inputs.commit }}',
|
||||
}).catch((err) => {
|
||||
console.error('Failed to tag release', EEversion, err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// push OSS tag
|
||||
await tagRelease({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
@@ -454,83 +445,6 @@ jobs:
|
||||
console.error('Failed to tag release', OSSversion, err);
|
||||
process.exit(1);
|
||||
});
|
||||
- name: Reorder release tags to put OSS first
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
$GITHUB_WORKSPACE/release/reorder-tags.sh ${{ needs.check-version.outputs.ee }} ${{ inputs.commit }}
|
||||
|
||||
trigger-docs-update:
|
||||
if: ${{ !inputs.auto && inputs.skip-release-notes != true }}
|
||||
needs:
|
||||
- push-tags
|
||||
- check-version
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
env:
|
||||
NEW_OSS_VERSION: ${{ needs.check-version.outputs.oss }}
|
||||
NEW_EE_VERSION: ${{ needs.check-version.outputs.ee }}
|
||||
GH_TOKEN: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
script: | # js
|
||||
await github.rest.repos.createDispatchEvent({
|
||||
owner: '${{ github.repository_owner }}',
|
||||
repo: '${{ secrets.DOCS_REPO }}',
|
||||
event_type: 'trigger-docs-update',
|
||||
client_payload: {
|
||||
version: '${{ inputs.version }}'
|
||||
}
|
||||
});
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
- name: update releases.md
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
|
||||
script: | # js
|
||||
const fs = require('fs');
|
||||
|
||||
const releaseText = fs.readFileSync('./docs/releases.md', 'utf8');
|
||||
|
||||
const newReleaseText = releaseText
|
||||
.replace(
|
||||
/## Metabase Enterprise Edition releases\n\n/,
|
||||
`## Metabase Enterprise Edition releases\n\n- [${process.env.NEW_EE_VERSION}](https://github.com/metabase/metabase/releases/tag/${process.env.NEW_EE_VERSION})\n`
|
||||
)
|
||||
.replace(
|
||||
/## Metabase Open Source Edition releases\n\n/,
|
||||
`## Metabase Open Source Edition releases\n\n- [${process.env.NEW_OSS_VERSION}](https://github.com/metabase/metabase/releases/tag/${process.env.NEW_OSS_VERSION})\n`
|
||||
);
|
||||
|
||||
fs.writeFileSync('./docs/releases.md', newReleaseText);
|
||||
|
||||
- name: commit and push updates
|
||||
run: | # bash
|
||||
git config --global user.email "metabase-bot@metabase.com"
|
||||
git config --global user.name "Metabase bot"
|
||||
|
||||
git checkout -b docs-add-$NEW_OSS_VERSION
|
||||
cd docs/
|
||||
|
||||
git add releases.md
|
||||
git commit -m "Add $NEW_OSS_VERSION to the list of releases"
|
||||
git push origin docs-add-$NEW_OSS_VERSION --force
|
||||
|
||||
- name: open pr with updates
|
||||
run: | # bash
|
||||
gh pr create --fill \
|
||||
--body "Like it says on the tin 😁" \
|
||||
--label "Type:Documentation" \
|
||||
--label "backport" \
|
||||
--reviewer "jeff-bruemmer" \
|
||||
--assignee "jeff-bruemmer"
|
||||
|
||||
trigger-cloud-issues:
|
||||
if: ${{ !inputs.auto }}
|
||||
@@ -577,7 +491,7 @@ jobs:
|
||||
});
|
||||
|
||||
draft-release-notes:
|
||||
if: ${{ !inputs.auto && inputs.skip-release-notes != true }}
|
||||
if: ${{ !inputs.auto }}
|
||||
needs: push-tags
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 15
|
||||
@@ -586,41 +500,26 @@ jobs:
|
||||
AWS_S3_DOWNLOADS_BUCKET: ${{ vars.AWS_S3_DOWNLOADS_BUCKET }}
|
||||
DOCKERHUB_OWNER: ${{ vars.DOCKERHUB_OWNER }}
|
||||
DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO }}
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [oss, ee]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: prepare release scripts
|
||||
run: cd release && yarn && yarn build
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Retrieve uberjar artifact
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-uberjar
|
||||
- name: Read Checksum
|
||||
run: |
|
||||
CHECKSUM=$(cat SHA256.sum)
|
||||
echo "CHECKSUM=$CHECKSUM" >> $GITHUB_ENV
|
||||
- name: Publish draft release notes
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
script: | # js
|
||||
const { publishRelease, getCanonicalVersion } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
const version = '${{ inputs.version }}';
|
||||
const edition = '${{ matrix.edition }}';
|
||||
|
||||
const canonical_version = getCanonicalVersion(version, edition);
|
||||
|
||||
await publishRelease({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: canonical_version,
|
||||
checksum: '${{ env.CHECKSUM }}',
|
||||
version,
|
||||
}).then(() => {
|
||||
console.log('Successfully published release notes', '${{ inputs.version }}');
|
||||
}).catch((err) => {
|
||||
@@ -629,7 +528,6 @@ jobs:
|
||||
});
|
||||
|
||||
publish-version-info:
|
||||
if: ${{ !inputs.auto && inputs.skip-version-info != true }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [push-tags, check-version]
|
||||
timeout-minutes: 15
|
||||
@@ -640,6 +538,11 @@ jobs:
|
||||
AWS_S3_STATIC_BUCKET: ${{ vars.AWS_S3_STATIC_BUCKET }}
|
||||
AWS_REGION: ${{ vars.AWS_REGION }}
|
||||
steps:
|
||||
- name: Finish early
|
||||
if: ${{ inputs.auto }}
|
||||
run: |
|
||||
echo "skipping version info update for nightly patch"
|
||||
exit 0
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
@@ -651,7 +554,7 @@ jobs:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Publish release notes
|
||||
- name: Publish version info
|
||||
uses: actions/github-script@v7
|
||||
id: new_version_info
|
||||
with:
|
||||
@@ -687,22 +590,20 @@ jobs:
|
||||
--distribution-id ${{ vars.AWS_CLOUDFRONT_STATIC_ID }} \
|
||||
--paths "/version-info.json" "/version-info-ee.json"
|
||||
|
||||
tag-nightly:
|
||||
if: ${{ inputs.auto }}
|
||||
needs: [push-tags, verify-docker-pull, verify-s3-download]
|
||||
set-release-channel:
|
||||
needs: publish-version-info
|
||||
uses: ./.github/workflows/release-tag.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
version: ${{ inputs.version }}
|
||||
tag_name: nightly
|
||||
tag_name: ${{ inputs.release-channel }}
|
||||
tag_rollout: 100
|
||||
tag_ee: true
|
||||
tag_oss: true
|
||||
|
||||
publish-complete-message:
|
||||
if: ${{ !inputs.auto }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [draft-release-notes, verify-docker-pull, verify-s3-download, publish-version-info]
|
||||
needs: set-release-channel
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -719,34 +620,7 @@ jobs:
|
||||
script: | # js
|
||||
const { sendPublishCompleteMessage } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
await sendPublishCompleteMessage({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: '${{ inputs.version }}',
|
||||
runId: '${{ github.run_id }}',
|
||||
channelName: '${{ vars.SLACK_RELEASE_CHANNEL }}',
|
||||
generalChannelName: 'general',
|
||||
}).catch(console.error);
|
||||
|
||||
auto-publish-complete-message:
|
||||
if: ${{ inputs.auto }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: tag-nightly
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: release
|
||||
- name: Prepare build scripts
|
||||
run: cd ${{ github.workspace }}/release && yarn && yarn build
|
||||
- name: Send auto publish complete message
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
SLACK_RELEASE_CHANNEL: ${{ vars.SLACK_RELEASE_CHANNEL }}
|
||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
with:
|
||||
script: | # js
|
||||
const { sendPublishCompleteMessage } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const isAutoRelease = '${{ inputs.auto }}' === 'true';
|
||||
|
||||
await sendPublishCompleteMessage({
|
||||
owner: context.repo.owner,
|
||||
@@ -754,7 +628,7 @@ jobs:
|
||||
version: '${{ inputs.version }}',
|
||||
runId: '${{ github.run_id }}',
|
||||
channelName: '${{ vars.SLACK_RELEASE_CHANNEL }}',
|
||||
generalChannelName: '',
|
||||
generalChannelName: !isAutoRelease ? '${{ vars.SLACK_GENERAL_CHANNEL }}' : '',
|
||||
}).catch(console.error);
|
||||
|
||||
manage-milestones:
|
||||
@@ -773,12 +647,12 @@ jobs:
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
const { closeMilestone, openNextMilestones, isRCVersion } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
const { closeMilestone, openNextMilestones, isPreReleaseVersion } = require('${{ github.workspace }}/release/dist/index.cjs');
|
||||
|
||||
const version = '${{ inputs.version }}';
|
||||
|
||||
if (isRCVersion(version)) {
|
||||
console.log("This is a release candidate, skipping milestone management");
|
||||
if (isPreReleaseVersion(version)) {
|
||||
console.log("This is a prerelease version, skipping milestone management");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
2
.github/workflows/snyk.yml
vendored
@@ -16,6 +16,8 @@ on:
|
||||
|
||||
jobs:
|
||||
monitor:
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
name: Generate Snyk report
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
|
||||
2
.github/workflows/stale.yml
vendored
@@ -8,6 +8,8 @@ permissions:
|
||||
|
||||
jobs:
|
||||
close-stale-prs:
|
||||
# don't run this workflow on a cron for forks
|
||||
if: ${{ github.event_name != 'schedule' || github.repository == 'metabase/metabase' }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
|
||||
57
.github/workflows/tag-for-release.yml
vendored
@@ -83,21 +83,14 @@ jobs:
|
||||
oss: getCanonicalVersion(version, 'oss'),
|
||||
};
|
||||
|
||||
const ossReleased = await hasBeenReleased({
|
||||
const released = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.oss,
|
||||
});
|
||||
|
||||
const eeReleased = await hasBeenReleased({
|
||||
github,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
version: versions.ee,
|
||||
});
|
||||
|
||||
if (ossReleased || eeReleased) {
|
||||
if (released) {
|
||||
throw new Error("This version has already been released!", version);
|
||||
}
|
||||
|
||||
@@ -155,7 +148,7 @@ jobs:
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17 # 11 throws an error on jar uf
|
||||
java-version: 21
|
||||
|
||||
- name: Retrieve test build uberjar artifact for ${{ matrix.edition }}
|
||||
id: find_release_artifact
|
||||
@@ -233,25 +226,25 @@ jobs:
|
||||
./COMMIT-ID
|
||||
./SHA256.sum
|
||||
|
||||
trigger-tests:
|
||||
needs: [tag-uberjar-for-release]
|
||||
permissions:
|
||||
actions: write
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: trigger pre-release testing
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: | # js
|
||||
github.rest.actions.createWorkflowDispatch({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
workflow_id: 'pre-release.yml',
|
||||
ref: '${{ github.ref }}',
|
||||
inputs: {
|
||||
commit: '${{ inputs.commit }}',
|
||||
version: '${{ inputs.version }}',
|
||||
auto: '${{ inputs.auto }}',
|
||||
}
|
||||
});
|
||||
run-pre-release-tests:
|
||||
name: Run pre-release tests for ${{ inputs.version }}
|
||||
needs: tag-uberjar-for-release
|
||||
uses: ./.github/workflows/pre-release.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
commit: ${{ inputs.commit }}
|
||||
version: ${{ inputs.version }}
|
||||
|
||||
auto-publish-release:
|
||||
name: Auto-publish release ${{ inputs.version }}
|
||||
if: ${{ inputs.auto }}
|
||||
needs: run-pre-release-tests
|
||||
uses: ./.github/workflows/release.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
version: ${{ inputs.version }}
|
||||
commit: ${{ inputs.commit }}
|
||||
auto: ${{ inputs.auto }}
|
||||
# for now don't auto-set release channel because we don't want to have
|
||||
# multiple nightlies due to race conditions
|
||||
release-channel: none
|
||||
|
||||
157
.github/workflows/uberjar-sdk.yml
vendored
@@ -1,157 +0,0 @@
|
||||
name: Build + Docker Uberjar for SDK
|
||||
|
||||
on:
|
||||
# This workflow will be called from "release-embedding-sdk.yml"
|
||||
workflow_call:
|
||||
inputs:
|
||||
git_ref:
|
||||
description: 'Valid git reference e.g. branches, tags, hashes'
|
||||
type: string
|
||||
required: true
|
||||
image_name:
|
||||
description: Docker image used to upload to Dockerhub
|
||||
type: string
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build MB ${{ matrix.edition }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 40
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [ee]
|
||||
env:
|
||||
MB_EDITION: ${{ matrix.edition }}
|
||||
INTERACTIVE: false
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.git_ref }}
|
||||
- name: Prepare front-end environment
|
||||
uses: ./.github/actions/prepare-frontend
|
||||
- name: Prepare back-end environment
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: uberjar
|
||||
- name: Build
|
||||
run: ./bin/build.sh
|
||||
- name: Prepare uberjar artifact
|
||||
uses: ./.github/actions/prepare-uberjar-artifact
|
||||
with:
|
||||
name: metabase-ee-uberjar
|
||||
|
||||
check_jar_health:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Is ${{ matrix.edition }} (java ${{ matrix.java-version }}) healthy?
|
||||
needs: build
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [ee]
|
||||
java-version: [11, 17]
|
||||
steps:
|
||||
- name: Prepare JRE (Java Run-time Environment)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-package: jre
|
||||
java-version: ${{ matrix.java-version }}
|
||||
distribution: 'temurin'
|
||||
- run: java -version
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Retrieve uberjar artifact
|
||||
with:
|
||||
name: metabase-ee-uberjar
|
||||
- name: Launch uberjar
|
||||
run: java -jar ./target/uberjar/metabase.jar &
|
||||
- name: Wait for Metabase to start
|
||||
run: while ! curl 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
|
||||
|
||||
containerize_test_and_push_container:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Containerize ${{ matrix.edition }}
|
||||
needs: check_jar_health
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [ee]
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
ports:
|
||||
- 5000:5000
|
||||
steps:
|
||||
- name: Extract and clean branch name
|
||||
shell: bash
|
||||
run: echo "branch=$(echo $GITHUB_REF_NAME | sed 's/[^-._a-zA-Z0-9]/-/g')" >> $GITHUB_OUTPUT
|
||||
id: extract_branch
|
||||
|
||||
- name: Set image name to env
|
||||
run: echo "image_name=${{ inputs.image_name || steps.extract_branch.outputs.branch }}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Verify the intended tag of the container image
|
||||
run: echo "Container image will be tagged as ${{ env.image_name }}-${{ matrix.edition }}"
|
||||
|
||||
- name: Check out the code (Dockerfile needed)
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.git_ref }}
|
||||
|
||||
- name: Download uploaded artifacts to insert into container
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-ee-uberjar
|
||||
path: bin/docker/
|
||||
|
||||
- name: Move the ${{ matrix.edition }} uberjar to the context dir
|
||||
run: mv bin/docker/target/uberjar/metabase.jar bin/docker/.
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2.5.0
|
||||
with:
|
||||
driver-opts: network=host
|
||||
|
||||
- name: Build ${{ matrix.edition }} container
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: bin/docker/.
|
||||
platforms: linux/amd64
|
||||
network: host
|
||||
tags: localhost:5000/metabase-dev:${{ env.image_name }}-${{ matrix.edition }}
|
||||
no-cache: true
|
||||
push: true
|
||||
|
||||
- name: Launch ${{ matrix.edition }} container
|
||||
run: docker run --rm -dp 3000:3000 localhost:5000/metabase-dev:${{ env.image_name }}-${{ matrix.edition }}
|
||||
timeout-minutes: 5
|
||||
|
||||
- name: Is Docker running?
|
||||
run: docker ps
|
||||
|
||||
- name: Wait for Metabase to start and reach 100% health
|
||||
run: while ! curl -s 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
|
||||
timeout-minutes: 3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Retag and push images
|
||||
run: docker tag localhost:5000/metabase-dev:${{ env.image_name }}-ee ${{ github.repository_owner }}/metabase-dev:${{ env.image_name }} && docker push ${{ github.repository_owner }}/metabase-dev:${{ env.image_name }}
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
env:
|
||||
TRIVY_OFFLINE_SCAN: true
|
||||
with:
|
||||
image-ref: docker.io/${{ github.repository_owner }}/metabase-dev:${{ env.image_name }}
|
||||
format: sarif
|
||||
output: trivy-results.sarif
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
47
.github/workflows/uberjar.yml
vendored
@@ -4,6 +4,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- metabot-v3-second-try
|
||||
- feature-visualizer
|
||||
paths-ignore:
|
||||
# config files
|
||||
- ".**"
|
||||
@@ -41,6 +43,9 @@ jobs:
|
||||
uses: ./.github/actions/prepare-backend
|
||||
with:
|
||||
m2-cache-key: uberjar
|
||||
# Build with Java 11 so they compiled code doesn't try to use Java >11 classes... see
|
||||
# https://metaboat.slack.com/archives/C5XHN8GLW/p1731517744549619?thread_ts=1731504670.951389&cid=C5XHN8GLW
|
||||
java-version: 11
|
||||
- name: Build
|
||||
run: ./bin/build.sh
|
||||
- name: Prepare uberjar artifact
|
||||
@@ -56,7 +61,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [ee, oss]
|
||||
java-version: [11, 17]
|
||||
java-version: [11, 17, 21]
|
||||
steps:
|
||||
- name: Prepare JRE (Java Run-time Environment)
|
||||
uses: actions/setup-java@v4
|
||||
@@ -70,7 +75,8 @@ jobs:
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.sha }}-uberjar
|
||||
- name: Launch uberjar
|
||||
run: java -jar ./target/uberjar/metabase.jar &
|
||||
run: >-
|
||||
java --add-opens java.base/java.nio=ALL-UNNAMED -jar ./target/uberjar/metabase.jar &
|
||||
- name: Wait for Metabase to start
|
||||
run: while ! curl 'http://localhost:3000/api/health' | grep '{"status":"ok"}'; do sleep 1; done
|
||||
|
||||
@@ -80,12 +86,16 @@ jobs:
|
||||
needs: check_jar_health
|
||||
strategy:
|
||||
matrix:
|
||||
edition: [ee, oss]
|
||||
edition: [ee, oss, ee-extra]
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
ports:
|
||||
- 5000:5000
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Extract and clean branch name
|
||||
shell: bash
|
||||
@@ -98,12 +108,24 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.event.inputs.commit }}
|
||||
- name: Download uploaded artifacts to insert into container
|
||||
if: ${{ matrix.edition != 'ee-extra' }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-${{ matrix.edition }}-${{ github.sha }}-uberjar
|
||||
path: bin/docker/
|
||||
- name: Download uploaded artifacts to insert into container
|
||||
if: ${{ matrix.edition == 'ee-extra' }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: metabase-ee-${{ github.sha }}-uberjar
|
||||
path: bin/docker/
|
||||
- name: Move the ${{ matrix.edition }} uberjar to the context dir
|
||||
run: mv bin/docker/target/uberjar/metabase.jar bin/docker/.
|
||||
- name: Add partner drivers to the container
|
||||
if: ${{ matrix.edition == 'ee-extra' }}
|
||||
uses: ./.github/actions/build-ee-extra
|
||||
with:
|
||||
iam-role: ${{ secrets.METABASE_EE_EXTRA_IAM_ROLE }}
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2.5.0
|
||||
@@ -133,44 +155,57 @@ jobs:
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Retag and push images if master (ee)
|
||||
if: ${{ (github.ref_name == 'master') && matrix.edition == 'ee' }}
|
||||
run: docker tag localhost:5000/metabase-dev:${{ steps.extract_branch.outputs.branch }}-ee ${{ github.repository_owner }}/metabase-enterprise-head:latest && docker push ${{ github.repository_owner }}/metabase-enterprise-head:latest
|
||||
|
||||
# TODO: remove when we're done testing metabot
|
||||
- name: Retag and push images if metabot-v3-second-try (ee)
|
||||
if: ${{ (github.ref_name == 'metabot-v3-second-try') && matrix.edition == 'ee' }}
|
||||
run: docker tag localhost:5000/metabase-dev:${{ steps.extract_branch.outputs.branch }}-ee ${{ github.repository_owner }}/metabase-enterprise-head:metabot && docker push ${{ github.repository_owner }}/metabase-enterprise-head:metabot
|
||||
|
||||
- name: Retag and push images if master (oss)
|
||||
if: ${{ (github.ref_name == 'master') && matrix.edition == 'oss' }}
|
||||
run: docker tag localhost:5000/metabase-dev:${{ steps.extract_branch.outputs.branch }}-oss ${{ github.repository_owner }}/metabase-head:latest && docker push ${{ github.repository_owner }}/metabase-head:latest
|
||||
|
||||
- name: Retag and push images if master (ee-extra)
|
||||
if: ${{ (github.ref_name == 'master') && matrix.edition == 'ee-extra' }}
|
||||
run: docker tag localhost:5000/metabase-dev:${{ steps.extract_branch.outputs.branch }}-ee-extra ${{ secrets.METABASE_EE_EXTRA_CONTAINER_REGISTRY }}/metabase-enterprise-head:latest && docker push ${{ secrets.METABASE_EE_EXTRA_CONTAINER_REGISTRY }}/metabase-enterprise-head:latest
|
||||
|
||||
- name: Retag and push images if dev branch
|
||||
if: ${{ !(startsWith(github.ref_name,'master') || startsWith(github.ref_name,'backport')) && matrix.edition == 'ee' }}
|
||||
run: docker tag localhost:5000/metabase-dev:${{ steps.extract_branch.outputs.branch }}-ee ${{ github.repository_owner }}/metabase-dev:${{ steps.extract_branch.outputs.branch }} && docker push ${{ github.repository_owner }}/metabase-dev:${{ steps.extract_branch.outputs.branch }}
|
||||
|
||||
- name: Run Trivy vulnerability scanner if master (ee)
|
||||
if: ${{ (github.ref_name == 'master') && matrix.edition == 'ee' }}
|
||||
uses: aquasecurity/trivy-action@master
|
||||
uses: aquasecurity/trivy-action@0.28.0
|
||||
env:
|
||||
TRIVY_OFFLINE_SCAN: true
|
||||
with:
|
||||
image-ref: docker.io/${{ github.repository_owner }}/metabase-enterprise-head:latest
|
||||
format: sarif
|
||||
output: trivy-results.sarif
|
||||
version: "v0.57.1"
|
||||
|
||||
- name: Run Trivy vulnerability scanner if master (oss)
|
||||
if: ${{ (github.ref_name == 'master') && matrix.edition == 'oss' }}
|
||||
uses: aquasecurity/trivy-action@master
|
||||
uses: aquasecurity/trivy-action@0.28.0
|
||||
env:
|
||||
TRIVY_OFFLINE_SCAN: true
|
||||
with:
|
||||
image-ref: docker.io/${{ github.repository_owner }}/metabase-head:latest
|
||||
format: sarif
|
||||
output: trivy-results.sarif
|
||||
version: "v0.57.1"
|
||||
|
||||
- name: Run Trivy vulnerability scanner if dev branch
|
||||
if: ${{ !(startsWith(github.ref_name,'master') || startsWith(github.ref_name,'backport')) && matrix.edition == 'ee' }}
|
||||
uses: aquasecurity/trivy-action@master
|
||||
uses: aquasecurity/trivy-action@0.28.0
|
||||
env:
|
||||
TRIVY_OFFLINE_SCAN: true
|
||||
with:
|
||||
version: "v0.57.1"
|
||||
image-ref: docker.io/${{ github.repository_owner }}/metabase-dev:${{ steps.extract_branch.outputs.branch }}
|
||||
format: sarif
|
||||
output: trivy-results.sarif
|
||||
|
||||
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
BIN
.loki/reference/chrome_laptop_Parameters_DatePicker_Exclude.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |