mirror of
https://github.com/apache/superset.git
synced 2026-07-05 14:25:32 +00:00
Compare commits
2861 Commits
superset-h
...
fix-webpac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98212189b8 | ||
|
|
1e4bc6ee78 | ||
|
|
db178cf527 | ||
|
|
5901320933 | ||
|
|
23bb4f88c0 | ||
|
|
4130b92966 | ||
|
|
38297edc6b | ||
|
|
0c8f326258 | ||
|
|
127f6b3d66 | ||
|
|
ea519a77b5 | ||
|
|
6cb3ef9f5d | ||
|
|
a889ae75fc | ||
|
|
b60be9655f | ||
|
|
fd6da21ce0 | ||
|
|
1bf112a57a | ||
|
|
1f530d45cb | ||
|
|
1187902e68 | ||
|
|
ad3eff9e90 | ||
|
|
3e554674ff | ||
|
|
dced2f8564 | ||
|
|
05c6a1bf20 | ||
|
|
c193d6d6a1 | ||
|
|
fb840b8e71 | ||
|
|
d0cc6f115b | ||
|
|
966e231f94 | ||
|
|
a66737cb05 | ||
|
|
bc6859a99d | ||
|
|
133e686224 | ||
|
|
7d0a472d1e | ||
|
|
c2534f9155 | ||
|
|
088ecdd0bf | ||
|
|
e1a2e4843a | ||
|
|
15e8ffee1e | ||
|
|
19ddcb7e5c | ||
|
|
36daa2dc3f | ||
|
|
7fd5a7668b | ||
|
|
95333e34b1 | ||
|
|
a9fb853e3e | ||
|
|
dea9068647 | ||
|
|
3416bd1479 | ||
|
|
e729b2dbb4 | ||
|
|
06261f262b | ||
|
|
454ed1883f | ||
|
|
b42060c880 | ||
|
|
7bf16d805d | ||
|
|
529adebe1b | ||
|
|
eb4351af83 | ||
|
|
5a2411fa64 | ||
|
|
078c1701f4 | ||
|
|
a7d349a5c6 | ||
|
|
7a20a65a4d | ||
|
|
912ed2ba80 | ||
|
|
fedb3ca941 | ||
|
|
42b15b6840 | ||
|
|
2f64343186 | ||
|
|
65376c7baf | ||
|
|
4c2b27e7f0 | ||
|
|
15e4e8df94 | ||
|
|
c5f220a9ff | ||
|
|
b05def1a8a | ||
|
|
da7f6efea8 | ||
|
|
1c2b9db4f0 | ||
|
|
0fce5ecfa5 | ||
|
|
385471c34d | ||
|
|
bef1f4d045 | ||
|
|
5a3182ce21 | ||
|
|
9efb80dbf4 | ||
|
|
a20b236809 | ||
|
|
4e969d19d1 | ||
|
|
876257fb94 | ||
|
|
472e599f91 | ||
|
|
d826e90395 | ||
|
|
c65cb284e6 | ||
|
|
bc54b7970a | ||
|
|
ce74ae095d | ||
|
|
9424538bb1 | ||
|
|
031fb4b5a8 | ||
|
|
7fb7ac8bef | ||
|
|
569a7b33a5 | ||
|
|
59df0d6f15 | ||
|
|
2e4ccffc11 | ||
|
|
2e51d02806 | ||
|
|
8406a827dd | ||
|
|
ea0a77daaf | ||
|
|
e5e3ddb24e | ||
|
|
7320ad9a0a | ||
|
|
3dbe593a4a | ||
|
|
61f359d565 | ||
|
|
e77ff267a1 | ||
|
|
c426723275 | ||
|
|
d2a1d86561 | ||
|
|
0cd0b37983 | ||
|
|
a6b4ff9847 | ||
|
|
a81282adeb | ||
|
|
3ba3c09c47 | ||
|
|
3081c7fb62 | ||
|
|
fa5b0d7281 | ||
|
|
1444ef36b9 | ||
|
|
15d2f22eb4 | ||
|
|
355d7e1ee5 | ||
|
|
448a28545b | ||
|
|
cefd046ea0 | ||
|
|
b0d3f0f0d4 | ||
|
|
b7a193d53e | ||
|
|
0a75bac2a1 | ||
|
|
0de5b28716 | ||
|
|
b5ae402c12 | ||
|
|
682cdcc3e0 | ||
|
|
5dba59b6a4 | ||
|
|
71242dc6dd | ||
|
|
b2f8803486 | ||
|
|
744fa1f54c | ||
|
|
f0ff972f0e | ||
|
|
ba838b6aeb | ||
|
|
6a4b1df3a2 | ||
|
|
0a76f84142 | ||
|
|
9bcc62f210 | ||
|
|
322442d5be | ||
|
|
92879e6b32 | ||
|
|
fad3cb3162 | ||
|
|
4d040006b6 | ||
|
|
6e7cb521ba | ||
|
|
bc9ec6ac63 | ||
|
|
b9cbf2e766 | ||
|
|
d183969744 | ||
|
|
4695be5cc5 | ||
|
|
c1a3606774 | ||
|
|
175835138c | ||
|
|
077724c2d2 | ||
|
|
6b69dc42dc | ||
|
|
c5a84c0985 | ||
|
|
dc7a8844eb | ||
|
|
54f071138c | ||
|
|
812374b31b | ||
|
|
e463743fcf | ||
|
|
1d9e17df14 | ||
|
|
bcf156c969 | ||
|
|
ebfb14c353 | ||
|
|
7946ec003f | ||
|
|
665a11f821 | ||
|
|
5566eb8dd6 | ||
|
|
836540e8c9 | ||
|
|
b558b34faf | ||
|
|
30c72ba0a3 | ||
|
|
d8a3d29ad9 | ||
|
|
53ce530a46 | ||
|
|
06264f07fb | ||
|
|
ce3b93d8a0 | ||
|
|
b74a244950 | ||
|
|
ab58b0a8a3 | ||
|
|
659db162d6 | ||
|
|
cb24737825 | ||
|
|
97b35a4640 | ||
|
|
54af1cb2c8 | ||
|
|
b8c2f7db47 | ||
|
|
4701e78f1f | ||
|
|
b89b0bdf5d | ||
|
|
47414e18d4 | ||
|
|
9c9588cce6 | ||
|
|
471d9fe737 | ||
|
|
b381992a75 | ||
|
|
1204507d68 | ||
|
|
c7779578f9 | ||
|
|
b225432c55 | ||
|
|
547f297171 | ||
|
|
5c3c2599db | ||
|
|
a8be5a5a0c | ||
|
|
e1234b2264 | ||
|
|
75af53dc3d | ||
|
|
0a45a89786 | ||
|
|
2b2cc96f11 | ||
|
|
59c01e016d | ||
|
|
3895b8b127 | ||
|
|
da8c0f94e6 | ||
|
|
6908a733a0 | ||
|
|
e8e1466185 | ||
|
|
ff1f7b64e2 | ||
|
|
63bb1d55a4 | ||
|
|
c568d463b9 | ||
|
|
179a6f2cfe | ||
|
|
695a20d009 | ||
|
|
e908775fb2 | ||
|
|
af05396227 | ||
|
|
277f03c207 | ||
|
|
48699a7194 | ||
|
|
b7d076bfee | ||
|
|
009b99bfbb | ||
|
|
b45141b2a1 | ||
|
|
4683a0827d | ||
|
|
ffb617a4c8 | ||
|
|
9de1706baa | ||
|
|
a95566f114 | ||
|
|
a82e310600 | ||
|
|
691926f0e1 | ||
|
|
a42185cd3b | ||
|
|
89eb7b207c | ||
|
|
f99022b242 | ||
|
|
f8b9e3ace4 | ||
|
|
9cbe5a90b8 | ||
|
|
f7fe617f4c | ||
|
|
e6c8343fd0 | ||
|
|
6969f2cf7a | ||
|
|
852adaa6cc | ||
|
|
1f482b42eb | ||
|
|
31e2143c84 | ||
|
|
b89e0d74be | ||
|
|
1127ab6c07 | ||
|
|
8d210fc7b8 | ||
|
|
8acb2fb700 | ||
|
|
a3cbc9755f | ||
|
|
28788fd1fa | ||
|
|
21790814db | ||
|
|
ff6dc03ddf | ||
|
|
fbcdf6909c | ||
|
|
fc95c4fc89 | ||
|
|
3a007f6284 | ||
|
|
2403d8d584 | ||
|
|
47874318df | ||
|
|
f6353bd1e8 | ||
|
|
1101182654 | ||
|
|
d79fc92a1a | ||
|
|
bce476c4a2 | ||
|
|
ecfb9f7d7c | ||
|
|
58ebc57285 | ||
|
|
1a57e50bd6 | ||
|
|
f3884a2db8 | ||
|
|
cb899f691b | ||
|
|
b25722ee2b | ||
|
|
34e10f5972 | ||
|
|
e88096f75c | ||
|
|
6d827cf905 | ||
|
|
ab13166e41 | ||
|
|
89f09ea57c | ||
|
|
baec438be9 | ||
|
|
5309edf3a5 | ||
|
|
f50cbd7958 | ||
|
|
2465ab4a98 | ||
|
|
1947d4da76 | ||
|
|
e452f5b70d | ||
|
|
698de7a38d | ||
|
|
e2a9f2dead | ||
|
|
1f80725b0e | ||
|
|
c3cb5c7e99 | ||
|
|
f7dd0659bf | ||
|
|
3c17ff8445 | ||
|
|
57d0e78d40 | ||
|
|
ae986903b3 | ||
|
|
6964f9bdbf | ||
|
|
9efa9898ff | ||
|
|
22b44421a4 | ||
|
|
02924b3c74 | ||
|
|
99539c786e | ||
|
|
5e621ceb34 | ||
|
|
370a24da81 | ||
|
|
732506b3fa | ||
|
|
1af9c8dba2 | ||
|
|
1dc22a9002 | ||
|
|
ad592c717e | ||
|
|
38e15196f2 | ||
|
|
8131c24acd | ||
|
|
952b620465 | ||
|
|
f3e3bd0348 | ||
|
|
1e1310dbd8 | ||
|
|
adaae8ba15 | ||
|
|
a66b7e98e0 | ||
|
|
3e12d97e8e | ||
|
|
00304f77e1 | ||
|
|
e88db9f403 | ||
|
|
53e9cf6d17 | ||
|
|
5a004590e0 | ||
|
|
53503e32ae | ||
|
|
246181a546 | ||
|
|
6f5d9c989a | ||
|
|
8515792b04 | ||
|
|
923b2b1d77 | ||
|
|
486b0122d0 | ||
|
|
ae090fa74c | ||
|
|
35ec6d308a | ||
|
|
c62a6f5cee | ||
|
|
cdd140b3cc | ||
|
|
09cf49c2ba | ||
|
|
ac4b4c7646 | ||
|
|
d0a6c78966 | ||
|
|
65f2071aa4 | ||
|
|
e8f37a3f89 | ||
|
|
19d229ea12 | ||
|
|
622a62d7a1 | ||
|
|
4a556f4ac4 | ||
|
|
7a1839ba1b | ||
|
|
8f2afb8f4d | ||
|
|
02586981da | ||
|
|
8700a0b939 | ||
|
|
d843fef2ce | ||
|
|
f45654c03c | ||
|
|
761daec53d | ||
|
|
407fb67f1e | ||
|
|
49689eec6c | ||
|
|
791ea9860d | ||
|
|
2f8939d229 | ||
|
|
ccf6290120 | ||
|
|
96a1aa60e8 | ||
|
|
2ea0368c2d | ||
|
|
9e407e4e80 | ||
|
|
360e58c181 | ||
|
|
22d5eb7835 | ||
|
|
7c4a77a909 | ||
|
|
4e209e51d0 | ||
|
|
7191ae55c8 | ||
|
|
17725ebc83 | ||
|
|
1a7a381bd5 | ||
|
|
daf207e5c2 | ||
|
|
72294c569f | ||
|
|
792dd08d38 | ||
|
|
1e40e7d02b | ||
|
|
7e98c75f01 | ||
|
|
b18de05ea4 | ||
|
|
9300652277 | ||
|
|
7c2ec4ca5f | ||
|
|
6a83b6fd87 | ||
|
|
659cd33749 | ||
|
|
cb27d5fe8d | ||
|
|
6c9cda758a | ||
|
|
967134f540 | ||
|
|
25bb353f9d | ||
|
|
9cf2472291 | ||
|
|
cf5b976659 | ||
|
|
70394e79ef | ||
|
|
ea64f3122e | ||
|
|
50197fc33e | ||
|
|
c480fa7fcf | ||
|
|
6fc734da51 | ||
|
|
762a11b0bb | ||
|
|
f168dd69a8 | ||
|
|
becd0b8883 | ||
|
|
fd4570625a | ||
|
|
54a5b58e40 | ||
|
|
a611278e04 | ||
|
|
5c2eb0a68c | ||
|
|
0cbf4d5d4d | ||
|
|
6006a21378 | ||
|
|
bf967d6ba4 | ||
|
|
131ae5aa9d | ||
|
|
eca28582b6 | ||
|
|
14e90a0f52 | ||
|
|
a1c39d4906 | ||
|
|
0964a8bb7a | ||
|
|
8de8f95a3c | ||
|
|
16db999067 | ||
|
|
972be15dda | ||
|
|
c9e06714f8 | ||
|
|
32626ab707 | ||
|
|
a9cd58508b | ||
|
|
122bb68e5a | ||
|
|
914ce9aa4f | ||
|
|
bb572983cd | ||
|
|
ff76ab647f | ||
|
|
f554848c9f | ||
|
|
dc0c389488 | ||
|
|
22b3cc0480 | ||
|
|
604d72cc98 | ||
|
|
913e068113 | ||
|
|
1a4e2173f5 | ||
|
|
c49789167b | ||
|
|
1be2287b3a | ||
|
|
e741a3167f | ||
|
|
5f11f9097a | ||
|
|
8783579aa8 | ||
|
|
c25b4221f8 | ||
|
|
9c771fb2ba | ||
|
|
7f44992c4b | ||
|
|
8df5860826 | ||
|
|
b794b192d1 | ||
|
|
3177131d52 | ||
|
|
89bf77b5c9 | ||
|
|
30e5684006 | ||
|
|
3f8472ca7b | ||
|
|
efa8cb6fa4 | ||
|
|
ab59b7e9b0 | ||
|
|
c99843b13a | ||
|
|
da55a6c94a | ||
|
|
7a1c056374 | ||
|
|
1e5a4e9bdc | ||
|
|
9b88527883 | ||
|
|
800c1639ec | ||
|
|
43775e9373 | ||
|
|
9099b0f00d | ||
|
|
77ffe65773 | ||
|
|
32f8f33a4f | ||
|
|
710c277681 | ||
|
|
11324607d0 | ||
|
|
9c6271136d | ||
|
|
c444eed63e | ||
|
|
1df5e59fdf | ||
|
|
77f66e7434 | ||
|
|
2c81eb6c39 | ||
|
|
09c4afc894 | ||
|
|
229d92590a | ||
|
|
f4f516c64c | ||
|
|
fe1fddde05 | ||
|
|
7e67deead7 | ||
|
|
6e02603098 | ||
|
|
4518f6999c | ||
|
|
aff847b3af | ||
|
|
b24aca0304 | ||
|
|
2c453035e4 | ||
|
|
4fe11869fc | ||
|
|
a0a49f9300 | ||
|
|
29d2fac485 | ||
|
|
0c5da6cb5d | ||
|
|
da6947d295 | ||
|
|
2db8f809ba | ||
|
|
5912fad745 | ||
|
|
dc41c45bec | ||
|
|
88ee90c579 | ||
|
|
bbb2279644 | ||
|
|
1958df6b83 | ||
|
|
58bd3bfcf0 | ||
|
|
d6eb6e08d0 | ||
|
|
96cb6030c8 | ||
|
|
94d47113ea | ||
|
|
f756cee01b | ||
|
|
e8926f177d | ||
|
|
16f4516903 | ||
|
|
000d353ef3 | ||
|
|
83b6f672ff | ||
|
|
0dc48e9b41 | ||
|
|
fe9eef9198 | ||
|
|
8a8248b575 | ||
|
|
42d9a78777 | ||
|
|
31a15c5162 | ||
|
|
67b21c45df | ||
|
|
b280ab9e1f | ||
|
|
c42be77c25 | ||
|
|
160917eae8 | ||
|
|
68b84acd93 | ||
|
|
0aa48b6564 | ||
|
|
0fc1955049 | ||
|
|
8a704d293b | ||
|
|
f4754641c8 | ||
|
|
7c98c3f4f6 | ||
|
|
5a32777dd0 | ||
|
|
7229e1ccf3 | ||
|
|
30695d75d7 | ||
|
|
75ee4edc6a | ||
|
|
d269e3d187 | ||
|
|
7d0fabe1ab | ||
|
|
9695249976 | ||
|
|
17c1a37afb | ||
|
|
73dfe57ae2 | ||
|
|
0d236c4ade | ||
|
|
bc0a10fc73 | ||
|
|
5efca408eb | ||
|
|
29f638e239 | ||
|
|
ddeb612429 | ||
|
|
0bc214e889 | ||
|
|
d951158ce6 | ||
|
|
85034b9748 | ||
|
|
11215b092a | ||
|
|
2129e22423 | ||
|
|
7ea1fca4f7 | ||
|
|
9c8fdc0fc1 | ||
|
|
e25be0f3d9 | ||
|
|
d633fe47ef | ||
|
|
c25e734407 | ||
|
|
d8fd6de940 | ||
|
|
733f112142 | ||
|
|
f55476034b | ||
|
|
0a5941edd7 | ||
|
|
0fc4119728 | ||
|
|
6adfd33e3a | ||
|
|
829e4d92d9 | ||
|
|
42db43c686 | ||
|
|
a0f9efd45e | ||
|
|
5d6a979cd0 | ||
|
|
d6ed819fe2 | ||
|
|
ef14a5fbb4 | ||
|
|
4718767ddb | ||
|
|
dfb377c636 | ||
|
|
7082933b96 | ||
|
|
11b6263d55 | ||
|
|
b0cf7b61ad | ||
|
|
96a1b33f22 | ||
|
|
5cff87c048 | ||
|
|
b9052fa461 | ||
|
|
0ea2066d5b | ||
|
|
992aa3a4d5 | ||
|
|
36c7b15342 | ||
|
|
2ab85f3b67 | ||
|
|
1b690a9876 | ||
|
|
f18d9b6bf4 | ||
|
|
ebca5169a0 | ||
|
|
b9ba4d6fda | ||
|
|
20371940d3 | ||
|
|
ee4944bc1a | ||
|
|
5a1023da89 | ||
|
|
4b94d25869 | ||
|
|
2ceced71c5 | ||
|
|
9f0523977d | ||
|
|
cb6342fc73 | ||
|
|
5214ee6fd4 | ||
|
|
7b3329f315 | ||
|
|
d1b372f670 | ||
|
|
09c657c899 | ||
|
|
24500e99f8 | ||
|
|
b2a173977e | ||
|
|
8be79f4170 | ||
|
|
debaf8d6e9 | ||
|
|
1133d84775 | ||
|
|
8c4ca60b28 | ||
|
|
90eded1a04 | ||
|
|
093ee37aac | ||
|
|
23b1fe3b9e | ||
|
|
42288c4784 | ||
|
|
c008190a08 | ||
|
|
2734688f4f | ||
|
|
e3d8326d81 | ||
|
|
e1ab27f484 | ||
|
|
d1d43be9d1 | ||
|
|
f9cec3e366 | ||
|
|
f92431176a | ||
|
|
c31daf8c92 | ||
|
|
c74fae9663 | ||
|
|
308007f909 | ||
|
|
9aaab7374e | ||
|
|
057218d87f | ||
|
|
050ccdcb3d | ||
|
|
09d975cc3f | ||
|
|
1d2a40f69b | ||
|
|
1a57601fe6 | ||
|
|
09736ee42c | ||
|
|
2e9939baf2 | ||
|
|
6af8ce6bb8 | ||
|
|
8d2c51c945 | ||
|
|
580738cea0 | ||
|
|
1a54b761c1 | ||
|
|
7f5f577daa | ||
|
|
e3cbbca4f9 | ||
|
|
b7ad8dba89 | ||
|
|
ede3de0ca0 | ||
|
|
8ee5505b61 | ||
|
|
eec563b0b4 | ||
|
|
a56d7252c2 | ||
|
|
8b5afc6f29 | ||
|
|
f802474b07 | ||
|
|
11a9f2fe4c | ||
|
|
0cff7619f2 | ||
|
|
a13a590796 | ||
|
|
e0e3f94949 | ||
|
|
6876a1e684 | ||
|
|
f6f9582186 | ||
|
|
5d23dea5aa | ||
|
|
6db6db23f8 | ||
|
|
98b35125c2 | ||
|
|
cd3191bb79 | ||
|
|
5d5b807d33 | ||
|
|
1c2e148d03 | ||
|
|
573dd0edec | ||
|
|
784f86c8eb | ||
|
|
4dc3dd0942 | ||
|
|
c8a809dbdd | ||
|
|
d3b781be77 | ||
|
|
8dd39502f6 | ||
|
|
05994319b7 | ||
|
|
a4f32f829d | ||
|
|
f7921399b9 | ||
|
|
dd129fa403 | ||
|
|
2cc1ef88c8 | ||
|
|
404f7c1043 | ||
|
|
a23a4ed054 | ||
|
|
63cb5807b6 | ||
|
|
85b3845f0d | ||
|
|
1cd12e8576 | ||
|
|
93583220a7 | ||
|
|
f1954ddcb2 | ||
|
|
54bedbd606 | ||
|
|
dc8c0f164f | ||
|
|
775a702b99 | ||
|
|
a1cbd2578e | ||
|
|
f2f1ea948c | ||
|
|
d2e6249ce2 | ||
|
|
3591e362e3 | ||
|
|
dc32608fa3 | ||
|
|
28b4f44baa | ||
|
|
b376459e8c | ||
|
|
e76a6ed63d | ||
|
|
4d6cdf4fea | ||
|
|
d15b0e4f6d | ||
|
|
527c8de773 | ||
|
|
9df990c2d1 | ||
|
|
7b6885a020 | ||
|
|
8fd0fd673f | ||
|
|
21d8d57380 | ||
|
|
7deca8f2cd | ||
|
|
0d3eebd221 | ||
|
|
e6f7c12e88 | ||
|
|
2b1d4a02b0 | ||
|
|
d7d7b7c0e6 | ||
|
|
773def64f2 | ||
|
|
78ad6db0c6 | ||
|
|
e6af4ea126 | ||
|
|
a64b9ac84f | ||
|
|
bce3d4f19e | ||
|
|
59e3645c17 | ||
|
|
e05ccb3824 | ||
|
|
86e7139245 | ||
|
|
bb6bd85c1d | ||
|
|
ca74ae75a6 | ||
|
|
ae6c072661 | ||
|
|
5f2f12d347 | ||
|
|
fc7ba060c1 | ||
|
|
3a3984006c | ||
|
|
d11b6d557e | ||
|
|
2f007bf7a5 | ||
|
|
6513445000 | ||
|
|
3ef92e5610 | ||
|
|
57bb425fb0 | ||
|
|
2fba789e8d | ||
|
|
08655a7559 | ||
|
|
3256008a59 | ||
|
|
da8efd36d7 | ||
|
|
5541dad32b | ||
|
|
b3f436a030 | ||
|
|
b00660acf1 | ||
|
|
a6af4f4d7a | ||
|
|
cc3460832f | ||
|
|
edc60914f6 | ||
|
|
c9518485ba | ||
|
|
a26e1d822a | ||
|
|
a7aa8f7cef | ||
|
|
ff34e3c81e | ||
|
|
20519158d2 | ||
|
|
cacf1e06d6 | ||
|
|
fa0c5891bf | ||
|
|
fc13a0fde5 | ||
|
|
ade85daee2 | ||
|
|
2d26af25c1 | ||
|
|
b033406387 | ||
|
|
c09f8f6f76 | ||
|
|
401ce56fa1 | ||
|
|
cf315388f2 | ||
|
|
f219dc1794 | ||
|
|
ed20d2a917 | ||
|
|
235c9d2ebf | ||
|
|
fdea4e21b0 | ||
|
|
e20a08cb14 | ||
|
|
429935a277 | ||
|
|
a4bb11c755 | ||
|
|
f0b6e87091 | ||
|
|
ea5a609d0b | ||
|
|
0abe6eed89 | ||
|
|
e205846845 | ||
|
|
deef923825 | ||
|
|
0fa3feb088 | ||
|
|
1393f7d3d2 | ||
|
|
b7ba50033a | ||
|
|
ce9759785a | ||
|
|
8de58b9848 | ||
|
|
cc8ab2c556 | ||
|
|
1409b1a25b | ||
|
|
bdfb698aa4 | ||
|
|
57183da315 | ||
|
|
c928f23e1b | ||
|
|
0c89914a6d | ||
|
|
630e0e0240 | ||
|
|
513047c3bb | ||
|
|
d932837a3c | ||
|
|
38868f9ff4 | ||
|
|
8013b32f0e | ||
|
|
adeed60fe0 | ||
|
|
546945e7a6 | ||
|
|
5b2f1bbf9e | ||
|
|
875f538d54 | ||
|
|
b7d3ff1e85 | ||
|
|
c03964dc5f | ||
|
|
950a3313d8 | ||
|
|
e2a22d481c | ||
|
|
b4e2406385 | ||
|
|
ca9e74edd8 | ||
|
|
39b3de6b5d | ||
|
|
26563bb330 | ||
|
|
0653e123cc | ||
|
|
76358ed64e | ||
|
|
217f11a8f7 | ||
|
|
af21ef2497 | ||
|
|
51c25831e8 | ||
|
|
be41e0526a | ||
|
|
0f240ea1b2 | ||
|
|
e520538af6 | ||
|
|
e03d840d06 | ||
|
|
1921ba993e | ||
|
|
b050897ebd | ||
|
|
0bdd8a223d | ||
|
|
d12f86363f | ||
|
|
9f680a63f8 | ||
|
|
928a052440 | ||
|
|
fbc84a1f9a | ||
|
|
fa1693dc5f | ||
|
|
8a8fb49617 | ||
|
|
dc4474889d | ||
|
|
29ac507d56 | ||
|
|
7f14e434c8 | ||
|
|
21ca26acd7 | ||
|
|
33e48146b0 | ||
|
|
73701b7295 | ||
|
|
22475e787e | ||
|
|
9e38a0cc29 | ||
|
|
a391ebecca | ||
|
|
72cd9dffa3 | ||
|
|
4ed05f4ff1 | ||
|
|
871cfe0c78 | ||
|
|
a928f8cd9e | ||
|
|
afaaf64f52 | ||
|
|
dc0d542054 | ||
|
|
0cd3a12daa | ||
|
|
35b30480f0 | ||
|
|
6d1f17bd46 | ||
|
|
ab899e71e7 | ||
|
|
6b9d8708d3 | ||
|
|
bc1e8e07cf | ||
|
|
82526865d2 | ||
|
|
02c8c9c752 | ||
|
|
6475188e6a | ||
|
|
6e485c9f70 | ||
|
|
b49e5857c9 | ||
|
|
13ced58261 | ||
|
|
ed36674a99 | ||
|
|
99aa3a6507 | ||
|
|
f045a73e2d | ||
|
|
7791674f24 | ||
|
|
9f0ae77341 | ||
|
|
5a9e366c0a | ||
|
|
c22c532a5c | ||
|
|
6db3a4d9d2 | ||
|
|
17d7b72f3b | ||
|
|
fee33dd0cf | ||
|
|
65605b4a54 | ||
|
|
e304f2d5ad | ||
|
|
4e0c261c9d | ||
|
|
22de26cd77 | ||
|
|
339ba96600 | ||
|
|
3c6091144b | ||
|
|
ef14b529b8 | ||
|
|
2a97a6ec1f | ||
|
|
fa6548939e | ||
|
|
418c673699 | ||
|
|
13f77a7416 | ||
|
|
303a80a316 | ||
|
|
2392ac6827 | ||
|
|
01ce4b987e | ||
|
|
2f308a85d8 | ||
|
|
e8d60509a0 | ||
|
|
d6f80eaae7 | ||
|
|
a5f986fec5 | ||
|
|
141d0252f2 | ||
|
|
c029b532d4 | ||
|
|
13816443ba | ||
|
|
2c4e22e598 | ||
|
|
aea776a131 | ||
|
|
d2360b533b | ||
|
|
de84a534ac | ||
|
|
ac636c73ae | ||
|
|
6a586fe4fd | ||
|
|
fbd8ae2888 | ||
|
|
7e4fde7a14 | ||
|
|
150b9a0168 | ||
|
|
f7b7aace38 | ||
|
|
f78c94c988 | ||
|
|
74ff8dc724 | ||
|
|
8aa127eac2 | ||
|
|
3729016a0d | ||
|
|
b6628cdfd2 | ||
|
|
ae48dba3e1 | ||
|
|
09364d182c | ||
|
|
99ed968289 | ||
|
|
8fa3b8d7e3 | ||
|
|
7530487760 | ||
|
|
79afc2b545 | ||
|
|
8c94f9c435 | ||
|
|
b589d44dfb | ||
|
|
4140261797 | ||
|
|
00f1fdb3c4 | ||
|
|
172e5dd095 | ||
|
|
a53907a646 | ||
|
|
be1b8d6751 | ||
|
|
26ff734ef9 | ||
|
|
0e18246999 | ||
|
|
7333ffd41e | ||
|
|
7dc5019b9d | ||
|
|
93fa39a14f | ||
|
|
342e6f3ab0 | ||
|
|
013379eb86 | ||
|
|
bc0ffe0d10 | ||
|
|
5f62deaa36 | ||
|
|
ff8605b723 | ||
|
|
45c77a1976 | ||
|
|
8cb71b8d3b | ||
|
|
2233c02720 | ||
|
|
839215148a | ||
|
|
c1eeb63d89 | ||
|
|
7b9ebbe735 | ||
|
|
a5a91d5e48 | ||
|
|
e1f5c49df7 | ||
|
|
3c1fc0b722 | ||
|
|
05faf2f352 | ||
|
|
347c174099 | ||
|
|
5656d69c04 | ||
|
|
ac4df8d06b | ||
|
|
bcd136cee1 | ||
|
|
7ab8534ef6 | ||
|
|
014b39290b | ||
|
|
4f97b739b1 | ||
|
|
d88cba92c0 | ||
|
|
5304bed4ed | ||
|
|
37194a41ec | ||
|
|
d75ff9e784 | ||
|
|
164a07e2be | ||
|
|
44bd200885 | ||
|
|
8242692541 | ||
|
|
09b92e7d08 | ||
|
|
31ac3898ad | ||
|
|
c1159c53e3 | ||
|
|
deb6aedddb | ||
|
|
ed0cd5e7b0 | ||
|
|
9280b4d2a9 | ||
|
|
3a57857707 | ||
|
|
6b7394e789 | ||
|
|
5a8eab3b25 | ||
|
|
15969fdf94 | ||
|
|
9b15e04bc4 | ||
|
|
fd947a097d | ||
|
|
e1383d3821 | ||
|
|
c131205ff1 | ||
|
|
b6df88a134 | ||
|
|
629b137bb0 | ||
|
|
db959a6463 | ||
|
|
4041150660 | ||
|
|
bcb43327b1 | ||
|
|
63c8bbf3eb | ||
|
|
24b1666273 | ||
|
|
86b795cd36 | ||
|
|
bc0bf94680 | ||
|
|
f5d64176f6 | ||
|
|
4f0020d0df | ||
|
|
c83eda9551 | ||
|
|
a36e636a58 | ||
|
|
f5d3627468 | ||
|
|
8eeed49547 | ||
|
|
00933a27af | ||
|
|
2bc33beec4 | ||
|
|
e1c1de1b94 | ||
|
|
26743dfcee | ||
|
|
8b0bda3bad | ||
|
|
a8a6254ea2 | ||
|
|
be4bc3dec5 | ||
|
|
6e02d19b0d | ||
|
|
662f0fa8f4 | ||
|
|
56bf17f879 | ||
|
|
b92909d621 | ||
|
|
8f35a3ec8c | ||
|
|
a4a092794a | ||
|
|
174750c9dd | ||
|
|
f2c0686346 | ||
|
|
c2afae51cb | ||
|
|
6e1d1ad18b | ||
|
|
ab22bb1878 | ||
|
|
e0ed652ed8 | ||
|
|
103fedaf92 | ||
|
|
50fe7483ae | ||
|
|
37f626f5e2 | ||
|
|
b1693f625a | ||
|
|
f0dc1e7527 | ||
|
|
6c7f089ebb | ||
|
|
68a81c3989 | ||
|
|
5222f940cc | ||
|
|
45ea11c1b6 | ||
|
|
b624919d2f | ||
|
|
b5cb5f4525 | ||
|
|
4a70065e5f | ||
|
|
7d77dc4fd2 | ||
|
|
6f69c84d10 | ||
|
|
6b96b37c38 | ||
|
|
b7435f84f0 | ||
|
|
7bc349c3c3 | ||
|
|
fd4e45aafc | ||
|
|
b339d7ad20 | ||
|
|
cedd186c21 | ||
|
|
c6c9114b40 | ||
|
|
f4a05a5ffd | ||
|
|
a82f916a71 | ||
|
|
ff0529c932 | ||
|
|
c0f83a7467 | ||
|
|
9bb3a5782d | ||
|
|
5ec710efc6 | ||
|
|
5866f3ec83 | ||
|
|
01801e3c36 | ||
|
|
d319543377 | ||
|
|
5392bafe28 | ||
|
|
89ce7ba0b0 | ||
|
|
376a1f49d3 | ||
|
|
6042ea8f28 | ||
|
|
78efb62781 | ||
|
|
e9d5079986 | ||
|
|
c6e0abbe13 | ||
|
|
4f166a03f5 | ||
|
|
29b62f7c0a | ||
|
|
09ee3e2a1d | ||
|
|
121e424a7f | ||
|
|
66c1a6a875 | ||
|
|
b26c373f4d | ||
|
|
4dd318ca68 | ||
|
|
ce6d5f5551 | ||
|
|
9e3052968b | ||
|
|
3f1ef2a283 | ||
|
|
bc3e19d0a2 | ||
|
|
850801f510 | ||
|
|
710af87faf | ||
|
|
6612343f33 | ||
|
|
c399295a4e | ||
|
|
e34644d983 | ||
|
|
cc0097c87a | ||
|
|
d71e655a4b | ||
|
|
99e69c32ee | ||
|
|
a2c164a77d | ||
|
|
78d2a584b7 | ||
|
|
f0c8c12c1a | ||
|
|
34cd741e9b | ||
|
|
1684ddc7e6 | ||
|
|
e35145c816 | ||
|
|
4adf44a43c | ||
|
|
cd5a94305c | ||
|
|
b4602aaf28 | ||
|
|
3e69ba1384 | ||
|
|
41bf215367 | ||
|
|
06deaebe19 | ||
|
|
6a13ab8920 | ||
|
|
f1a222d356 | ||
|
|
a87bedf31a | ||
|
|
890b6079b9 | ||
|
|
9c62456487 | ||
|
|
414cdbf83a | ||
|
|
df06bdf33b | ||
|
|
449f51aed5 | ||
|
|
c9e2c7037e | ||
|
|
a49a15f990 | ||
|
|
eb39ddbfe3 | ||
|
|
974d36d35e | ||
|
|
b64e3254fc | ||
|
|
9907db9e1a | ||
|
|
b4dd64aa24 | ||
|
|
6e049225f9 | ||
|
|
831369a44b | ||
|
|
7c9c30db1d | ||
|
|
0c6d868483 | ||
|
|
777760b096 | ||
|
|
e8ad096173 | ||
|
|
2f6f5c6778 | ||
|
|
832e028b39 | ||
|
|
d92af9c95c | ||
|
|
12435159db | ||
|
|
8695239372 | ||
|
|
29b4c40e43 | ||
|
|
53471072f4 | ||
|
|
bf902b2240 | ||
|
|
4b4912ba99 | ||
|
|
fa890ecb23 | ||
|
|
67af8bd730 | ||
|
|
f5eca4fe0b | ||
|
|
057423ed92 | ||
|
|
7dbe608d27 | ||
|
|
d8d4b75a11 | ||
|
|
664047f3fb | ||
|
|
1e20b048d3 | ||
|
|
6c1806df74 | ||
|
|
d97d991b5f | ||
|
|
90e18e37d0 | ||
|
|
c5a2bc5484 | ||
|
|
2ecc7e4f56 | ||
|
|
9f79c5ab4d | ||
|
|
e7721a8c4d | ||
|
|
c8f5089f7a | ||
|
|
a0ea905a7a | ||
|
|
b8fd1a30ee | ||
|
|
ff9ae54ae9 | ||
|
|
a16de15015 | ||
|
|
079e40144e | ||
|
|
a3f3a35c20 | ||
|
|
4fdeab8dad | ||
|
|
9ea58381f4 | ||
|
|
85d51f5c9a | ||
|
|
3b1d763421 | ||
|
|
91ab123860 | ||
|
|
8e021b0c82 | ||
|
|
7aa89db8d0 | ||
|
|
d3ba2755e8 | ||
|
|
0b0e0e9ce8 | ||
|
|
979f890cd5 | ||
|
|
89b6d7fb68 | ||
|
|
644882faff | ||
|
|
edfcbed24f | ||
|
|
f45ab70080 | ||
|
|
33aa9030bf | ||
|
|
4c3aae7583 | ||
|
|
c5dd52bcc9 | ||
|
|
eae7cf81b0 | ||
|
|
20e5df501e | ||
|
|
68e8d9858c | ||
|
|
99238dccbb | ||
|
|
626736bdd3 | ||
|
|
c2de749d0e | ||
|
|
9ad9ea67cf | ||
|
|
82595df6f9 | ||
|
|
281d1a8ec4 | ||
|
|
d2e0e2b79c | ||
|
|
05409d51da | ||
|
|
e98194cdd3 | ||
|
|
317532752c | ||
|
|
c90e45a373 | ||
|
|
8decc9e45f | ||
|
|
8053833e1f | ||
|
|
07221d8859 | ||
|
|
c1abe1ec44 | ||
|
|
b3dfd4930a | ||
|
|
fc844d3dfd | ||
|
|
d8686c2d12 | ||
|
|
90388885db | ||
|
|
33370eaa5c | ||
|
|
2b53b1800e | ||
|
|
807dcddc28 | ||
|
|
a45ce1e8d1 | ||
|
|
3d5128735b | ||
|
|
6173a6c329 | ||
|
|
813e79fa9f | ||
|
|
c0e92b1639 | ||
|
|
ef08ccbaa2 | ||
|
|
93d759c689 | ||
|
|
0d24ce0ef9 | ||
|
|
a4902a3685 | ||
|
|
16b08e333d | ||
|
|
15cf06699a | ||
|
|
fe33661821 | ||
|
|
2b98f326e8 | ||
|
|
d7e0ee6ceb | ||
|
|
ce367d6427 | ||
|
|
6c3886aad0 | ||
|
|
5af4e61aff | ||
|
|
5766c36372 | ||
|
|
61b72f0c0b | ||
|
|
d79f7b28c2 | ||
|
|
84b52b2323 | ||
|
|
eacb234872 | ||
|
|
6317a91541 | ||
|
|
128c45e2d3 | ||
|
|
4d6b4f8343 | ||
|
|
789049d386 | ||
|
|
cf7ce31054 | ||
|
|
2c851b7580 | ||
|
|
f4105e9ed2 | ||
|
|
74733ae310 | ||
|
|
1d823a0be5 | ||
|
|
00429558c2 | ||
|
|
dae6acf028 | ||
|
|
822d72c57d | ||
|
|
c02a0a00f4 | ||
|
|
a08c18febe | ||
|
|
479a5d2f72 | ||
|
|
793fbac405 | ||
|
|
167dacc2e4 | ||
|
|
00883c395c | ||
|
|
83071d0e5f | ||
|
|
b0dac046e6 | ||
|
|
8dcae810d4 | ||
|
|
b43e2ac8f4 | ||
|
|
bc02f05613 | ||
|
|
90651dfe3e | ||
|
|
c583eec4c7 | ||
|
|
0f07d78e01 | ||
|
|
22fe985cfc | ||
|
|
ace8a3adb7 | ||
|
|
4c4b5e8c64 | ||
|
|
2c37ddb2f6 | ||
|
|
b06a9edfd6 | ||
|
|
5140250421 | ||
|
|
88cf2d5c39 | ||
|
|
422a07b382 | ||
|
|
f820f9a976 | ||
|
|
c27aee2b14 | ||
|
|
7ce1a3445c | ||
|
|
42a3c523ae | ||
|
|
bb46dd93be | ||
|
|
b207f0616d | ||
|
|
9dcf788f47 | ||
|
|
6900bc1855 | ||
|
|
b09bfd7889 | ||
|
|
2d8892958e | ||
|
|
f9a43921c5 | ||
|
|
e74efd3072 | ||
|
|
d5a5bd46d2 | ||
|
|
e422e3c620 | ||
|
|
b269d920a9 | ||
|
|
de2bce6f47 | ||
|
|
e061116032 | ||
|
|
878bcbd8c7 | ||
|
|
093135ff30 | ||
|
|
734f8ed4c3 | ||
|
|
dcc9628f31 | ||
|
|
321d105c42 | ||
|
|
460aec7bc9 | ||
|
|
ffe9244458 | ||
|
|
fa09d8187a | ||
|
|
9da30956c0 | ||
|
|
9c7835a244 | ||
|
|
ad057324b7 | ||
|
|
2c583d1584 | ||
|
|
15fbb195e9 | ||
|
|
5867b87680 | ||
|
|
52563d3eea | ||
|
|
21348c418a | ||
|
|
af3589fe91 | ||
|
|
937d40cdde | ||
|
|
319a860f23 | ||
|
|
d3b854a833 | ||
|
|
650fa5ccfb | ||
|
|
db70c7912c | ||
|
|
3160607aaf | ||
|
|
eec54affc3 | ||
|
|
31d6f5a639 | ||
|
|
60424c4ccd | ||
|
|
60bbd72028 | ||
|
|
a78968c68e | ||
|
|
1c3ec21e0f | ||
|
|
8d1fb9c82d | ||
|
|
f01493277f | ||
|
|
0f6bd5ea83 | ||
|
|
0030f46d2d | ||
|
|
06f8f8e608 | ||
|
|
a144464506 | ||
|
|
2770bc0865 | ||
|
|
bcc61bd933 | ||
|
|
38c46fcafd | ||
|
|
f3e7c64de6 | ||
|
|
f9f8c5d07a | ||
|
|
c5f4a7f302 | ||
|
|
389aae270b | ||
|
|
e97eb71a52 | ||
|
|
5a8488af36 | ||
|
|
205cff3a94 | ||
|
|
649a0dec6c | ||
|
|
e8990f4a36 | ||
|
|
acf91e1f60 | ||
|
|
6ed9dae2f7 | ||
|
|
ea5879bf2b | ||
|
|
c7c3b1b0e9 | ||
|
|
c64018d421 | ||
|
|
53d944d013 | ||
|
|
9aa8b09505 | ||
|
|
8984f88a3e | ||
|
|
386aa93e24 | ||
|
|
0cd0fcdecb | ||
|
|
cde2d49c95 | ||
|
|
9e5876dc17 | ||
|
|
1064ad5d58 | ||
|
|
7db0589340 | ||
|
|
c590e90c87 | ||
|
|
101d3fa78d | ||
|
|
468bb5f47a | ||
|
|
1c1494d3e0 | ||
|
|
5fc11fb706 | ||
|
|
f73d61a597 | ||
|
|
3f46bcf142 | ||
|
|
aa67525b70 | ||
|
|
568f6d958b | ||
|
|
b12f515185 | ||
|
|
732de4ac7f | ||
|
|
e4bdb28ba2 | ||
|
|
a87a13c3ab | ||
|
|
19e8a7049b | ||
|
|
a21f184058 | ||
|
|
f4efce3475 | ||
|
|
23d9f46d30 | ||
|
|
6478bb7eab | ||
|
|
962fd4cca3 | ||
|
|
640d4f09bd | ||
|
|
7e2b7941f3 | ||
|
|
aa74ba3da2 | ||
|
|
1b375b715c | ||
|
|
09c1987de4 | ||
|
|
827042f12f | ||
|
|
925938b4d1 | ||
|
|
65c4d39c31 | ||
|
|
4b0e907c3d | ||
|
|
687f762457 | ||
|
|
6eb87e04c0 | ||
|
|
5fe6ef268e | ||
|
|
51e090d67a | ||
|
|
fc5dde15fe | ||
|
|
14f798afec | ||
|
|
6d117ffbb5 | ||
|
|
fcd166149c | ||
|
|
7482b20f7b | ||
|
|
1d6423e71f | ||
|
|
7cf7267085 | ||
|
|
f5fff5eaad | ||
|
|
e4e07eef5a | ||
|
|
b74da7963b | ||
|
|
7383e4348b | ||
|
|
983aa827a8 | ||
|
|
78cd635b7a | ||
|
|
dfb9af36df | ||
|
|
a02a2f5a96 | ||
|
|
dca3efb3dd | ||
|
|
43a97f86f5 | ||
|
|
b5ac415afc | ||
|
|
4417e6eaef | ||
|
|
f8fe780f52 | ||
|
|
eec374426f | ||
|
|
550123882c | ||
|
|
79f21b09d2 | ||
|
|
63843c5682 | ||
|
|
8960db4132 | ||
|
|
66c22f896b | ||
|
|
840773e626 | ||
|
|
2874096e27 | ||
|
|
b86572b084 | ||
|
|
e4f6e55e89 | ||
|
|
c1cbc334ad | ||
|
|
249fdf444a | ||
|
|
547b8b9314 | ||
|
|
ab6045691e | ||
|
|
fc8710f50a | ||
|
|
aacfe4d667 | ||
|
|
f235787703 | ||
|
|
4ca5846c7f | ||
|
|
754ccd0448 | ||
|
|
d4bd20ffb4 | ||
|
|
4bad1a258f | ||
|
|
ffb6913706 | ||
|
|
6531101517 | ||
|
|
bbf7586fe8 | ||
|
|
ef57318259 | ||
|
|
8050e351ed | ||
|
|
c2d7cf388d | ||
|
|
274aa143d3 | ||
|
|
855011360a | ||
|
|
44ff462718 | ||
|
|
9661afff16 | ||
|
|
1a43654207 | ||
|
|
822441e0bd | ||
|
|
66f1e1f714 | ||
|
|
b5e62753b7 | ||
|
|
aae8fda11d | ||
|
|
bebcd3dcdd | ||
|
|
5e0de04eab | ||
|
|
472ca9d8f6 | ||
|
|
41ed37ab02 | ||
|
|
bbdc195a3b | ||
|
|
740fbf72d7 | ||
|
|
8a2aada58d | ||
|
|
7bd53a84d5 | ||
|
|
5f18e849c1 | ||
|
|
49876c3f13 | ||
|
|
399b709aaf | ||
|
|
a477d84729 | ||
|
|
5acd03876b | ||
|
|
3a6fdf8bdf | ||
|
|
9cd3a8d5b0 | ||
|
|
840a920aba | ||
|
|
e4b3ecd372 | ||
|
|
f29eafd044 | ||
|
|
4f1a837bd3 | ||
|
|
d5a4815836 | ||
|
|
210537a4d2 | ||
|
|
0eca79cb6c | ||
|
|
550d893c38 | ||
|
|
71dca5c076 | ||
|
|
7f72b062d1 | ||
|
|
d68f8d11fe | ||
|
|
b54de611d3 | ||
|
|
f3c5d1c608 | ||
|
|
9e17304523 | ||
|
|
0460415bcb | ||
|
|
b4c5f65a5f | ||
|
|
62486a7dd1 | ||
|
|
8e32aca282 | ||
|
|
c7ae5c587a | ||
|
|
2cea1bcc82 | ||
|
|
5ff2dfb8e2 | ||
|
|
4b54b2b953 | ||
|
|
7e4570bc9c | ||
|
|
78d7df02cb | ||
|
|
ee36cf058c | ||
|
|
668194d574 | ||
|
|
c13cb8a1f2 | ||
|
|
72e87d6980 | ||
|
|
a986a61b5f | ||
|
|
5484db34f9 | ||
|
|
109e6c69ff | ||
|
|
e311bc1ca5 | ||
|
|
553d41fedd | ||
|
|
2996d9ab9c | ||
|
|
bf1da0f91f | ||
|
|
ca12a1d466 | ||
|
|
7c90323649 | ||
|
|
27e42b5091 | ||
|
|
65c72c12c4 | ||
|
|
bcf649a116 | ||
|
|
e371de4ea3 | ||
|
|
b27df30222 | ||
|
|
892349d7c9 | ||
|
|
dec8a65730 | ||
|
|
3084cebd6b | ||
|
|
879e795147 | ||
|
|
509c0a6aab | ||
|
|
91d1648230 | ||
|
|
640dac1eff | ||
|
|
9321ab9deb | ||
|
|
a193d790b2 | ||
|
|
b382ef1058 | ||
|
|
488e7b4692 | ||
|
|
be7df6c16f | ||
|
|
ddd964e49a | ||
|
|
a275a86d12 | ||
|
|
1c99f399c2 | ||
|
|
c38c7a29fd | ||
|
|
0fde78cb17 | ||
|
|
5df3317ad0 | ||
|
|
e88c4e1100 | ||
|
|
d85bb8b6a0 | ||
|
|
fd9c2b399e | ||
|
|
e8daa63d7e | ||
|
|
640d6f848a | ||
|
|
8c5e525c57 | ||
|
|
e87feba45d | ||
|
|
9d3438a8b3 | ||
|
|
fd6ef4f870 | ||
|
|
d94bd413e5 | ||
|
|
0c2f697f6d | ||
|
|
b831bed7cd | ||
|
|
d9554622c0 | ||
|
|
89ad48764a | ||
|
|
5ab3c5ea99 | ||
|
|
fdc7273d56 | ||
|
|
a59a0fe475 | ||
|
|
16e29c466e | ||
|
|
35d109389f | ||
|
|
e5b561c87f | ||
|
|
3999c0fc41 | ||
|
|
e2a1ce220e | ||
|
|
369346c03d | ||
|
|
d09ccb2504 | ||
|
|
c514b6b0b9 | ||
|
|
040f27e6da | ||
|
|
a5fdf6d14a | ||
|
|
16c9418ee1 | ||
|
|
d8aba2f7e6 | ||
|
|
db11a2a308 | ||
|
|
f362c6f508 | ||
|
|
7458c4bbd5 | ||
|
|
531f1b6aa4 | ||
|
|
723ef591a5 | ||
|
|
e51b95ffa8 | ||
|
|
9da65d6bfd | ||
|
|
88cde7225e | ||
|
|
e788b858d0 | ||
|
|
c0feb99f0e | ||
|
|
567380ffe1 | ||
|
|
a5e36c9aab | ||
|
|
4c380b48e7 | ||
|
|
3375e65486 | ||
|
|
a1adb7f31c | ||
|
|
9b28a6eed6 | ||
|
|
8be69aa647 | ||
|
|
48510d2ffb | ||
|
|
04077ce934 | ||
|
|
092faa019b | ||
|
|
1f17b975d6 | ||
|
|
15ede02c25 | ||
|
|
4bccf36375 | ||
|
|
21e794a66f | ||
|
|
e1f98e246f | ||
|
|
bf56a327f4 | ||
|
|
cd200f07a5 | ||
|
|
4ff9aac1fa | ||
|
|
988da2c477 | ||
|
|
f510f42b96 | ||
|
|
43314dc8db | ||
|
|
423a0fefa5 | ||
|
|
fd57fce977 | ||
|
|
d8fbaa4cbe | ||
|
|
a6e05f4558 | ||
|
|
42f4490bbc | ||
|
|
852e9ae173 | ||
|
|
26ec6b78eb | ||
|
|
d6a82f7852 | ||
|
|
232e2055aa | ||
|
|
955efdac1a | ||
|
|
654701af4c | ||
|
|
73d21a87ae | ||
|
|
878c7f0267 | ||
|
|
cb78c778dd | ||
|
|
310558508e | ||
|
|
3daca8d251 | ||
|
|
28b01c5464 | ||
|
|
1fbdd21133 | ||
|
|
55a6c3a10a | ||
|
|
fc45647440 | ||
|
|
3bfead66c4 | ||
|
|
b54a97b5f0 | ||
|
|
931f69d6c7 | ||
|
|
ae8c6865c9 | ||
|
|
0133bab038 | ||
|
|
48c5ee4f8b | ||
|
|
9315a8838c | ||
|
|
592564b623 | ||
|
|
79aff6827c | ||
|
|
079e7327a2 | ||
|
|
48864ce8c7 | ||
|
|
2816a70af3 | ||
|
|
6af22a9cdd | ||
|
|
827fe06903 | ||
|
|
45815d8642 | ||
|
|
cf5c770adc | ||
|
|
638f82b46d | ||
|
|
e0e1eea9ce | ||
|
|
27c7240185 | ||
|
|
5ca2a8f670 | ||
|
|
2d60a2d48c | ||
|
|
b70c8ee7a8 | ||
|
|
a3fd7423b0 | ||
|
|
f679a18e82 | ||
|
|
77f3764fea | ||
|
|
1e0c04fc15 | ||
|
|
56b973f3cc | ||
|
|
3479574bd4 | ||
|
|
aa55751b1d | ||
|
|
6c2aade375 | ||
|
|
f51f19bcba | ||
|
|
1d44662b1d | ||
|
|
25f4226dbb | ||
|
|
dd1ba96adf | ||
|
|
d4888fa4af | ||
|
|
b3559f644c | ||
|
|
fe80fb1090 | ||
|
|
43efa05113 | ||
|
|
e5e3f9e210 | ||
|
|
468dfed416 | ||
|
|
3564740255 | ||
|
|
8020729ced | ||
|
|
deec63bb5b | ||
|
|
339d491dfc | ||
|
|
d66ac9f3f4 | ||
|
|
06fb330569 | ||
|
|
ce0e06a935 | ||
|
|
5006f97f70 | ||
|
|
24d001e498 | ||
|
|
eab888c63a | ||
|
|
3d3c09d299 | ||
|
|
97dde8c485 | ||
|
|
14682b9054 | ||
|
|
93ba8e16c3 | ||
|
|
dbcb473040 | ||
|
|
f0811c8863 | ||
|
|
0166db9663 | ||
|
|
c26f073134 | ||
|
|
45668e31fc | ||
|
|
529aed5da1 | ||
|
|
09802acf0d | ||
|
|
9224051b80 | ||
|
|
fd9d3301f6 | ||
|
|
68499a1199 | ||
|
|
f077323e6f | ||
|
|
7f2e752796 | ||
|
|
97683ec052 | ||
|
|
73164c61ad | ||
|
|
564c168420 | ||
|
|
95f4fe0cb8 | ||
|
|
bbc6d374ea | ||
|
|
316da5e5f5 | ||
|
|
e2b9b8e9fd | ||
|
|
7154b8d40f | ||
|
|
fcb3ff3a41 | ||
|
|
342cfc41ec | ||
|
|
aa7d3b0f96 | ||
|
|
3e28bd2cfa | ||
|
|
cc1eec69df | ||
|
|
3fa0de4293 | ||
|
|
2ad8af71b5 | ||
|
|
b648cc1168 | ||
|
|
f24bf873bf | ||
|
|
e0a5033596 | ||
|
|
ef14d58c64 | ||
|
|
547a4adef5 | ||
|
|
5256a2f194 | ||
|
|
0560c2615d | ||
|
|
ff282492a1 | ||
|
|
312dc1c749 | ||
|
|
1e26c34758 | ||
|
|
decaba72c3 | ||
|
|
7e8c77e636 | ||
|
|
ba99980cf4 | ||
|
|
c62f722f99 | ||
|
|
3fd23508bc | ||
|
|
9ff9e0299b | ||
|
|
6488ced3d3 | ||
|
|
9a2be95159 | ||
|
|
ef4e03c9fe | ||
|
|
ca2f0288e5 | ||
|
|
ca63760a4b | ||
|
|
83924f7e10 | ||
|
|
c4a56c3f6e | ||
|
|
cf134ab3aa | ||
|
|
043c585008 | ||
|
|
0d346d4414 | ||
|
|
9067371234 | ||
|
|
40fe05c5e2 | ||
|
|
e3bdfb5def | ||
|
|
55f0713a2f | ||
|
|
5aee59cc3a | ||
|
|
94d3774d9e | ||
|
|
b665254f39 | ||
|
|
4dc8cce8e8 | ||
|
|
d206a20ce7 | ||
|
|
6fcc282a4e | ||
|
|
93c35a7ba5 | ||
|
|
9dfa8d5f8f | ||
|
|
87504056fe | ||
|
|
429c18f9e8 | ||
|
|
5bddc81f60 | ||
|
|
9837b4a61e | ||
|
|
454f143661 | ||
|
|
7376dfc6e9 | ||
|
|
838d47d578 | ||
|
|
14e81d0a9a | ||
|
|
f68c2b2454 | ||
|
|
814c3dfecc | ||
|
|
b8aade776b | ||
|
|
e092e6002d | ||
|
|
673754d16e | ||
|
|
27deeb2f51 | ||
|
|
9a7a84c7a0 | ||
|
|
a3d2588313 | ||
|
|
5c87fee282 | ||
|
|
b24323d500 | ||
|
|
824aca85d0 | ||
|
|
1e4098a29e | ||
|
|
3aa8f32ca9 | ||
|
|
bf42ea70ba | ||
|
|
d69da5f0f5 | ||
|
|
078257dd1b | ||
|
|
8c1c2570b3 | ||
|
|
a80803566d | ||
|
|
f551f5b7b6 | ||
|
|
1978cde4f1 | ||
|
|
c5f6cc6382 | ||
|
|
e9e2c0bee8 | ||
|
|
33a9817388 | ||
|
|
91301bcd5b | ||
|
|
67ad7da5cc | ||
|
|
e0deb704f9 | ||
|
|
abf3790ea6 | ||
|
|
f8adaf66c1 | ||
|
|
832fed1db5 | ||
|
|
ccce9abf57 | ||
|
|
7d60a88048 | ||
|
|
8905508d8f | ||
|
|
0b647b2dcc | ||
|
|
f58b5295a9 | ||
|
|
9e5b568cc9 | ||
|
|
90572be95a | ||
|
|
3c326598a8 | ||
|
|
ae04959175 | ||
|
|
1e224398e1 | ||
|
|
fa7b66424c | ||
|
|
d1feef51c7 | ||
|
|
1102d41842 | ||
|
|
d22b7860a4 | ||
|
|
4c072b8314 | ||
|
|
4f899dd164 | ||
|
|
9437d9cf5e | ||
|
|
b84e5250f1 | ||
|
|
c6685a706d | ||
|
|
1b63b8f3c7 | ||
|
|
e528cb48c4 | ||
|
|
824eaf84be | ||
|
|
c648cb2de5 | ||
|
|
1991d1f6e5 | ||
|
|
df479940a6 | ||
|
|
87c73175a7 | ||
|
|
a3e89cbfab | ||
|
|
f38f5ac3cf | ||
|
|
58f9be9b85 | ||
|
|
a7069e60e2 | ||
|
|
6e665c3e07 | ||
|
|
4e8eba802a | ||
|
|
ac3a10d8f1 | ||
|
|
c2885a166e | ||
|
|
0e165c1a21 | ||
|
|
629bbc5d4d | ||
|
|
4d50d4944f | ||
|
|
88934265c0 | ||
|
|
16ad5a8f5a | ||
|
|
24b8a94c2c | ||
|
|
a1f86baab2 | ||
|
|
0af124eaae | ||
|
|
57af97d1a2 | ||
|
|
f4c36a6d05 | ||
|
|
683ed0d943 | ||
|
|
88eb95c39a | ||
|
|
dd39138e6e | ||
|
|
5b2f005e80 | ||
|
|
de8282cea0 | ||
|
|
710c6f9412 | ||
|
|
8c7a3bf85a | ||
|
|
3be6cef597 | ||
|
|
d217a78857 | ||
|
|
63b97ab76d | ||
|
|
6b9122bb3b | ||
|
|
5a59dcf06e | ||
|
|
fb6ad3240f | ||
|
|
2eadc1f086 | ||
|
|
d1bc986d93 | ||
|
|
0b263697ca | ||
|
|
f0b86f877f | ||
|
|
a91daab1f7 | ||
|
|
54cc69a382 | ||
|
|
41464931a4 | ||
|
|
e01c8792ec | ||
|
|
4b33353165 | ||
|
|
8b815a3aac | ||
|
|
2a96a9c734 | ||
|
|
b73ee7f2e0 | ||
|
|
f85175e16d | ||
|
|
305b6df6e3 | ||
|
|
64f8140731 | ||
|
|
5820d31b5c | ||
|
|
29e3f4bcc4 | ||
|
|
b02d18a39e | ||
|
|
d466383df2 | ||
|
|
3ec3f0a610 | ||
|
|
ab95bff7b6 | ||
|
|
b3edbe45cf | ||
|
|
ccc2f66e92 | ||
|
|
5d42dfb1e6 | ||
|
|
fa9d2cefcc | ||
|
|
f19c4280c0 | ||
|
|
402c29c2bc | ||
|
|
3e29777526 | ||
|
|
2518190b2d | ||
|
|
31aad28a31 | ||
|
|
58edc79820 | ||
|
|
a729f04695 | ||
|
|
849d426e06 | ||
|
|
bc5da631c8 | ||
|
|
9bb69ab311 | ||
|
|
dc9dd5fabf | ||
|
|
4511e1c28d | ||
|
|
e79778ac6d | ||
|
|
d5a98e0189 | ||
|
|
73768f6313 | ||
|
|
eb14c762af | ||
|
|
a74ef412fb | ||
|
|
60cd2550a7 | ||
|
|
576ad85eb4 | ||
|
|
f2a9f31135 | ||
|
|
98c0fdc7e8 | ||
|
|
bdb79a0630 | ||
|
|
fbd7c0ce01 | ||
|
|
b9ac800bfb | ||
|
|
eecb537808 | ||
|
|
09d3f60d85 | ||
|
|
c03bf80864 | ||
|
|
299cea0601 | ||
|
|
a12ccf2c1d | ||
|
|
1c56857f0c | ||
|
|
3d443e0126 | ||
|
|
ec2d3307fd | ||
|
|
e4d8f7af61 | ||
|
|
19f840cde7 | ||
|
|
c9ff09a418 | ||
|
|
ee3befb9fc | ||
|
|
16981d6316 | ||
|
|
34131c2948 | ||
|
|
87deb19bcb | ||
|
|
6fef6ac3a2 | ||
|
|
4433ef47fe | ||
|
|
4d5f70c694 | ||
|
|
f8fd2ec4ad | ||
|
|
4a5d978abb | ||
|
|
e0ebeacd4d | ||
|
|
d9a1db044a | ||
|
|
47c5334502 | ||
|
|
950a21a020 | ||
|
|
bad48d0722 | ||
|
|
c8edd1fb25 | ||
|
|
53a121d9e1 | ||
|
|
74b63a4ba4 | ||
|
|
362948324c | ||
|
|
4cac7feb67 | ||
|
|
d6b2e86155 | ||
|
|
7132d5a86a | ||
|
|
55f18a34a9 | ||
|
|
2c3ba95768 | ||
|
|
6ede3271ff | ||
|
|
0e9c0f621a | ||
|
|
47c1e09c75 | ||
|
|
9a2b1a5cf7 | ||
|
|
9c12b1c7da | ||
|
|
0db59b45b8 | ||
|
|
ef0ede7c13 | ||
|
|
62b94d5abf | ||
|
|
318eff7327 | ||
|
|
211564a6da | ||
|
|
7a8e8f890f | ||
|
|
7b47e43fd0 | ||
|
|
fc857d987b | ||
|
|
a849c29288 | ||
|
|
1f013055d2 | ||
|
|
2e887598ba | ||
|
|
aa94488065 | ||
|
|
163b71e019 | ||
|
|
a098809294 | ||
|
|
95325c4673 | ||
|
|
68c9a8177c | ||
|
|
f314685a8e | ||
|
|
0b34197815 | ||
|
|
b627011463 | ||
|
|
2aa9348759 | ||
|
|
6217cb636f | ||
|
|
2a458a4802 | ||
|
|
989744aba2 | ||
|
|
4dfee727e8 | ||
|
|
b2fd56094f | ||
|
|
03146b21be | ||
|
|
e0172a24b8 | ||
|
|
bd42e336c7 | ||
|
|
84d3e3d25f | ||
|
|
a194393efc | ||
|
|
bc8e9513bf | ||
|
|
f4094829c2 | ||
|
|
657377b0ab | ||
|
|
8019c8b665 | ||
|
|
4c73b040c8 | ||
|
|
d3a208eb8a | ||
|
|
7d0cb39f2a | ||
|
|
553932dc72 | ||
|
|
da7a74e604 | ||
|
|
15f3ea8d05 | ||
|
|
62350f2e5f | ||
|
|
e5ddb3bbd6 | ||
|
|
f425c9d315 | ||
|
|
a8500abd8f | ||
|
|
ee9ece8992 | ||
|
|
7468904968 | ||
|
|
8a68a96f77 | ||
|
|
fa34e0fae3 | ||
|
|
54679c5f49 | ||
|
|
d1d9011f4d | ||
|
|
9f476b2ce2 | ||
|
|
70ef40eb33 | ||
|
|
2e5016713a | ||
|
|
9a5e8a4b70 | ||
|
|
daa4b1dc65 | ||
|
|
c7aeb2160e | ||
|
|
4834390e6a | ||
|
|
bdd50c7553 | ||
|
|
999dca76c1 | ||
|
|
63e17ca546 | ||
|
|
a3bfbd0186 | ||
|
|
cc9fd88c0d | ||
|
|
96b0bcfd78 | ||
|
|
4ac0bb1bed | ||
|
|
92680b3fe4 | ||
|
|
4f5f8fd216 | ||
|
|
36f7a3f524 | ||
|
|
0fdcd8b27e | ||
|
|
20b1eabb9b | ||
|
|
b7ac697dce | ||
|
|
abf2943e4d | ||
|
|
43721f1206 | ||
|
|
0e8fa54f81 | ||
|
|
ad2998598f | ||
|
|
69d5f766a8 | ||
|
|
18c2376b50 | ||
|
|
39f1b714a5 | ||
|
|
0baac62099 | ||
|
|
046c096d86 | ||
|
|
de3af85ee1 | ||
|
|
cc1bb69671 | ||
|
|
30ca30370d | ||
|
|
710406aa76 | ||
|
|
ee3a56714e | ||
|
|
a095b08758 | ||
|
|
bfdab40aaf | ||
|
|
55d9d57112 | ||
|
|
f3e4347a8b | ||
|
|
d4351668ba | ||
|
|
ac66ae813f | ||
|
|
038ef32454 | ||
|
|
994de1f812 | ||
|
|
36f3cd1f70 | ||
|
|
ef9e5e523d | ||
|
|
9b87ca9209 | ||
|
|
186e75f9b2 | ||
|
|
6c2bd2a968 | ||
|
|
68594d97cb | ||
|
|
a90aa055f5 | ||
|
|
78099b0d1f | ||
|
|
1441ad8546 | ||
|
|
0dcfe74bc6 | ||
|
|
e54353c4da | ||
|
|
08145d88b9 | ||
|
|
a3952051e1 | ||
|
|
930078b6f5 | ||
|
|
cd8b56706b | ||
|
|
2f0c9947ce | ||
|
|
c33d49ecab | ||
|
|
f315a4f02c | ||
|
|
46b1d869b1 | ||
|
|
2166cbdd80 | ||
|
|
63f4f4f60c | ||
|
|
f553344aa1 | ||
|
|
0679454b48 | ||
|
|
3ad0fd48ef | ||
|
|
d1bdbd8189 | ||
|
|
bcbd679a75 | ||
|
|
e9094659d3 | ||
|
|
bdf29cb7c2 | ||
|
|
8cd18cac8c | ||
|
|
3877355555 | ||
|
|
dbab2fb955 | ||
|
|
c5594f2979 | ||
|
|
ff3b86b5ff | ||
|
|
23467bd7e4 | ||
|
|
8c0b873ae2 | ||
|
|
2e107398ae | ||
|
|
c4c0845b3b | ||
|
|
f8a77537a7 | ||
|
|
be0a0ced25 | ||
|
|
88b698c092 | ||
|
|
0f44362348 | ||
|
|
750888f6d3 | ||
|
|
4385b44e86 | ||
|
|
1b34ad65fa | ||
|
|
dca970946d | ||
|
|
e2a6d370f0 | ||
|
|
a31a4eebdd | ||
|
|
7bb6a14944 | ||
|
|
5a0e88771b | ||
|
|
d0c9cde0ba | ||
|
|
dd4f223a39 | ||
|
|
d191e67e51 | ||
|
|
cddf1530da | ||
|
|
52a03f18a1 | ||
|
|
6baeb659a7 | ||
|
|
fed117fbf7 | ||
|
|
ff5cc09eac | ||
|
|
100b31cb71 | ||
|
|
0080374a77 | ||
|
|
d685497a10 | ||
|
|
1f890718a2 | ||
|
|
05197db71b | ||
|
|
3aafd29768 | ||
|
|
0744abe87b | ||
|
|
d7547fc4ef | ||
|
|
601e55656c | ||
|
|
c6ccd2ee6a | ||
|
|
aa50eb3b03 | ||
|
|
4d1db9e32c | ||
|
|
6294e339e2 | ||
|
|
d3f5c795ff | ||
|
|
043b5d4b9a | ||
|
|
1fe5db2ec3 | ||
|
|
63eb7e5519 | ||
|
|
1317af8d85 | ||
|
|
b178675276 | ||
|
|
a1143228b2 | ||
|
|
02c47b8eb5 | ||
|
|
75f19312ec | ||
|
|
4bf441149d | ||
|
|
5374a4c9c4 | ||
|
|
e02b18c63c | ||
|
|
de3de541e7 | ||
|
|
2097b716f4 | ||
|
|
acea58ebe7 | ||
|
|
3f2e2371ef | ||
|
|
272ed98db5 | ||
|
|
d406c80942 | ||
|
|
1338c25896 | ||
|
|
5e42d7aed0 | ||
|
|
34e240ef0e | ||
|
|
cc39afef46 | ||
|
|
9cb9e5beee | ||
|
|
880d634dc8 | ||
|
|
ff449ad8ab | ||
|
|
6009023fad | ||
|
|
09dfe2f2ab | ||
|
|
0415ed34ce | ||
|
|
c929f5ed7a | ||
|
|
5c5b4d0f5f | ||
|
|
af066a4630 | ||
|
|
2b27e9eda1 | ||
|
|
db06a4e241 | ||
|
|
02adf44768 | ||
|
|
78a53bfa06 | ||
|
|
d3760f3000 | ||
|
|
dd6c0ad001 | ||
|
|
9c3eb8f51f | ||
|
|
72a520fba4 | ||
|
|
9596e458c6 | ||
|
|
548d543efe | ||
|
|
103cd3d6f3 | ||
|
|
cd6b8b2f6d | ||
|
|
1f2f66bcb0 | ||
|
|
4fe3000275 | ||
|
|
e2c4435cab | ||
|
|
606ddc3181 | ||
|
|
07985e2f5a | ||
|
|
75c500c9a5 | ||
|
|
e886cc40fe | ||
|
|
c428108713 | ||
|
|
d80f23ed94 | ||
|
|
07a90ad4fe | ||
|
|
2afb66d68d | ||
|
|
fcf0450294 | ||
|
|
4e346180e0 | ||
|
|
029799e2e8 | ||
|
|
764d4fa1ad | ||
|
|
5bebcf61fe | ||
|
|
e8db5dfd67 | ||
|
|
cf4a21d095 | ||
|
|
c8436eb9c0 | ||
|
|
0a626bd8ae | ||
|
|
2fda221b7c | ||
|
|
9249facaf5 | ||
|
|
7db34b994e | ||
|
|
cb23d6f1a8 | ||
|
|
d497dcad41 | ||
|
|
bc6d2dba37 | ||
|
|
ce72a0ac27 | ||
|
|
9d5268ab6d | ||
|
|
17eecb1981 | ||
|
|
5906890b78 | ||
|
|
4b59e42d3f | ||
|
|
bf94370d38 | ||
|
|
eb2d69a5e6 | ||
|
|
5e847c7afa | ||
|
|
4d821f44ae | ||
|
|
c049771a7f | ||
|
|
1a1548da3b | ||
|
|
8e2f81816f | ||
|
|
1ca5947a7d | ||
|
|
7650c47e72 | ||
|
|
1818054166 | ||
|
|
175ba78d32 | ||
|
|
cf083bf827 | ||
|
|
907fc8a713 | ||
|
|
5ec3093deb | ||
|
|
7e88649730 | ||
|
|
955db48c59 | ||
|
|
5bd6e92cb8 | ||
|
|
bac61fc24e | ||
|
|
6e1ef193dd | ||
|
|
a225f329c5 | ||
|
|
2cc07e6112 | ||
|
|
e8f5d7680f | ||
|
|
47715c39d0 | ||
|
|
56f75922b9 | ||
|
|
88d07ce603 | ||
|
|
edd94b66e5 | ||
|
|
e38f2f990c | ||
|
|
5c9a882226 | ||
|
|
fe5242a876 | ||
|
|
f5d614d80d | ||
|
|
39209c2b40 | ||
|
|
9f5eb899e8 | ||
|
|
050c6daff3 | ||
|
|
c016ca5ad9 | ||
|
|
57a4199f52 | ||
|
|
222c46f639 | ||
|
|
fb7f50868d | ||
|
|
b323bf0fb6 | ||
|
|
38d64e8dd2 | ||
|
|
fb6efb9e9a | ||
|
|
e77f755765 | ||
|
|
56e59b47fe | ||
|
|
9b95accf6b | ||
|
|
c220245414 | ||
|
|
db1d77cba2 | ||
|
|
0c3aa7d8fe | ||
|
|
226b755798 | ||
|
|
c7dc4dc7fc | ||
|
|
fede4f9f1b | ||
|
|
e16ba28a8c | ||
|
|
052b38bdf3 | ||
|
|
61c0970968 | ||
|
|
1c3ef01209 | ||
|
|
9fed576cb4 | ||
|
|
e011c91921 | ||
|
|
7eb3ca408f | ||
|
|
422aa6b657 | ||
|
|
c27db070db | ||
|
|
4a06e830ca | ||
|
|
aa26ca5c27 | ||
|
|
5b5f448af0 | ||
|
|
f1136b57dd | ||
|
|
d877d46557 | ||
|
|
9c058fee7a | ||
|
|
e2eb9fe35e | ||
|
|
6bc8567802 | ||
|
|
819597faf6 | ||
|
|
27c08d0e0e | ||
|
|
ecb9ff0f8a | ||
|
|
5a3b1ee3fd | ||
|
|
c87a4fd642 | ||
|
|
57e8cd2ba2 | ||
|
|
40520c54d4 | ||
|
|
5ff259e870 | ||
|
|
d1ea4abb12 | ||
|
|
74e811706b | ||
|
|
26e1779f20 | ||
|
|
eaaa44c6c1 | ||
|
|
91faa3593a | ||
|
|
ebbef827ff | ||
|
|
5339f3dffa | ||
|
|
516f3663c0 | ||
|
|
4d9fd1b045 | ||
|
|
e623d745f5 | ||
|
|
1d2dee8a4e | ||
|
|
71786dba64 | ||
|
|
5936e8dbca | ||
|
|
d143b24232 | ||
|
|
249f5ec31a | ||
|
|
2cbd945692 | ||
|
|
66eb9593d1 | ||
|
|
59e366ce90 | ||
|
|
5d06b01fd6 | ||
|
|
c5829419e3 | ||
|
|
c094ac3584 | ||
|
|
2b4a8e9083 | ||
|
|
20adae8b21 | ||
|
|
da46ad4013 | ||
|
|
0d62bb2261 | ||
|
|
4c52ecc4d8 | ||
|
|
06c9f3368a | ||
|
|
714caeafb6 | ||
|
|
2231348356 | ||
|
|
2bce20f790 | ||
|
|
d21d7591c0 | ||
|
|
6bf8596d68 | ||
|
|
525e837c5b | ||
|
|
8891f04f11 | ||
|
|
134ca38b8d | ||
|
|
c3702be9d4 | ||
|
|
68ef13e37f | ||
|
|
cff9865c47 | ||
|
|
c22dfa1abb | ||
|
|
f0fa96fc46 | ||
|
|
00bab74d17 | ||
|
|
ee54363163 | ||
|
|
320ba9eac2 | ||
|
|
fd8f8719f8 | ||
|
|
bcc14b5274 | ||
|
|
a9229899f6 | ||
|
|
06ac7bf16c | ||
|
|
385cf8af8c | ||
|
|
40f9a40aa1 | ||
|
|
adc2ba405b | ||
|
|
d4f0ac4a63 | ||
|
|
1ec8eb8f57 | ||
|
|
363999d197 | ||
|
|
e21f945802 | ||
|
|
396cf9b822 | ||
|
|
705ffda574 | ||
|
|
f51bf67554 | ||
|
|
3c971455e7 | ||
|
|
5ed19319dd | ||
|
|
dac69e2092 | ||
|
|
72caec10fe | ||
|
|
922128f6e0 | ||
|
|
3de2b7c989 | ||
|
|
cd713a239e | ||
|
|
453e6deb97 | ||
|
|
27dde2a811 | ||
|
|
2a9a1d3194 | ||
|
|
be833dce4f | ||
|
|
92537f1fd5 | ||
|
|
ae0edbfdce | ||
|
|
9487d6c9d6 | ||
|
|
5539f87912 | ||
|
|
85b66946ed | ||
|
|
5b79752e5d | ||
|
|
1e412a8711 | ||
|
|
6dbfe2aab9 | ||
|
|
c0d46eb1af | ||
|
|
ae6e58f918 | ||
|
|
3ade01f828 | ||
|
|
db3fa8df77 | ||
|
|
9da5be3d79 | ||
|
|
245e1986c1 | ||
|
|
b39952549f | ||
|
|
c30ca534a3 | ||
|
|
028e9c9294 | ||
|
|
b66c0f8d30 | ||
|
|
ec508a70a6 | ||
|
|
00ab12ce9b | ||
|
|
e90a9b3c87 | ||
|
|
d51a2add65 | ||
|
|
6eda6dfe06 | ||
|
|
462cda400b | ||
|
|
fb15278f97 | ||
|
|
a56f656a83 | ||
|
|
fa095a98ed | ||
|
|
0d352b4e06 | ||
|
|
84a1cd245c | ||
|
|
3f6b7e2456 | ||
|
|
d535f3fe56 | ||
|
|
33b934cbb3 | ||
|
|
dd74757032 | ||
|
|
33a31ca393 | ||
|
|
67df4e3ce3 | ||
|
|
1d35ca4bc5 | ||
|
|
17a4537215 | ||
|
|
ec5bbaa678 | ||
|
|
5aacf563d8 | ||
|
|
1734eeaf0c | ||
|
|
bea4882b04 | ||
|
|
428b68f3e0 | ||
|
|
3bf89893dc | ||
|
|
813775e719 | ||
|
|
e749efcb97 | ||
|
|
3d0665183c | ||
|
|
b4560d442b | ||
|
|
b481bc95b5 | ||
|
|
dc16255605 | ||
|
|
9052f9fbb4 | ||
|
|
1682994b7e | ||
|
|
9724c99341 | ||
|
|
ee72d6cdca | ||
|
|
0e0028260f | ||
|
|
241834205f | ||
|
|
e768796491 | ||
|
|
d89648147f | ||
|
|
0f60701995 | ||
|
|
6d2b3b8698 | ||
|
|
4e861cf86e | ||
|
|
145694d828 | ||
|
|
48f6fe6d69 | ||
|
|
5231e86b6c | ||
|
|
6b73b69b41 | ||
|
|
35da6ac270 | ||
|
|
d5c0506faa | ||
|
|
fb1f2c4f18 | ||
|
|
7f3c8efab0 | ||
|
|
7bb7fc0f49 | ||
|
|
3449b8f9dc | ||
|
|
7a0ae36c4a | ||
|
|
cf031bbee4 | ||
|
|
1e73820277 | ||
|
|
839ca82a19 | ||
|
|
446a3b22dc | ||
|
|
028665030f | ||
|
|
7d6e933348 | ||
|
|
0cf676b574 | ||
|
|
7727b9dc79 | ||
|
|
5aac1b59b1 | ||
|
|
cfe29406e5 | ||
|
|
42773b9b1c | ||
|
|
179cf269c6 | ||
|
|
ba405bacbf | ||
|
|
5c9352fae4 | ||
|
|
e274925b2a | ||
|
|
8fb8199a55 | ||
|
|
a3f0d00714 | ||
|
|
f128718d34 | ||
|
|
ed3c66b6a6 | ||
|
|
66bc8ceddd | ||
|
|
2a587a771c | ||
|
|
c70a9d0e67 | ||
|
|
9c5c124155 | ||
|
|
59d1eea4c8 | ||
|
|
9d405738c0 | ||
|
|
466dda2b14 | ||
|
|
5948dac889 | ||
|
|
53450b7e2f | ||
|
|
731cfb1553 | ||
|
|
c49a6dfdef | ||
|
|
d4054e3d85 | ||
|
|
c83d5b88e1 | ||
|
|
58f33d227a | ||
|
|
de6a518161 | ||
|
|
b5a72e21f7 | ||
|
|
d74d3a87bb | ||
|
|
dffad48504 | ||
|
|
f9f70e3e55 | ||
|
|
c12b4e9cba | ||
|
|
d69363ef11 | ||
|
|
708afb7146 | ||
|
|
213fd69b2b | ||
|
|
5ffa616d98 | ||
|
|
160cece017 | ||
|
|
ee5227733b | ||
|
|
01ffc1227a | ||
|
|
4fe04e63ac | ||
|
|
fe3ba12801 | ||
|
|
79d84f30f5 | ||
|
|
9444c6bd4b | ||
|
|
8c990adabe | ||
|
|
118552d4d2 | ||
|
|
514eda82fb | ||
|
|
5e060cef7c | ||
|
|
6378ec5d69 | ||
|
|
03143bf9ad | ||
|
|
a5355d86fc | ||
|
|
70f6f5f3ef | ||
|
|
313ee596f5 | ||
|
|
1770f8b783 | ||
|
|
03969d5f90 | ||
|
|
172ddb47d5 | ||
|
|
99fc04b9a6 | ||
|
|
36b1535199 | ||
|
|
188b5f4781 | ||
|
|
9f70697046 | ||
|
|
796726376a | ||
|
|
4537ab6b1a | ||
|
|
725afc3848 | ||
|
|
527f1d20ad | ||
|
|
ab7f8ad1bf | ||
|
|
c7b8ae9013 | ||
|
|
358e83a849 | ||
|
|
d49d79121c | ||
|
|
ae7c40920e | ||
|
|
914ebd9ba3 | ||
|
|
08e44c0850 | ||
|
|
ddc9f06786 | ||
|
|
7ddea62331 | ||
|
|
37753cbdc2 | ||
|
|
16c449748a | ||
|
|
2418efe85c | ||
|
|
b50e3af07c | ||
|
|
05829cbda9 | ||
|
|
66bd0ce3d0 | ||
|
|
3dadefcfb0 | ||
|
|
0dc9215c89 | ||
|
|
daf37cbe58 | ||
|
|
f185bbed3c | ||
|
|
53798c7904 | ||
|
|
6b016da185 | ||
|
|
31afb62e95 | ||
|
|
a88979631e | ||
|
|
f2d5bbc671 | ||
|
|
4bb2e2f8af | ||
|
|
5167d20f27 | ||
|
|
a067ffb92d | ||
|
|
cc492ffed4 | ||
|
|
dfda0877c0 | ||
|
|
a7294be94f | ||
|
|
8699571654 | ||
|
|
adbbe8f453 | ||
|
|
2ea859e4e5 | ||
|
|
684e10d718 | ||
|
|
dd67772ad9 | ||
|
|
024cfd86e4 | ||
|
|
8e15d4807f | ||
|
|
bfae2c8348 | ||
|
|
68fd189586 | ||
|
|
5660f8e554 | ||
|
|
fc9bc175e6 | ||
|
|
066f6b1f8a | ||
|
|
f2e020e398 | ||
|
|
9cdf6b88ad | ||
|
|
961cb961e9 | ||
|
|
5c9a79442c | ||
|
|
8f02eb0a34 | ||
|
|
bb9f326f9b | ||
|
|
eef7828681 | ||
|
|
de3a1d87b3 | ||
|
|
b5d9ac0690 | ||
|
|
17d7e7e5e1 | ||
|
|
df0b1cb8ed | ||
|
|
dabb4e064f | ||
|
|
d303852609 | ||
|
|
a9cebe81ea | ||
|
|
0ca42a8e4d | ||
|
|
8a8ce16a1f | ||
|
|
1a52c6a3b8 | ||
|
|
725375541d | ||
|
|
95706d9be2 | ||
|
|
896fe854dc | ||
|
|
bc9eab9902 | ||
|
|
8b6496715f | ||
|
|
e6c5435f72 | ||
|
|
22c5d510a0 | ||
|
|
4640a6e382 | ||
|
|
9b5a27f195 | ||
|
|
f0066a859a | ||
|
|
aa766c0664 | ||
|
|
25ace49ec1 | ||
|
|
84b893a7bd | ||
|
|
a6a232fa47 | ||
|
|
940f79e7c0 | ||
|
|
fdad607de4 | ||
|
|
4fd9170958 | ||
|
|
c6f4d507e9 | ||
|
|
ba848cf0e6 | ||
|
|
dd7ce3755c | ||
|
|
35e1820f8a | ||
|
|
a608bdb8d4 | ||
|
|
ce568c34f9 | ||
|
|
2dbb44b725 | ||
|
|
0070097af8 | ||
|
|
7dd28a9003 | ||
|
|
8d57a35531 | ||
|
|
78aa79bb15 | ||
|
|
cbd3fa2190 | ||
|
|
643ee17544 | ||
|
|
020c79970f | ||
|
|
453a645356 | ||
|
|
a67b0edfb2 | ||
|
|
f0662475ad | ||
|
|
5dfbab5424 | ||
|
|
6575cacc5d | ||
|
|
07b2449bd7 | ||
|
|
87110ebce4 | ||
|
|
f9d2451b23 | ||
|
|
30dfd92577 | ||
|
|
e17724a73a | ||
|
|
8c3250396f | ||
|
|
c67e3e7e1d | ||
|
|
18f327781d | ||
|
|
6a734e2746 | ||
|
|
03a62aaa33 | ||
|
|
4ff17409ab | ||
|
|
a59bad83d4 | ||
|
|
42e05ce494 | ||
|
|
4bdf7b560b | ||
|
|
307477a62a | ||
|
|
51dd41bb72 | ||
|
|
0fdb4b7c23 | ||
|
|
475364248f | ||
|
|
22d8074c49 | ||
|
|
4d252647ef | ||
|
|
f988d997ff | ||
|
|
0ed87c5d56 | ||
|
|
57bd3c35c2 | ||
|
|
b53ccf893f | ||
|
|
4ad823e97a | ||
|
|
f7b273460d | ||
|
|
9ac0cf7d14 | ||
|
|
5f553601f7 | ||
|
|
c1a7bb4f62 | ||
|
|
eadf84d8cf | ||
|
|
c82c4b6877 | ||
|
|
2c982cf5b3 | ||
|
|
278570bc38 | ||
|
|
3d67346f77 | ||
|
|
21486da2b4 | ||
|
|
820fecb481 | ||
|
|
f39eda150f | ||
|
|
a5df955a39 | ||
|
|
63e98286e9 | ||
|
|
6044f643ed | ||
|
|
65937947a9 | ||
|
|
a48128d317 | ||
|
|
207a5f054b | ||
|
|
dfc2ee2a88 | ||
|
|
1fd2f2c80e | ||
|
|
94f1c4d2a9 | ||
|
|
8953a822a4 | ||
|
|
e5341d28e4 | ||
|
|
d8b69c2656 | ||
|
|
796f279aec | ||
|
|
b99a815da5 | ||
|
|
61d44488dd | ||
|
|
344d359ba9 | ||
|
|
296f67197e | ||
|
|
bf80273577 | ||
|
|
d07cebc220 | ||
|
|
6ecbaf3468 | ||
|
|
a4ed34ceaf | ||
|
|
876074cc50 | ||
|
|
5eb9002868 | ||
|
|
2b73b6a80c | ||
|
|
5d52aaf49d | ||
|
|
245a369d9f | ||
|
|
d5886dc180 | ||
|
|
bf7946e31c | ||
|
|
071df0263c | ||
|
|
d625a5b99c | ||
|
|
948c0d08f3 | ||
|
|
262a2fc5fb | ||
|
|
51f49c4df4 | ||
|
|
c42f674089 | ||
|
|
7a55ea717d | ||
|
|
057656f8be | ||
|
|
d6a90b0abd | ||
|
|
8ae2974a8e | ||
|
|
575c54f48e | ||
|
|
ac2e0e227a | ||
|
|
35284589cb | ||
|
|
1573c101a7 | ||
|
|
ac53f7fea9 | ||
|
|
4fa7619b1f | ||
|
|
62a0336425 | ||
|
|
0d5aec12d4 | ||
|
|
1c48fe05fd | ||
|
|
56f0fc4ec2 | ||
|
|
e954360eec | ||
|
|
389d8b5b5d | ||
|
|
78530c6c17 | ||
|
|
51d50358a0 | ||
|
|
a27eea3450 | ||
|
|
3d8efbc6df | ||
|
|
c51ca98e14 | ||
|
|
c9aa4a1f84 | ||
|
|
a2947d0c23 | ||
|
|
956511f7ef | ||
|
|
5ae645828f | ||
|
|
9924cfdf3c | ||
|
|
5da6d2bd88 | ||
|
|
b1f85dce71 | ||
|
|
b69958b412 | ||
|
|
87f8340da4 | ||
|
|
c90eea2b31 | ||
|
|
bac71613de | ||
|
|
24fa7a94d0 | ||
|
|
02b98b9565 | ||
|
|
938a7270eb | ||
|
|
aa2b060da8 | ||
|
|
bfb92976cb | ||
|
|
c08849883d | ||
|
|
c369e8161c | ||
|
|
cafc1a2c13 | ||
|
|
97341a14b9 | ||
|
|
8f0baa45b6 | ||
|
|
0d5f08a2fd | ||
|
|
2defa10d37 | ||
|
|
5f714b707c | ||
|
|
f420005b57 | ||
|
|
6232aac95a | ||
|
|
11164e2450 | ||
|
|
65e0d54fa5 | ||
|
|
821c7d7f2c | ||
|
|
f0b7b95d05 | ||
|
|
d7b6f1cb5d | ||
|
|
c12deed12e | ||
|
|
4f693c6db0 | ||
|
|
964202adff | ||
|
|
920f2f437e | ||
|
|
b160fd40c8 | ||
|
|
afdf0389a3 | ||
|
|
4c8e9a1414 | ||
|
|
e9de641705 | ||
|
|
2199f6f60d | ||
|
|
0cb60aea8f | ||
|
|
1ccbc655eb | ||
|
|
e6aba5979a | ||
|
|
fedd24522c | ||
|
|
908a9bbb4c | ||
|
|
62b1757b07 | ||
|
|
e8ba5045d9 | ||
|
|
3f5ffc7026 | ||
|
|
356a58d5f6 | ||
|
|
d871b4d267 | ||
|
|
89dbb9888c | ||
|
|
983f809951 | ||
|
|
e1cd0547de | ||
|
|
d25928f125 | ||
|
|
4f51f05133 | ||
|
|
54e02f5b11 | ||
|
|
add79a4b24 | ||
|
|
b0157649af | ||
|
|
e91669821e | ||
|
|
02478e5b95 | ||
|
|
3a62eab163 | ||
|
|
26df7b4ad5 | ||
|
|
76a9e1d37d | ||
|
|
5bad7fc4f3 | ||
|
|
8f9663ac67 | ||
|
|
93e654212c | ||
|
|
7da6147bf8 | ||
|
|
498c608667 | ||
|
|
f29e1e4c29 | ||
|
|
e516bba8fc | ||
|
|
307ebeaa19 | ||
|
|
e6a85c5901 | ||
|
|
ba2cf5dbbc | ||
|
|
de1ae2bd48 | ||
|
|
499fb2c631 | ||
|
|
bbfe5c0ae8 | ||
|
|
b224b8331a | ||
|
|
9c065951e7 | ||
|
|
e1a440fa36 | ||
|
|
ce668d46cc | ||
|
|
07cd1d89d0 | ||
|
|
c8185694be | ||
|
|
55f3b46f41 | ||
|
|
9e4ba6762f | ||
|
|
5a13e64dc6 | ||
|
|
8c27d4d47f | ||
|
|
bd1c3fcba4 | ||
|
|
1bf04015c6 | ||
|
|
f04b4e87fb | ||
|
|
c618767c6b | ||
|
|
b7ac526257 | ||
|
|
b549977f05 | ||
|
|
467e612533 | ||
|
|
b4ab36a6a5 | ||
|
|
10c78960a7 | ||
|
|
a2f0b988d4 | ||
|
|
c10cee3a39 | ||
|
|
d1e13ab3e4 | ||
|
|
2a7bfa4bb3 | ||
|
|
0f301450e0 | ||
|
|
27c93f438a | ||
|
|
bf5ff55074 | ||
|
|
e90246fd1f | ||
|
|
9a339f08a7 | ||
|
|
f5843fe588 | ||
|
|
49231da42f | ||
|
|
517f254726 | ||
|
|
f95d9cde40 | ||
|
|
49992dd9d2 | ||
|
|
3e74ff174c | ||
|
|
b4c4ab7790 | ||
|
|
5331dc740a | ||
|
|
27952e7057 | ||
|
|
0ce5864fc7 | ||
|
|
593c653ab5 | ||
|
|
d36bccdc8c | ||
|
|
513852b7c3 | ||
|
|
e94360486e | ||
|
|
b17db6d669 | ||
|
|
f4b6c3049b | ||
|
|
55391bb587 | ||
|
|
38e2843b24 | ||
|
|
7c8423a522 | ||
|
|
ec8351d336 | ||
|
|
e4f93b293f | ||
|
|
2b4b771449 | ||
|
|
538d1bb245 | ||
|
|
3ac387bb66 | ||
|
|
fe37d914e5 | ||
|
|
51da5adbc7 | ||
|
|
3cc8434c5a | ||
|
|
c641bbfb9e | ||
|
|
2e9cc654ef | ||
|
|
f03de27a92 | ||
|
|
601896b1fc | ||
|
|
2e5f3ed851 | ||
|
|
a38dc90abe | ||
|
|
efda57e8a5 | ||
|
|
44690fb299 | ||
|
|
f9f0bc687d | ||
|
|
4d2247a7e1 | ||
|
|
743c0bde7e | ||
|
|
c975f97ce8 | ||
|
|
76d897eaa2 | ||
|
|
a08c24c4aa | ||
|
|
fca3a525d0 | ||
|
|
db5edb3a42 | ||
|
|
3a2a930ad3 | ||
|
|
7e94dc5b40 | ||
|
|
cdbf8f394a | ||
|
|
173d5d09bf | ||
|
|
c5e7d870f0 | ||
|
|
1e47e65ac5 | ||
|
|
271510f0a8 | ||
|
|
63afa24c11 | ||
|
|
ce1d18e534 | ||
|
|
4afeabe042 | ||
|
|
6cf681df68 | ||
|
|
52f8734662 | ||
|
|
7b40b6426c | ||
|
|
2d63722150 | ||
|
|
e8a678b75a | ||
|
|
bc65c245fe | ||
|
|
a9075fdb1f | ||
|
|
8baf754615 | ||
|
|
cf90def462 | ||
|
|
9db431b430 | ||
|
|
f155138659 | ||
|
|
efc1ab83d4 | ||
|
|
68c77d6e9f | ||
|
|
063914af04 | ||
|
|
b7f3e0bb50 | ||
|
|
de82d90b9c | ||
|
|
cfc440c56c | ||
|
|
83fedcc9ea | ||
|
|
cddcff2c63 | ||
|
|
e889f17421 | ||
|
|
c23876d536 | ||
|
|
fe2be5ffea | ||
|
|
1ef839ca6d | ||
|
|
f5bd183cc5 | ||
|
|
7906e7b5ff | ||
|
|
11dbae78cb | ||
|
|
86d7b04eaa | ||
|
|
bfa2c46430 | ||
|
|
e465876ed4 | ||
|
|
37f900a264 | ||
|
|
783dbb5040 | ||
|
|
452e26ea79 | ||
|
|
529954fbcb | ||
|
|
b168520ad2 | ||
|
|
7b21e8fbae | ||
|
|
76568807c4 | ||
|
|
3f86df1445 | ||
|
|
95b3f31d9c | ||
|
|
17a65b1e03 | ||
|
|
0f0f299b3e | ||
|
|
6c045f4228 | ||
|
|
947391778e | ||
|
|
4c1e2bcc7a | ||
|
|
6748c4361f | ||
|
|
7e91d18853 | ||
|
|
2f11f66167 | ||
|
|
7263c7cb47 | ||
|
|
9ee56bbc5b | ||
|
|
96cea5aa1f | ||
|
|
9967f52657 | ||
|
|
84ef17d818 | ||
|
|
fda9c60e25 | ||
|
|
68a982dfe6 | ||
|
|
69a7bfc88d | ||
|
|
0e096e8001 | ||
|
|
5ece57bd34 | ||
|
|
8a390f03e3 | ||
|
|
f3c538a3dd | ||
|
|
cd15655ed3 | ||
|
|
c457add848 | ||
|
|
19170d94c8 | ||
|
|
594e5a50a3 | ||
|
|
3310315d4b | ||
|
|
80f76947d1 | ||
|
|
89da4f82d3 | ||
|
|
5a9ddbba2e | ||
|
|
181a901f75 | ||
|
|
aab645e01c | ||
|
|
e9c0ca545f | ||
|
|
6e01a68276 | ||
|
|
4b0452b87b | ||
|
|
de9daf7ad9 | ||
|
|
c225e17a75 | ||
|
|
99c414e4da | ||
|
|
0c12369084 | ||
|
|
8538796128 | ||
|
|
2a62c40526 | ||
|
|
08aaebbf7c | ||
|
|
caad29b5b3 | ||
|
|
54387b4589 | ||
|
|
40e77be813 | ||
|
|
8afe973968 | ||
|
|
99a1601aea | ||
|
|
06077d42a8 | ||
|
|
6844735a45 | ||
|
|
02b69709bb | ||
|
|
35c8b7a162 | ||
|
|
4f363e1180 | ||
|
|
7e679d56ea | ||
|
|
aef325a416 | ||
|
|
9998a11fdd | ||
|
|
cd136ad847 | ||
|
|
a29cdefedf | ||
|
|
a6d16ed477 | ||
|
|
dea430649d | ||
|
|
9423d59132 | ||
|
|
cbfdba2ca6 | ||
|
|
eb4ca010ae | ||
|
|
8200261506 | ||
|
|
601d011986 | ||
|
|
c5c5f4dbc1 | ||
|
|
717a3991f4 | ||
|
|
4202fba0f1 | ||
|
|
71d174bad6 | ||
|
|
a5e65d572a | ||
|
|
93b83febc2 | ||
|
|
481a63da55 | ||
|
|
ae0f2ce3c1 | ||
|
|
4ecfce98f6 | ||
|
|
e80d194b8f | ||
|
|
7c8e1bb46e | ||
|
|
996cced3d4 | ||
|
|
5377b6cb2f | ||
|
|
c5b7f7a08c | ||
|
|
34b1db219c | ||
|
|
662c1ed618 | ||
|
|
4428bde024 | ||
|
|
a1983e468b | ||
|
|
eda304bda9 | ||
|
|
9377227e06 | ||
|
|
62433c14a7 | ||
|
|
bbe209a9e8 | ||
|
|
3e6d966513 | ||
|
|
559605e393 | ||
|
|
31d0c542e2 | ||
|
|
104299a211 | ||
|
|
47d629f50c | ||
|
|
fb919c718d | ||
|
|
265390c243 | ||
|
|
ebcf4e044b | ||
|
|
5ed48760fb | ||
|
|
601432ad82 | ||
|
|
a9681fa3f3 | ||
|
|
e5837b46e5 | ||
|
|
949e6b52e6 | ||
|
|
cfa0556df7 | ||
|
|
27acc0b133 | ||
|
|
5beda309ab | ||
|
|
394abced43 | ||
|
|
9a4bdeabbd | ||
|
|
3f24083ed6 | ||
|
|
5cde275965 | ||
|
|
ebdf1bbdd5 | ||
|
|
c661518bb1 | ||
|
|
870e94809c | ||
|
|
1b9e2581d2 | ||
|
|
a498d6d10f | ||
|
|
30bc8f06dc | ||
|
|
24fc2b67d8 | ||
|
|
2a06c08c6b | ||
|
|
6e8ea2753b | ||
|
|
c38529741e | ||
|
|
848a7ffbf3 | ||
|
|
c3149994ac | ||
|
|
d318df96ae | ||
|
|
208afc96a1 | ||
|
|
6052ef656d | ||
|
|
87e1c3f2fd | ||
|
|
9d0928633a | ||
|
|
1d3fdc74dc | ||
|
|
271fbc064e | ||
|
|
976b098421 | ||
|
|
9c3915d42c | ||
|
|
e39bb57c07 | ||
|
|
08700f8cb9 | ||
|
|
6683d292ce | ||
|
|
ad752f04c7 | ||
|
|
c990baf96a | ||
|
|
59f0057017 | ||
|
|
8e3cecda9f | ||
|
|
9022f5c519 | ||
|
|
fdc2dbe7db | ||
|
|
fa74d32a6a | ||
|
|
5ab95aaf7d | ||
|
|
1c742f5866 | ||
|
|
5603453c18 | ||
|
|
29a5b72d5f | ||
|
|
e2b708e8f7 | ||
|
|
48bff6b352 | ||
|
|
12fe2929a4 | ||
|
|
9fea3154fa | ||
|
|
3a34c7ff7c | ||
|
|
f25795c4e4 | ||
|
|
8bdf457dfa | ||
|
|
9fece4f811 | ||
|
|
3e147f8693 | ||
|
|
0d0e47acf7 | ||
|
|
ca47717eb0 | ||
|
|
a664e21054 | ||
|
|
a23bfeda0a | ||
|
|
5b1d6b2850 | ||
|
|
356b0d8ee5 | ||
|
|
c0f8dfc7f9 | ||
|
|
79cf2060e5 | ||
|
|
fcf90dffa8 | ||
|
|
8ae4662f17 | ||
|
|
546d48adbb | ||
|
|
d69a1870a0 | ||
|
|
bbcb722e50 | ||
|
|
951d7d66ac | ||
|
|
a52f0d6947 | ||
|
|
e1e3b99d03 | ||
|
|
10785e301e | ||
|
|
fcfdb819f2 | ||
|
|
ca033efc6c | ||
|
|
424afe09f5 | ||
|
|
0804c424c0 | ||
|
|
84b01a312f | ||
|
|
6cc1391173 | ||
|
|
70da454bbc | ||
|
|
9065a4e7d2 | ||
|
|
96dde34cdc | ||
|
|
a4c5446d2f | ||
|
|
34dca0eb31 | ||
|
|
e5ebfd5c50 | ||
|
|
fa76262b01 | ||
|
|
bc62a80b8c | ||
|
|
2ed5a346c4 | ||
|
|
1e3393cfa0 | ||
|
|
c9d98a5679 | ||
|
|
0710242f22 | ||
|
|
0c192232ca | ||
|
|
5dbee13b3e | ||
|
|
40a4806857 | ||
|
|
bccd654b01 | ||
|
|
883e455e12 | ||
|
|
528946d3cc | ||
|
|
585144578e | ||
|
|
38eecfc5d4 | ||
|
|
c73b24ad08 | ||
|
|
7b44b8b7e1 | ||
|
|
7369754192 | ||
|
|
a48f770195 | ||
|
|
86bd7a93b5 | ||
|
|
47adcd7f32 | ||
|
|
6db94e98b5 | ||
|
|
349e496da5 | ||
|
|
4b971ec7a9 | ||
|
|
c2183e47ec | ||
|
|
a0cf91dad0 | ||
|
|
9960c78923 | ||
|
|
2c833b507c | ||
|
|
46fcfd80d7 | ||
|
|
3ae74d1f2d | ||
|
|
12921e6ec3 | ||
|
|
28cbedb82f | ||
|
|
ed9e542781 | ||
|
|
fa3fea9dd8 | ||
|
|
ce210eebde | ||
|
|
cf010b63e3 | ||
|
|
6aee58fad6 | ||
|
|
4720b4f0e6 | ||
|
|
a19398445b | ||
|
|
bd281ee51c | ||
|
|
b07c07de05 | ||
|
|
560097931d | ||
|
|
4fce940a9c | ||
|
|
a2fd83367e | ||
|
|
33c2d98e66 | ||
|
|
d87422527b | ||
|
|
235670244e | ||
|
|
22e823b5f9 | ||
|
|
0df7832639 | ||
|
|
f94f08eddd | ||
|
|
bcfb8f4349 | ||
|
|
20007355d1 | ||
|
|
3f073dcd98 | ||
|
|
0f6e4041c7 | ||
|
|
30b497e758 | ||
|
|
cd7972d05b | ||
|
|
5083ca0e81 | ||
|
|
8a715cc1b5 | ||
|
|
ec6bfcbaa0 | ||
|
|
a47469f4c5 | ||
|
|
842b0939f6 | ||
|
|
b25dd0c055 | ||
|
|
a8c01f4cad | ||
|
|
d4d8625ab8 | ||
|
|
bfe55b9ded | ||
|
|
72a41c1642 | ||
|
|
6f3afab01d | ||
|
|
6e528426dd | ||
|
|
fcceaf081c | ||
|
|
e32b1c861f | ||
|
|
718cd64657 | ||
|
|
f274c4785d | ||
|
|
d0d9fc5bdf | ||
|
|
5e8459bb91 | ||
|
|
d5680ad376 | ||
|
|
ad7bd09819 | ||
|
|
86aa8bde8b | ||
|
|
36290ce72f |
37
.asf.yaml
37
.asf.yaml
@@ -17,7 +17,14 @@
|
||||
|
||||
# https://cwiki.apache.org/confluence/display/INFRA/.asf.yaml+features+for+git+repositories
|
||||
---
|
||||
notifications:
|
||||
commits: commits@superset.apache.org
|
||||
issues: notifications@superset.apache.org
|
||||
pullrequests: notifications@superset.apache.org
|
||||
discussions: notifications@superset.apache.org
|
||||
|
||||
github:
|
||||
del_branch_on_merge: true
|
||||
description: "Apache Superset is a Data Visualization and Data Exploration Platform"
|
||||
homepage: https://superset.apache.org/
|
||||
labels:
|
||||
@@ -47,12 +54,17 @@ github:
|
||||
projects: true
|
||||
# Enable wiki for documentation
|
||||
wiki: true
|
||||
# Enable discussions
|
||||
discussions: true
|
||||
|
||||
enabled_merge_buttons:
|
||||
squash: true
|
||||
merge: false
|
||||
rebase: false
|
||||
|
||||
ghp_branch: gh-pages
|
||||
ghp_path: /
|
||||
|
||||
protected_branches:
|
||||
master:
|
||||
required_status_checks:
|
||||
@@ -63,16 +75,22 @@ github:
|
||||
# combination here.
|
||||
contexts:
|
||||
- lint-check
|
||||
- cypress-matrix (0, chrome)
|
||||
- cypress-matrix (1, chrome)
|
||||
- cypress-matrix (2, chrome)
|
||||
- cypress-matrix (3, chrome)
|
||||
- cypress-matrix (4, chrome)
|
||||
- cypress-matrix (5, chrome)
|
||||
- dependency-review
|
||||
- frontend-build
|
||||
- pre-commit (3.9)
|
||||
- python-lint (3.9)
|
||||
- test-mysql (3.9)
|
||||
- test-postgres (3.9)
|
||||
- test-postgres (3.10)
|
||||
- test-sqlite (3.9)
|
||||
- pre-commit (current)
|
||||
- pre-commit (previous)
|
||||
- test-mysql
|
||||
- test-postgres (current)
|
||||
- test-postgres-hive
|
||||
- test-postgres-presto
|
||||
- test-sqlite
|
||||
- unit-tests (current)
|
||||
|
||||
required_pull_request_reviews:
|
||||
dismiss_stale_reviews: false
|
||||
@@ -80,3 +98,10 @@ github:
|
||||
required_approving_review_count: 1
|
||||
|
||||
required_signatures: false
|
||||
gh-pages:
|
||||
required_pull_request_reviews:
|
||||
dismiss_stale_reviews: false
|
||||
require_code_owner_reviews: true
|
||||
required_approving_review_count: 1
|
||||
|
||||
required_signatures: false
|
||||
|
||||
36
.coveragerc
Normal file
36
.coveragerc
Normal file
@@ -0,0 +1,36 @@
|
||||
# .coveragerc to control coverage.py
|
||||
[run]
|
||||
branch = True
|
||||
source = superset
|
||||
# omit = bad_file.py
|
||||
|
||||
[paths]
|
||||
source =
|
||||
superset/
|
||||
*/site-packages/
|
||||
|
||||
[report]
|
||||
# Regexes for lines to exclude from consideration
|
||||
exclude_lines =
|
||||
# Have to re-enable the standard pragma
|
||||
pragma: no cover
|
||||
|
||||
# Don't complain about missing debug-only code:
|
||||
def __repr__
|
||||
if self\.debug
|
||||
|
||||
# Don't complain if tests don't hit defensive assertion code:
|
||||
raise AssertionError
|
||||
raise NotImplementedError
|
||||
|
||||
# Don't complain if non-runnable code isn't run:
|
||||
if 0:
|
||||
if __name__ == .__main__.:
|
||||
|
||||
# Ignore importlib backport
|
||||
from importlib
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
#fail_under = 100
|
||||
show_missing = True
|
||||
125
.cursor/rules/dev-standard.mdc
Normal file
125
.cursor/rules/dev-standard.mdc
Normal file
@@ -0,0 +1,125 @@
|
||||
---
|
||||
description: Apache Superset development standards and guidelines for Cursor IDE
|
||||
globs: ["**/*.py", "**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.sql", "**/*.md"]
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Apache Superset Development Standards for Cursor IDE
|
||||
|
||||
Apache Superset is a data visualization platform with Flask/Python backend and React/TypeScript frontend.
|
||||
|
||||
## ⚠️ CRITICAL: Ongoing Refactors (What NOT to Do)
|
||||
|
||||
**These migrations are actively happening - avoid deprecated patterns:**
|
||||
|
||||
### Frontend Modernization
|
||||
- **NO `any` types** - Use proper TypeScript types
|
||||
- **NO JavaScript files** - Convert to TypeScript (.ts/.tsx)
|
||||
- **NO Enzyme** - Use React Testing Library/Jest (Enzyme fully removed)
|
||||
- **Use @superset-ui/core** - Don't import Ant Design directly
|
||||
|
||||
### Testing Strategy Migration
|
||||
- **Prefer unit tests** over integration tests
|
||||
- **Prefer integration tests** over Cypress end-to-end tests
|
||||
- **Cypress is last resort** - Actively moving away from Cypress
|
||||
- **Use Jest + React Testing Library** for component testing
|
||||
|
||||
### Backend Type Safety
|
||||
- **Add type hints** - All new Python code needs proper typing
|
||||
- **MyPy compliance** - Run `pre-commit run mypy` to validate
|
||||
- **SQLAlchemy typing** - Use proper model annotations
|
||||
|
||||
## Code Standards
|
||||
|
||||
### TypeScript Frontend
|
||||
- **NO `any` types** - Use proper TypeScript
|
||||
- **Functional components** with hooks
|
||||
- **@superset-ui/core** for UI components (not direct antd)
|
||||
- **Jest** for testing (NO Enzyme)
|
||||
- **Redux** for global state, hooks for local
|
||||
|
||||
### Python Backend
|
||||
- **Type hints required** for all new code
|
||||
- **MyPy compliant** - run `pre-commit run mypy`
|
||||
- **SQLAlchemy models** with proper typing
|
||||
- **pytest** for testing
|
||||
|
||||
### Apache License Headers
|
||||
- **New files require ASF license headers** - When creating new code files, include the standard Apache Software Foundation license header
|
||||
- **LLM instruction files are excluded** - Files like LLMS.md, CLAUDE.md, etc. are in `.rat-excludes` to avoid header token overhead
|
||||
|
||||
## Key Directory Structure
|
||||
|
||||
```
|
||||
superset/
|
||||
├── superset/ # Python backend (Flask, SQLAlchemy)
|
||||
│ ├── views/api/ # REST API endpoints
|
||||
│ ├── models/ # Database models
|
||||
│ └── connectors/ # Database connections
|
||||
├── superset-frontend/src/ # React TypeScript frontend
|
||||
│ ├── components/ # Reusable components
|
||||
│ ├── explore/ # Chart builder
|
||||
│ ├── dashboard/ # Dashboard interface
|
||||
│ └── SqlLab/ # SQL editor
|
||||
├── superset-frontend/packages/
|
||||
│ └── superset-ui-core/ # UI component library (USE THIS)
|
||||
├── tests/ # Python/integration tests
|
||||
├── docs/ # Documentation (UPDATE FOR CHANGES)
|
||||
└── UPDATING.md # Breaking changes log
|
||||
```
|
||||
|
||||
## Architecture Patterns
|
||||
|
||||
### Dataset-Centric Approach
|
||||
Charts built from enriched datasets containing:
|
||||
- Dimension columns with labels/descriptions
|
||||
- Predefined metrics as SQL expressions
|
||||
- Self-service analytics within defined contexts
|
||||
|
||||
### Security & Features
|
||||
- **RBAC**: Role-based access via Flask-AppBuilder
|
||||
- **Feature flags**: Control feature rollouts
|
||||
- **Row-level security**: SQL-based data access control
|
||||
|
||||
## Test Utilities
|
||||
|
||||
### Python Test Helpers
|
||||
- **`SupersetTestCase`** - Base class in `tests/integration_tests/base_tests.py`
|
||||
- **`@with_config`** - Config mocking decorator
|
||||
- **`@with_feature_flags`** - Feature flag testing
|
||||
- **`login_as()`, `login_as_admin()`** - Authentication helpers
|
||||
- **`create_dashboard()`, `create_slice()`** - Data setup utilities
|
||||
|
||||
### TypeScript Test Helpers
|
||||
- **`superset-frontend/spec/helpers/testing-library.tsx`** - Custom render() with providers
|
||||
- **`createWrapper()`** - Redux/Router/Theme wrapper
|
||||
- **`selectOption()`** - Select component helper
|
||||
- **React Testing Library** - NO Enzyme (removed)
|
||||
|
||||
## Pre-commit Validation
|
||||
|
||||
**Use pre-commit hooks for quality validation:**
|
||||
|
||||
```bash
|
||||
# Install hooks
|
||||
pre-commit install
|
||||
|
||||
# Quick validation (faster than --all-files)
|
||||
pre-commit run # Staged files only
|
||||
pre-commit run mypy # Python type checking
|
||||
pre-commit run prettier # Code formatting
|
||||
pre-commit run eslint # Frontend linting
|
||||
```
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
- **Documentation**: Update docs/ for any user-facing changes
|
||||
- **Breaking Changes**: Add to UPDATING.md
|
||||
- **Docstrings**: Required for new functions/classes
|
||||
- **Follow existing patterns**: Mimic code style, use existing libraries and utilities
|
||||
- **Type Safety**: This codebase is actively modernizing toward full TypeScript and type safety
|
||||
- **Always run `pre-commit run`** to validate changes before committing
|
||||
|
||||
---
|
||||
|
||||
**Note**: This codebase is actively modernizing toward full TypeScript and type safety. Always run `pre-commit run` to validate changes. Follow the ongoing refactors section to avoid deprecated patterns.
|
||||
20
.devcontainer/Dockerfile
Normal file
20
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,20 @@
|
||||
# Keep this in sync with the base image in the main Dockerfile (ARG PY_VER)
|
||||
FROM python:3.11.13-trixie AS base
|
||||
|
||||
# Install system dependencies that Superset needs
|
||||
# This layer will be cached across Codespace sessions
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libsasl2-dev \
|
||||
libldap2-dev \
|
||||
libpq-dev \
|
||||
tmux \
|
||||
gh \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install uv for fast Python package management
|
||||
# This will also be cached in the image
|
||||
RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \
|
||||
echo 'export PATH="/root/.cargo/bin:$PATH"' >> /etc/bash.bashrc
|
||||
|
||||
# Set the cargo/bin directory in PATH for all users
|
||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||
16
.devcontainer/README.md
Normal file
16
.devcontainer/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Superset Development with GitHub Codespaces
|
||||
|
||||
For complete documentation on using GitHub Codespaces with Apache Superset, please see:
|
||||
|
||||
**[Setting up a Development Environment - GitHub Codespaces](https://superset.apache.org/docs/contributing/development#github-codespaces-cloud-development)**
|
||||
|
||||
## Pre-installed Development Environment
|
||||
|
||||
When you create a new Codespace from this repository, it automatically:
|
||||
|
||||
1. **Creates a Python virtual environment** using `uv venv`
|
||||
2. **Installs all development dependencies** via `uv pip install -r requirements/development.txt`
|
||||
3. **Sets up pre-commit hooks** with `pre-commit install`
|
||||
4. **Activates the virtual environment** automatically in all terminals
|
||||
|
||||
The virtual environment is located at `/workspaces/{repository-name}/.venv` and is automatically activated through environment variables set in the devcontainer configuration.
|
||||
62
.devcontainer/bashrc-additions
Normal file
62
.devcontainer/bashrc-additions
Normal file
@@ -0,0 +1,62 @@
|
||||
# Superset Codespaces environment setup
|
||||
# This file is appended to ~/.bashrc during Codespace setup
|
||||
|
||||
# Find the workspace directory (handles both 'superset' and 'superset-2' names)
|
||||
WORKSPACE_DIR=$(find /workspaces -maxdepth 1 -name "superset*" -type d | head -1)
|
||||
|
||||
if [ -n "$WORKSPACE_DIR" ]; then
|
||||
# Check if virtual environment exists
|
||||
if [ -d "$WORKSPACE_DIR/.venv" ]; then
|
||||
# Activate the virtual environment
|
||||
source "$WORKSPACE_DIR/.venv/bin/activate"
|
||||
echo "✅ Python virtual environment activated"
|
||||
|
||||
# Verify pre-commit is installed and set up
|
||||
if command -v pre-commit &> /dev/null; then
|
||||
echo "✅ pre-commit is available ($(pre-commit --version))"
|
||||
# Install git hooks if not already installed
|
||||
if [ -d "$WORKSPACE_DIR/.git" ] && [ ! -f "$WORKSPACE_DIR/.git/hooks/pre-commit" ]; then
|
||||
echo "🪝 Installing pre-commit hooks..."
|
||||
cd "$WORKSPACE_DIR" && pre-commit install
|
||||
fi
|
||||
else
|
||||
echo "⚠️ pre-commit not found. Run: pip install pre-commit"
|
||||
fi
|
||||
else
|
||||
echo "⚠️ Python virtual environment not found at $WORKSPACE_DIR/.venv"
|
||||
echo " Run: cd $WORKSPACE_DIR && .devcontainer/setup-dev.sh"
|
||||
fi
|
||||
|
||||
# Always cd to the workspace directory for convenience
|
||||
cd "$WORKSPACE_DIR"
|
||||
fi
|
||||
|
||||
# Add helpful aliases for Superset development
|
||||
alias start-superset="$WORKSPACE_DIR/.devcontainer/start-superset.sh"
|
||||
alias setup-dev="$WORKSPACE_DIR/.devcontainer/setup-dev.sh"
|
||||
|
||||
# Show helpful message on login
|
||||
echo ""
|
||||
echo "🚀 Superset Codespaces Environment"
|
||||
echo "=================================="
|
||||
|
||||
# Check if Superset is running
|
||||
if docker ps 2>/dev/null | grep -q "superset"; then
|
||||
echo "✅ Superset is running!"
|
||||
echo " - Check the 'Ports' tab for your live Superset URL"
|
||||
echo " - Initial startup takes 10-20 minutes"
|
||||
echo " - Login: admin/admin"
|
||||
else
|
||||
echo "⚠️ Superset is not running. Use: start-superset"
|
||||
# Check if there's a startup log
|
||||
if [ -f "/tmp/superset-startup.log" ]; then
|
||||
echo " 📋 Startup log found: cat /tmp/superset-startup.log"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Quick commands:"
|
||||
echo " start-superset - Start Superset with Docker Compose"
|
||||
echo " setup-dev - Set up Python environment (if not already done)"
|
||||
echo " pre-commit run - Run pre-commit checks on staged files"
|
||||
echo ""
|
||||
20
.devcontainer/build-and-push-image.sh
Executable file
20
.devcontainer/build-and-push-image.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
# Script to build and push the devcontainer image to GitHub Container Registry
|
||||
# This allows caching the image between Codespace sessions
|
||||
|
||||
# You'll need to run this with appropriate GitHub permissions
|
||||
# gh auth login --scopes write:packages
|
||||
|
||||
REGISTRY="ghcr.io"
|
||||
OWNER="apache"
|
||||
REPO="superset"
|
||||
TAG="devcontainer-base"
|
||||
|
||||
echo "Building devcontainer image..."
|
||||
docker build -t $REGISTRY/$OWNER/$REPO:$TAG .devcontainer/
|
||||
|
||||
echo "Pushing to GitHub Container Registry..."
|
||||
docker push $REGISTRY/$OWNER/$REPO:$TAG
|
||||
|
||||
echo "Done! Update .devcontainer/devcontainer.json to use:"
|
||||
echo " \"image\": \"$REGISTRY/$OWNER/$REPO:$TAG\""
|
||||
66
.devcontainer/devcontainer.json
Normal file
66
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"name": "Apache Superset Development",
|
||||
// Option 1: Use pre-built image directly
|
||||
// "image": "ghcr.io/apache/superset:devcontainer-base",
|
||||
|
||||
// Option 2: Build from Dockerfile with cache (current approach)
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
// Cache from the Apache registry image
|
||||
"cacheFrom": ["ghcr.io/apache/superset:devcontainer-base"]
|
||||
},
|
||||
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/docker-in-docker:2": {
|
||||
"moby": true,
|
||||
"dockerDashComposeVersion": "v2"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "20"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/git:1": {},
|
||||
"ghcr.io/devcontainers/features/common-utils:2": {
|
||||
"configureZshAsDefaultShell": true
|
||||
},
|
||||
"ghcr.io/devcontainers/features/sshd:1": {
|
||||
"version": "latest"
|
||||
}
|
||||
},
|
||||
|
||||
// Forward ports for development
|
||||
"forwardPorts": [9001],
|
||||
"portsAttributes": {
|
||||
"9001": {
|
||||
"label": "Superset (via Webpack Dev Server)",
|
||||
"onAutoForward": "notify",
|
||||
"visibility": "public"
|
||||
}
|
||||
},
|
||||
|
||||
// Run commands after container is created
|
||||
"postCreateCommand": "bash .devcontainer/setup-dev.sh || echo '⚠️ Setup had issues - run .devcontainer/setup-dev.sh manually'",
|
||||
|
||||
// Auto-start Superset after ensuring Docker is ready
|
||||
// Run in foreground to see any errors, but don't block on failures
|
||||
"postStartCommand": "bash -c 'echo \"Waiting 30s for services to initialize...\"; sleep 30; .devcontainer/start-superset.sh || echo \"⚠️ Auto-start failed - run start-superset manually\"'",
|
||||
|
||||
// Set environment variables
|
||||
"remoteEnv": {
|
||||
// Removed automatic venv activation to prevent startup issues
|
||||
// The setup script will handle this
|
||||
},
|
||||
|
||||
// VS Code customizations
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"charliermarsh.ruff",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
78
.devcontainer/setup-dev.sh
Executable file
78
.devcontainer/setup-dev.sh
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
# Setup script for Superset Codespaces development environment
|
||||
|
||||
echo "🔧 Setting up Superset development environment..."
|
||||
|
||||
# System dependencies and uv are now pre-installed in the Docker image
|
||||
# This speeds up Codespace creation significantly!
|
||||
|
||||
# Create virtual environment using uv
|
||||
echo "🐍 Creating Python virtual environment..."
|
||||
if ! uv venv; then
|
||||
echo "❌ Failed to create virtual environment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install Python dependencies
|
||||
echo "📦 Installing Python dependencies..."
|
||||
if ! uv pip install -r requirements/development.txt; then
|
||||
echo "❌ Failed to install Python dependencies"
|
||||
echo "💡 You may need to run this manually after the Codespace starts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install pre-commit hooks
|
||||
echo "🪝 Installing pre-commit hooks..."
|
||||
if source .venv/bin/activate && pre-commit install; then
|
||||
echo "✅ Pre-commit hooks installed"
|
||||
else
|
||||
echo "⚠️ Pre-commit hooks installation failed (non-critical)"
|
||||
fi
|
||||
|
||||
# Install Claude Code CLI via npm
|
||||
echo "🤖 Installing Claude Code..."
|
||||
if npm install -g @anthropic-ai/claude-code; then
|
||||
echo "✅ Claude Code installed"
|
||||
else
|
||||
echo "⚠️ Claude Code installation failed (non-critical)"
|
||||
fi
|
||||
|
||||
# Make the start script executable
|
||||
chmod +x .devcontainer/start-superset.sh
|
||||
|
||||
# Add bashrc additions for automatic venv activation
|
||||
echo "🔧 Setting up automatic environment activation..."
|
||||
if [ -f ~/.bashrc ]; then
|
||||
# Check if we've already added our additions
|
||||
if ! grep -q "Superset Codespaces environment setup" ~/.bashrc; then
|
||||
echo "" >> ~/.bashrc
|
||||
cat .devcontainer/bashrc-additions >> ~/.bashrc
|
||||
echo "✅ Added automatic venv activation to ~/.bashrc"
|
||||
else
|
||||
echo "✅ Bashrc additions already present"
|
||||
fi
|
||||
else
|
||||
# Create bashrc if it doesn't exist
|
||||
cat .devcontainer/bashrc-additions > ~/.bashrc
|
||||
echo "✅ Created ~/.bashrc with automatic venv activation"
|
||||
fi
|
||||
|
||||
# Also add to zshrc since that's the default shell
|
||||
if [ -f ~/.zshrc ] || [ -n "$ZSH_VERSION" ]; then
|
||||
if ! grep -q "Superset Codespaces environment setup" ~/.zshrc; then
|
||||
echo "" >> ~/.zshrc
|
||||
cat .devcontainer/bashrc-additions >> ~/.zshrc
|
||||
echo "✅ Added automatic venv activation to ~/.zshrc"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "✅ Development environment setup complete!"
|
||||
echo ""
|
||||
echo "📝 The virtual environment will be automatically activated in new terminals"
|
||||
echo ""
|
||||
echo "🔄 To activate in this terminal, run:"
|
||||
echo " source ~/.bashrc"
|
||||
echo ""
|
||||
echo "🚀 To start Superset:"
|
||||
echo " start-superset"
|
||||
echo ""
|
||||
108
.devcontainer/start-superset.sh
Executable file
108
.devcontainer/start-superset.sh
Executable file
@@ -0,0 +1,108 @@
|
||||
#!/bin/bash
|
||||
# Startup script for Superset in Codespaces
|
||||
|
||||
# Log to a file for debugging
|
||||
LOG_FILE="/tmp/superset-startup.log"
|
||||
echo "[$(date)] Starting Superset startup script" >> "$LOG_FILE"
|
||||
echo "[$(date)] User: $(whoami), PWD: $(pwd)" >> "$LOG_FILE"
|
||||
|
||||
echo "🚀 Starting Superset in Codespaces..."
|
||||
echo "🌐 Frontend will be available at port 9001"
|
||||
|
||||
# Find the workspace directory (Codespaces clones as 'superset', not 'superset-2')
|
||||
WORKSPACE_DIR=$(find /workspaces -maxdepth 1 -name "superset*" -type d | head -1)
|
||||
if [ -n "$WORKSPACE_DIR" ]; then
|
||||
cd "$WORKSPACE_DIR"
|
||||
echo "📁 Working in: $WORKSPACE_DIR"
|
||||
else
|
||||
echo "📁 Using current directory: $(pwd)"
|
||||
fi
|
||||
|
||||
# Wait for Docker to be available
|
||||
echo "⏳ Waiting for Docker to start..."
|
||||
echo "[$(date)] Waiting for Docker..." >> "$LOG_FILE"
|
||||
max_attempts=30
|
||||
attempt=0
|
||||
while ! docker info > /dev/null 2>&1; do
|
||||
if [ $attempt -eq $max_attempts ]; then
|
||||
echo "❌ Docker failed to start after $max_attempts attempts"
|
||||
echo "[$(date)] Docker failed to start after $max_attempts attempts" >> "$LOG_FILE"
|
||||
echo "🔄 Please restart the Codespace or run this script manually later"
|
||||
exit 1
|
||||
fi
|
||||
echo " Attempt $((attempt + 1))/$max_attempts..."
|
||||
echo "[$(date)] Docker check attempt $((attempt + 1))/$max_attempts" >> "$LOG_FILE"
|
||||
sleep 2
|
||||
attempt=$((attempt + 1))
|
||||
done
|
||||
echo "✅ Docker is ready!"
|
||||
echo "[$(date)] Docker is ready" >> "$LOG_FILE"
|
||||
|
||||
# Check if Superset containers are already running
|
||||
if docker ps | grep -q "superset"; then
|
||||
echo "✅ Superset containers are already running!"
|
||||
echo ""
|
||||
echo "🌐 To access Superset:"
|
||||
echo " 1. Click the 'Ports' tab at the bottom of VS Code"
|
||||
echo " 2. Find port 9001 and click the globe icon to open"
|
||||
echo " 3. Wait 10-20 minutes for initial startup"
|
||||
echo ""
|
||||
echo "📝 Login credentials: admin/admin"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Clean up any existing containers
|
||||
echo "🧹 Cleaning up existing containers..."
|
||||
docker-compose -f docker-compose-light.yml down
|
||||
|
||||
# Start services
|
||||
echo "🏗️ Starting Superset in background (daemon mode)..."
|
||||
echo ""
|
||||
|
||||
# Start in detached mode
|
||||
docker-compose -f docker-compose-light.yml up -d
|
||||
|
||||
echo ""
|
||||
echo "✅ Docker Compose started successfully!"
|
||||
echo ""
|
||||
echo "📋 Important information:"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "⏱️ Initial startup takes 10-20 minutes"
|
||||
echo "🌐 Check the 'Ports' tab for your Superset URL (port 9001)"
|
||||
echo "👤 Login: admin / admin"
|
||||
echo ""
|
||||
echo "📊 Useful commands:"
|
||||
echo " docker-compose -f docker-compose-light.yml logs -f # Follow logs"
|
||||
echo " docker-compose -f docker-compose-light.yml ps # Check status"
|
||||
echo " docker-compose -f docker-compose-light.yml down # Stop services"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "💤 Keeping terminal open for 60 seconds to test persistence..."
|
||||
sleep 60
|
||||
echo "✅ Test complete - check if this terminal is still visible!"
|
||||
|
||||
# Show final status
|
||||
docker-compose -f docker-compose-light.yml ps
|
||||
EXIT_CODE=$?
|
||||
|
||||
# If it failed, provide helpful instructions
|
||||
if [ $EXIT_CODE -ne 0 ] && [ $EXIT_CODE -ne 130 ]; then # 130 is Ctrl+C
|
||||
echo ""
|
||||
echo "❌ Superset startup failed (exit code: $EXIT_CODE)"
|
||||
echo ""
|
||||
echo "🔄 To restart Superset, run:"
|
||||
echo " .devcontainer/start-superset.sh"
|
||||
echo ""
|
||||
echo "🔧 For troubleshooting:"
|
||||
echo " # View logs:"
|
||||
echo " docker-compose -f docker-compose-light.yml logs"
|
||||
echo ""
|
||||
echo " # Clean restart (removes volumes):"
|
||||
echo " docker-compose -f docker-compose-light.yml down -v"
|
||||
echo " .devcontainer/start-superset.sh"
|
||||
echo ""
|
||||
echo " # Common issues:"
|
||||
echo " - Network timeouts: Just retry, often transient"
|
||||
echo " - Port conflicts: Check 'docker ps'"
|
||||
echo " - Database issues: Try clean restart with -v"
|
||||
fi
|
||||
@@ -34,7 +34,6 @@
|
||||
**/*.sqllite
|
||||
**/*.swp
|
||||
**/.terser-plugin-cache/
|
||||
**/.storybook/
|
||||
**/node_modules/
|
||||
|
||||
tests/
|
||||
@@ -42,6 +41,8 @@ docs/
|
||||
install/
|
||||
superset-frontend/cypress-base/
|
||||
superset-frontend/coverage/
|
||||
superset-frontend/.temp_cache/
|
||||
superset/static/assets/
|
||||
superset-websocket/dist/
|
||||
venv
|
||||
.venv
|
||||
|
||||
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1 +1,4 @@
|
||||
docker/**/*.sh text eol=lf
|
||||
*.svg binary
|
||||
*.ipynb binary
|
||||
*.geojson binary
|
||||
|
||||
26
.github/CODEOWNERS
vendored
26
.github/CODEOWNERS
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
# https://github.com/apache/superset/issues/13351
|
||||
|
||||
/superset/migrations/ @apache/superset-committers
|
||||
/superset/migrations/ @mistercrunch @michael-s-molina @betodealmeida @eschutho @sadpandajoe
|
||||
|
||||
# Notify some committers of changes in the components
|
||||
|
||||
@@ -12,23 +12,31 @@
|
||||
|
||||
# Notify Helm Chart maintainers about changes in it
|
||||
|
||||
/helm/superset/ @craig-rueda @dpgaspar @villebro
|
||||
/helm/superset/ @craig-rueda @dpgaspar @villebro @nytai @michael-s-molina @mistercrunch @rusackas @Antonio-RiveroMartnez
|
||||
|
||||
# Notify E2E test maintainers of changes
|
||||
|
||||
/superset-frontend/cypress-base/ @jinghua-qa @geido @eschutho @rusackas @betodealmeida
|
||||
/superset-frontend/cypress-base/ @sadpandajoe @geido @eschutho @rusackas @betodealmeida @mistercrunch
|
||||
|
||||
# Notify PMC members of changes to GitHub Actions
|
||||
|
||||
/.github/ @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @john-bodley @kgabryje @dpgaspar
|
||||
/.github/ @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar
|
||||
|
||||
# Notify PMC members of changes to required Github Actions
|
||||
# Notify PMC members of changes to required GitHub Actions
|
||||
|
||||
/.asf.yaml @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @john-bodley @kgabryje @dpgaspar
|
||||
/.asf.yaml @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar @Antonio-RiveroMartnez
|
||||
|
||||
# Maps are a finicky contribution process we care about
|
||||
|
||||
# Maps are a finnicky contribution process we care about
|
||||
**/*.geojson @villebro @rusackas
|
||||
/superset-frontend/plugins/legacy-plugin-chart-country-map/ @villebro @rusackas
|
||||
|
||||
# Translations are a finnicky contribution that we care about
|
||||
/superset/translations/ @villebro @rusackas @michael-s-molina
|
||||
# Notify PMC members of changes to extension-related files
|
||||
|
||||
/superset-core/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset-extensions-cli/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset/core/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset/extensions/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset-frontend/src/packages/superset-core/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset-frontend/src/core/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset-frontend/src/extensions/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
|
||||
14
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
14
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -7,6 +7,7 @@ body:
|
||||
value: |
|
||||
Hello Superset Community member! Please keep things tidy by putting your post in the proper place:
|
||||
|
||||
🚨 Reporting a security issue: send an email to security@superset.apache.org. DO NOT USE GITHUB ISSUES TO REPORT SECURITY PROBLEMS.
|
||||
🐛 Reporting a bug: use this form.
|
||||
🙏 Asking a question or getting help: post in the [Superset Slack chat](http://bit.ly/join-superset-slack) or [GitHub Discussions](https://github.com/apache/superset/discussions) under "Q&A / Help".
|
||||
💡 Requesting a new feature: Search [GitHub Discussions](https://github.com/apache/superset/discussions) to see if it exists already. If not, add a new post there under "Ideas".
|
||||
@@ -14,14 +15,9 @@ body:
|
||||
id: bug-description
|
||||
attributes:
|
||||
label: Bug description
|
||||
description: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: repro-steps
|
||||
attributes:
|
||||
label: How to reproduce the bug
|
||||
description: A clear description of what the bug is, including reproduction steps and expected behavior.
|
||||
placeholder: |
|
||||
The bug is that...
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
@@ -45,8 +41,8 @@ body:
|
||||
label: Superset version
|
||||
options:
|
||||
- master / latest-dev
|
||||
- "3.1.1"
|
||||
- "3.0.4"
|
||||
- "5.0.0"
|
||||
- "4.1.3"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
||||
34
.github/actions/change-detector/action.yml
vendored
Normal file
34
.github/actions/change-detector/action.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Change Detector
|
||||
description: Detects file changes for pull request and push events
|
||||
inputs:
|
||||
token:
|
||||
description: GitHub token for authentication
|
||||
required: true
|
||||
outputs:
|
||||
python:
|
||||
description: Whether Python-related files were changed
|
||||
value: ${{ steps.change-detector.outputs.python }}
|
||||
frontend:
|
||||
description: Whether frontend-related files were changed
|
||||
value: ${{ steps.change-detector.outputs.frontend }}
|
||||
docker:
|
||||
description: Whether docker-related files were changed
|
||||
value: ${{ steps.change-detector.outputs.docker }}
|
||||
docs:
|
||||
description: Whether docs-related files were changed
|
||||
value: ${{ steps.change-detector.outputs.docs }}
|
||||
superset-extensions-cli:
|
||||
description: Whether superset-extensions-cli package-related files were changed
|
||||
value: ${{ steps.change-detector.outputs.superset-extensions-cli }}
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Detect file changes
|
||||
id: change-detector
|
||||
run: |
|
||||
python --version
|
||||
python scripts/change_detector.py
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ inputs.token }}
|
||||
GITHUB_OUTPUT: ${{ github.output }}
|
||||
23
.github/actions/change-detector/label-draft-pr.yml
vendored
Normal file
23
.github/actions/change-detector/label-draft-pr.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Label Draft PRs
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- converted_to_draft
|
||||
jobs:
|
||||
label-draft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check if the PR is a draft
|
||||
id: check-draft
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const isDraft = context.payload.pull_request.draft;
|
||||
core.setOutput('isDraft', isDraft);
|
||||
- name: Add `review:draft` Label
|
||||
if: steps.check-draft.outputs.isDraft == 'true'
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: "review:draft"
|
||||
2
.github/actions/chart-releaser-action
vendored
2
.github/actions/chart-releaser-action
vendored
Submodule .github/actions/chart-releaser-action updated: 120944e663...a917fd15b2
43
.github/actions/setup-backend/action.yml
vendored
43
.github/actions/setup-backend/action.yml
vendored
@@ -2,9 +2,9 @@ name: 'Setup Python Environment'
|
||||
description: 'Set up Python and install dependencies with optional configurations.'
|
||||
inputs:
|
||||
python-version:
|
||||
description: 'Python version to set up.'
|
||||
description: 'Python version to set up. Accepts a version number, "current", or "next".'
|
||||
required: true
|
||||
default: '3.9'
|
||||
default: 'current'
|
||||
cache:
|
||||
description: 'Cache dependencies. Options: pip'
|
||||
required: false
|
||||
@@ -13,21 +13,46 @@ inputs:
|
||||
description: 'Type of requirements to install. Options: base, development, default'
|
||||
required: false
|
||||
default: 'dev'
|
||||
install-superset:
|
||||
description: 'Whether to install Superset itself. If false, only python is installed'
|
||||
required: false
|
||||
default: 'true'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Set up Python ${{ inputs.python-version }}
|
||||
- name: Interpret Python Version
|
||||
id: set-python-version
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ inputs.python-version }}" = "current" ]; then
|
||||
echo "PYTHON_VERSION=3.11" >> $GITHUB_ENV
|
||||
elif [ "${{ inputs.python-version }}" = "next" ]; then
|
||||
# currently disabled in GHA matrixes because of library compatibility issues
|
||||
echo "PYTHON_VERSION=3.12" >> $GITHUB_ENV
|
||||
elif [ "${{ inputs.python-version }}" = "previous" ]; then
|
||||
echo "PYTHON_VERSION=3.10" >> $GITHUB_ENV
|
||||
else
|
||||
echo "PYTHON_VERSION=${{ inputs.python-version }}" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
cache: ${{ inputs.cache }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade pip setuptools wheel
|
||||
if [ "${{ inputs.requirements-type }}" = "dev" ]; then
|
||||
pip install -r requirements/development.txt
|
||||
elif [ "${{ inputs.requirements-type }}" = "base" ]; then
|
||||
pip install -r requirements/base.txt
|
||||
if [ "${{ inputs.install-superset }}" = "true" ]; then
|
||||
sudo apt-get update && sudo apt-get -y install libldap2-dev libsasl2-dev
|
||||
|
||||
pip install --upgrade pip setuptools wheel uv
|
||||
|
||||
if [ "${{ inputs.requirements-type }}" = "dev" ]; then
|
||||
uv pip install --system -r requirements/development.txt
|
||||
elif [ "${{ inputs.requirements-type }}" = "base" ]; then
|
||||
uv pip install --system -r requirements/base.txt
|
||||
fi
|
||||
|
||||
uv pip install --system -e .
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
69
.github/actions/setup-docker/action.yml
vendored
Normal file
69
.github/actions/setup-docker/action.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: "Setup Docker Environment"
|
||||
description: "Reusable steps for setting up QEMU, Docker Buildx, DockerHub login, Supersetbot, and optionally Docker Compose"
|
||||
inputs:
|
||||
build:
|
||||
description: "Used for building?"
|
||||
required: false
|
||||
default: "false"
|
||||
dockerhub-user:
|
||||
description: "DockerHub username"
|
||||
required: false
|
||||
dockerhub-token:
|
||||
description: "DockerHub token"
|
||||
required: false
|
||||
install-docker-compose:
|
||||
description: "Flag to install Docker Compose"
|
||||
required: false
|
||||
default: "true"
|
||||
login-to-dockerhub:
|
||||
description: "Whether you want to log into dockerhub"
|
||||
required: false
|
||||
default: "true"
|
||||
outputs: {}
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
|
||||
- name: Set up QEMU
|
||||
if: ${{ inputs.build == 'true' }}
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
if: ${{ inputs.build == 'true' }}
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Try to login to DockerHub
|
||||
if: ${{ inputs.login-to-dockerhub == 'true' }}
|
||||
continue-on-error: true
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ inputs.dockerhub-user }}
|
||||
password: ${{ inputs.dockerhub-token }}
|
||||
|
||||
- name: Install Docker Compose
|
||||
if: ${{ inputs.install-docker-compose == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates curl
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
|
||||
# Download and save the Docker GPG key in the correct format
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# Ensure the key file is readable
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# Add the Docker repository using the correct key
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
# Update package lists and install Docker Compose plugin
|
||||
sudo apt update
|
||||
sudo apt install -y docker-compose-plugin
|
||||
|
||||
- name: Docker Version Info
|
||||
shell: bash
|
||||
run: docker info
|
||||
40
.github/actions/setup-supersetbot/action.yml
vendored
Normal file
40
.github/actions/setup-supersetbot/action.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: 'Setup supersetbot'
|
||||
description: 'Sets up supersetbot npm lib from the repo or npm'
|
||||
inputs:
|
||||
from-npm:
|
||||
description: 'Install from npm instead of local setup'
|
||||
required: false
|
||||
default: 'true' # Defaults to using the local setup
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
|
||||
- name: Setup Node Env
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install supersetbot from npm
|
||||
if: ${{ inputs.from-npm == 'true' }}
|
||||
shell: bash
|
||||
run: npm install -g supersetbot
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
if: ${{ inputs.from-npm == 'false' }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: apache-superset/supersetbot
|
||||
path: supersetbot
|
||||
|
||||
- name: Setup supersetbot from repo
|
||||
if: ${{ inputs.from-npm == 'false' }}
|
||||
shell: bash
|
||||
working-directory: supersetbot
|
||||
run: |
|
||||
# simple trick to install globally with dependencies
|
||||
npm pack
|
||||
npm install -g ./supersetbot*.tgz
|
||||
|
||||
- name: echo supersetbot version
|
||||
shell: bash
|
||||
run: supersetbot version
|
||||
1
.github/copilot-instructions.md
vendored
Symbolic link
1
.github/copilot-instructions.md
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../LLMS.md
|
||||
27
.github/dependabot.yml
vendored
27
.github/dependabot.yml
vendored
@@ -1,4 +1,5 @@
|
||||
version: 2
|
||||
enable-beta-ecosystems: true
|
||||
updates:
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
@@ -8,8 +9,13 @@ updates:
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
ignore:
|
||||
# not until node >= 18.12.0
|
||||
- dependency-name: "css-minimizer-webpack-plugin"
|
||||
# not until React >= 18.0.0
|
||||
- dependency-name: "storybook"
|
||||
- dependency-name: "@storybook*"
|
||||
# JSDOM v30 doesn't play well with Jest v30
|
||||
# Source: https://jestjs.io/blog#known-issues
|
||||
# GH thread: https://github.com/jsdom/jsdom/issues/3492
|
||||
- dependency-name: "jest-environment-jsdom"
|
||||
directory: "/superset-frontend/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
@@ -19,14 +25,17 @@ updates:
|
||||
open-pull-requests-limit: 30
|
||||
versioning-strategy: increase
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/requirements/"
|
||||
|
||||
# NOTE: `uv` support is in beta, more details here:
|
||||
# https://github.com/dependabot/dependabot-core/pull/10040#issuecomment-2696978430
|
||||
- package-ecosystem: "uv"
|
||||
directory: "requirements/"
|
||||
open-pull-requests-limit: 10
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "weekly"
|
||||
labels:
|
||||
- pip
|
||||
- uv
|
||||
- dependabot
|
||||
open-pull-requests-limit: 30
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: ".github/actions"
|
||||
@@ -325,6 +334,10 @@ updates:
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/packages/superset-ui-core/"
|
||||
ignore:
|
||||
# not until React >= 18.0.0
|
||||
- dependency-name: "react-markdown"
|
||||
- dependency-name: "remark-gfm"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
labels:
|
||||
|
||||
10
.github/labeler.yml
vendored
10
.github/labeler.yml
vendored
@@ -72,6 +72,11 @@
|
||||
- any-glob-to-any-file:
|
||||
- 'superset/translations/zh/**'
|
||||
|
||||
"i18n:traditional-chinese":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'superset/translations/zh_TW/**'
|
||||
|
||||
"i18n:dutch":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
@@ -122,6 +127,11 @@
|
||||
- any-glob-to-any-file:
|
||||
- 'superset/translations/es/**'
|
||||
|
||||
"i18n:persian":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'superset/translations/fa/**'
|
||||
|
||||
############################################
|
||||
# Sub-projects and monorepo packages
|
||||
############################################
|
||||
|
||||
22
.github/supersetbot/.eslintrc.json
vendored
22
.github/supersetbot/.eslintrc.json
vendored
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"extends": "airbnb-base",
|
||||
"rules": {
|
||||
"import/extensions": 0,
|
||||
"import/prefer-default-export": 0,
|
||||
"func-names": 0,
|
||||
"no-console": 0,
|
||||
"class-methods-use-this": 0
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module",
|
||||
"requireConfigFile": false
|
||||
},
|
||||
"env": {
|
||||
"jest": true
|
||||
}
|
||||
}
|
||||
37
.github/supersetbot/README.md
vendored
37
.github/supersetbot/README.md
vendored
@@ -1,37 +0,0 @@
|
||||
# supersetbot
|
||||
|
||||
supersetbot is a utility bot that can be used to help around GitHub, CI and beyond.
|
||||
|
||||
The bot can be used as a local CLI OR, for a subset of fitted use cases, can be invoked directly
|
||||
from GitHub comments.
|
||||
|
||||
Because it's its own npm app, it can be tested/deployed/used in isolation from the rest of
|
||||
Superset, and take on some of the complexity from GitHub actions and onto a nifty
|
||||
utility that can be used in different contexts.
|
||||
|
||||
## Features
|
||||
|
||||
```bash
|
||||
$ use nvm 20
|
||||
$ npm i -g supersetbot
|
||||
$ supersetbot
|
||||
Usage: supersetbot [options] [command]
|
||||
|
||||
Options:
|
||||
-v, --verbose Output extra debugging information
|
||||
-r, --repo <repo> The GitHub repo to use (ie: "apache/superset")
|
||||
-d, --dry-run Run the command in dry-run mode
|
||||
-a, --actor <actor> The actor
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
label [options] <label> Add a label to an issue or PR
|
||||
unlabel [options] <label> Remove a label from an issue or PR
|
||||
release-label-pr [options] <prId> Figure out first release for PR and label it
|
||||
version Prints supersetbot's version number
|
||||
release-label-prs [options] Given a set of PRs, auto-release label them
|
||||
release-label [options] <release> Figure out first release for PR and label it
|
||||
orglabel [options] Add an org label based on the author
|
||||
docker [options] Generates/run docker build commands use in CI
|
||||
help [command] display help for command
|
||||
```
|
||||
8
.github/supersetbot/jest.config.js
vendored
8
.github/supersetbot/jest.config.js
vendored
@@ -1,8 +0,0 @@
|
||||
export default {
|
||||
transform: {
|
||||
},
|
||||
testEnvironment: 'node',
|
||||
moduleNameMapper: {
|
||||
'^(\\.{1,2}/.*)\\.js$': '$1',
|
||||
},
|
||||
};
|
||||
11020
.github/supersetbot/package-lock.json
generated
vendored
11020
.github/supersetbot/package-lock.json
generated
vendored
File diff suppressed because it is too large
Load Diff
36
.github/supersetbot/package.json
vendored
36
.github/supersetbot/package.json
vendored
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "supersetbot",
|
||||
"version": "0.4.1",
|
||||
"description": "A bot for the Superset GitHub repo",
|
||||
"type": "module",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
||||
"eslint": "eslint",
|
||||
"supersetbot": "supersetbot"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@octokit/plugin-throttling": "^8.1.3",
|
||||
"@octokit/rest": "^20.0.2",
|
||||
"commander": "^11.0.0",
|
||||
"semver": "^7.6.0",
|
||||
"simple-git": "^3.22.0",
|
||||
"string-argv": "^0.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/globals": "^29.7.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"jest": "^29.7.0"
|
||||
},
|
||||
"bin": {
|
||||
"supersetbot": "./src/supersetbot"
|
||||
}
|
||||
}
|
||||
175
.github/supersetbot/src/cli.js
vendored
175
.github/supersetbot/src/cli.js
vendored
@@ -1,175 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
import * as docker from './docker.js';
|
||||
import * as utils from './utils.js';
|
||||
import Github from './github.js';
|
||||
import Git from './git.js';
|
||||
|
||||
export default function getCLI(context) {
|
||||
const program = new Command();
|
||||
|
||||
// Some reusable options
|
||||
const issueOption = new Option('-i, --issue <issue>', 'The issue number', process.env.GITHUB_ISSUE_NUMBER);
|
||||
const excludeCherriesOption = new Option('-c, --exclude-cherries', 'Generate cherry labels point to each release where the PR has been cherried');
|
||||
|
||||
// Setting up top-level CLI options
|
||||
program
|
||||
.option('-v, --verbose', 'Output extra debugging information')
|
||||
.option('-r, --repo <repo>', 'The GitHub repo to use (ie: "apache/superset")', process.env.GITHUB_REPOSITORY)
|
||||
.option('-d, --dry-run', 'Run the command in dry-run mode')
|
||||
.option('-a, --actor <actor>', 'The actor', process.env.GITHUB_ACTOR);
|
||||
|
||||
program.command('label <label>')
|
||||
.description('Add a label to an issue or PR')
|
||||
.addOption(issueOption)
|
||||
.action(async function (label) {
|
||||
const opts = context.processOptions(this, ['issue', 'repo']);
|
||||
const github = new Github({ context, issue: opts.issue });
|
||||
await github.label(opts.issue, label, context, opts.actor, opts.verbose, opts.dryRun);
|
||||
});
|
||||
|
||||
program.command('unlabel <label>')
|
||||
.description('Remove a label from an issue or PR')
|
||||
.addOption(issueOption)
|
||||
.action(async function (label) {
|
||||
const opts = context.processOptions(this, ['issue', 'repo']);
|
||||
const github = new Github({ context, issueNumber: opts.issue });
|
||||
await github.unlabel(opts.issue, label, context, opts.actor, opts.verbose, opts.dryRun);
|
||||
});
|
||||
|
||||
program.command('release-label-pr <prId>')
|
||||
.description('Figure out first release for PR and label it')
|
||||
.addOption(excludeCherriesOption)
|
||||
.action(async function (prId) {
|
||||
const opts = context.processOptions(this, ['repo']);
|
||||
const git = new Git(context);
|
||||
await git.loadReleases();
|
||||
|
||||
let wrapped = context.commandWrapper({
|
||||
func: git.getReleaseLabels,
|
||||
verbose: opts.verbose,
|
||||
});
|
||||
const labels = await wrapped(parseInt(prId, 10), opts.verbose, opts.excludeCherries);
|
||||
const github = new Github({ context, issueNumber: opts.issue });
|
||||
wrapped = context.commandWrapper({
|
||||
func: github.syncLabels,
|
||||
verbose: opts.verbose,
|
||||
});
|
||||
await wrapped({labels, prId, actor: opts.actor, verbose: opts.verbose, dryRun: opts.dryRun});
|
||||
});
|
||||
|
||||
program.command('version')
|
||||
.description("Prints supersetbot's version number")
|
||||
.action(async () => {
|
||||
const version = await utils.currentPackageVersion();
|
||||
context.log(version);
|
||||
});
|
||||
|
||||
if (context.source === 'CLI') {
|
||||
program.command('release-label-prs')
|
||||
.description('Given a set of PRs, auto-release label them')
|
||||
.option('-s, --search <search>', 'extra search string to append using the GitHub mini-language')
|
||||
.option('-p, --pages <pages>', 'the number of pages (100 per page) to fetch and process', 10)
|
||||
.action(async function () {
|
||||
const opts = context.processOptions(this, ['repo']);
|
||||
|
||||
const github = new Github({ context, issueNumber: opts.issue });
|
||||
const prs = await github.searchMergedPRs({
|
||||
query: opts.search,
|
||||
onlyUnlabeled: true,
|
||||
verbose: opts.verbose,
|
||||
pages: opts.pages,
|
||||
});
|
||||
const prIdLabelMap = new Map(prs.map((pr) => [pr.number, pr.labels]));
|
||||
const git = new Git(context);
|
||||
await git.loadReleases();
|
||||
|
||||
const prsPromises = prs.map(async (pr) => {
|
||||
const labels = await git.getReleaseLabels(pr.number, opts.verbose);
|
||||
return { prId: pr.number, labels };
|
||||
});
|
||||
const prsTargetLabel = await Promise.all(prsPromises);
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const { prId, labels } of prsTargetLabel) {
|
||||
// Running sequentially to avoid rate limiting
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await github.syncLabels({
|
||||
labels,
|
||||
existingLabels: prIdLabelMap.get(prId).map(l => l.name),
|
||||
prId,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
program.command('release-label <release>')
|
||||
.description('Figure out first release for PR and label it')
|
||||
.addOption(excludeCherriesOption)
|
||||
.action(async function (release) {
|
||||
const opts = context.processOptions(this, ['repo']);
|
||||
const git = new Git(context);
|
||||
await git.loadReleases();
|
||||
const prs = await git.getPRsToSync(release, opts.verbose, opts.excludeCherries);
|
||||
|
||||
const github = new Github({ context });
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const { prId, labels } of prs) {
|
||||
// Running sequentially to avoid rate limiting
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await github.syncLabels({
|
||||
prId,
|
||||
labels,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
program.command('orglabel')
|
||||
.description('Add an org label based on the author')
|
||||
.addOption(issueOption)
|
||||
.action(async function () {
|
||||
const opts = context.processOptions(this, ['issue', 'repo']);
|
||||
const github = new Github({ context, issueNumber: opts.issue });
|
||||
await github.assignOrgLabel(opts.issue, opts.verbose, opts.dryRun);
|
||||
});
|
||||
|
||||
|
||||
program.command('docker')
|
||||
.description('Generates/run docker build commands use in CI')
|
||||
.option('-t, --preset', 'Build preset', /^(lean|dev|dockerize|websocket|py310|ci)$/i, 'lean')
|
||||
.option('-c, --context <context>', 'Build context', /^(push|pull_request|release)$/i, 'local')
|
||||
.option('-r, --context-ref <ref>', 'Reference to the PR, release, or branch')
|
||||
.option('-p, --platform <platform...>', 'Platforms (multiple values allowed)')
|
||||
.option('-f, --force-latest', 'Force the "latest" tag on the release')
|
||||
.option('-v, --verbose', 'Print more info')
|
||||
.action(function (preset) {
|
||||
const opts = context.processOptions(this);
|
||||
opts.platform = opts.platform || ['linux/arm64'];
|
||||
const cmd = docker.getDockerCommand({ preset, ...opts });
|
||||
context.log(cmd);
|
||||
if (!opts.dryRun) {
|
||||
utils.runShellCommand(cmd, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
152
.github/supersetbot/src/context.js
vendored
152
.github/supersetbot/src/context.js
vendored
@@ -1,152 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { parseArgsStringToArgv } from 'string-argv';
|
||||
|
||||
class Context {
|
||||
constructor(source) {
|
||||
this.hasErrors = false;
|
||||
this.source = source;
|
||||
this.options = {};
|
||||
this.errorLogs = [];
|
||||
this.logs = [];
|
||||
this.repo = null;
|
||||
this.optToEnvMap = {
|
||||
issue: 'GITHUB_ISSUE_NUMBER',
|
||||
repo: 'GITHUB_REPOSITORY',
|
||||
};
|
||||
}
|
||||
|
||||
requireOption(optionName, options) {
|
||||
const optionValue = options[optionName];
|
||||
if (optionValue === undefined || optionValue === null) {
|
||||
this.logError(`option [${optionName}] is required`);
|
||||
// this.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
parseArgs(s) {
|
||||
return parseArgsStringToArgv(s);
|
||||
}
|
||||
|
||||
requireOptions(optionNames, options) {
|
||||
optionNames.forEach((optionName) => {
|
||||
this.requireOption(optionName, options);
|
||||
});
|
||||
}
|
||||
|
||||
processOptions(command, requiredOptions = []) {
|
||||
const raw = command.parent?.rawArgs;
|
||||
this.command = '???';
|
||||
if (raw) {
|
||||
this.command = raw.map((s) => (s.includes(' ') ? `"${s}"` : s)).join(' ').replace('node ', '');
|
||||
}
|
||||
this.options = { ...command.opts(), ...command.parent.opts() };
|
||||
|
||||
// Runtime defaults for unit tests since commanders can't receive callables as default
|
||||
Object.entries(this.optToEnvMap).forEach(([k, v]) => {
|
||||
if (!this.options[k]) {
|
||||
this.options[k] = process.env[v];
|
||||
}
|
||||
});
|
||||
this.requireOptions(requiredOptions, this.options);
|
||||
this.issueNumber = this.options.issue;
|
||||
|
||||
if (this.source === 'GHA') {
|
||||
this.options.actor = process.env.GITHUB_ACTOR || 'UNKNOWN';
|
||||
this.options.repo = process.env.GITHUB_REPOSITORY;
|
||||
}
|
||||
this.repo = this.options.repo;
|
||||
|
||||
return this.options;
|
||||
}
|
||||
|
||||
log(msg) {
|
||||
console.log(msg);
|
||||
this.logs = [...this.logs, msg];
|
||||
}
|
||||
|
||||
logSuccess(msg) {
|
||||
const augMsg = `🟢 SUCCESS: ${msg}`;
|
||||
console.log(augMsg);
|
||||
this.logs.push(augMsg);
|
||||
}
|
||||
|
||||
logError(msg) {
|
||||
this.hasErrors = true;
|
||||
const augMsg = `🔴 ERROR: ${msg}`;
|
||||
console.error(augMsg);
|
||||
this.errorLogs.push(augMsg);
|
||||
}
|
||||
|
||||
exit(code = 0) {
|
||||
this.onDone();
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
commandWrapper({
|
||||
func, successMsg, errorMsg = null, verbose = false, dryRun = false,
|
||||
}) {
|
||||
return async (...args) => {
|
||||
let resp;
|
||||
let hasError = false;
|
||||
|
||||
try {
|
||||
if (!dryRun) {
|
||||
resp = await func(...args);
|
||||
}
|
||||
if (verbose && resp) {
|
||||
console.log(resp);
|
||||
}
|
||||
} catch (error) {
|
||||
hasError = true;
|
||||
if (errorMsg) {
|
||||
this.logError(errorMsg);
|
||||
} else {
|
||||
this.logError(error);
|
||||
}
|
||||
throw (error);
|
||||
}
|
||||
if (successMsg && !hasError) {
|
||||
this.logSuccess(successMsg);
|
||||
}
|
||||
return resp;
|
||||
};
|
||||
}
|
||||
|
||||
doneComment() {
|
||||
const msgs = [...this.logs, ...this.errorLogs];
|
||||
let comment = '';
|
||||
comment += `> \`${this.command}\`\n`;
|
||||
comment += '```\n';
|
||||
comment += msgs.join('\n');
|
||||
comment += '\n```';
|
||||
return comment;
|
||||
}
|
||||
|
||||
async onDone() {
|
||||
let msg;
|
||||
if (this.source === 'GHA') {
|
||||
msg = this.doneComment();
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
export default Context;
|
||||
142
.github/supersetbot/src/docker.js
vendored
142
.github/supersetbot/src/docker.js
vendored
@@ -1,142 +0,0 @@
|
||||
import { spawnSync } from 'child_process';
|
||||
|
||||
const REPO = 'apache/superset';
|
||||
const CACHE_REPO = `${REPO}-cache`;
|
||||
const BASE_PY_IMAGE = '3.9-slim-bookworm';
|
||||
|
||||
export function runCmd(command, raiseOnFailure = true) {
|
||||
const { stdout, stderr } = spawnSync(command, { shell: true, encoding: 'utf-8', env: process.env });
|
||||
|
||||
if (stderr && raiseOnFailure) {
|
||||
throw new Error(stderr);
|
||||
}
|
||||
return stdout;
|
||||
}
|
||||
|
||||
function getGitSha() {
|
||||
return runCmd('git rev-parse HEAD').trim();
|
||||
}
|
||||
|
||||
function getBuildContextRef(buildContext) {
|
||||
const event = buildContext || process.env.GITHUB_EVENT_NAME;
|
||||
const githubRef = process.env.GITHUB_REF || '';
|
||||
|
||||
if (event === 'pull_request') {
|
||||
const githubHeadRef = process.env.GITHUB_HEAD_REF || '';
|
||||
return githubHeadRef.replace(/[^a-zA-Z0-9]/g, '-').slice(0, 40);
|
||||
} if (event === 'release') {
|
||||
return githubRef.replace('refs/tags/', '').slice(0, 40);
|
||||
} if (event === 'push') {
|
||||
return githubRef.replace('refs/heads/', '').replace(/[^a-zA-Z0-9]/g, '-').slice(0, 40);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
export function isLatestRelease(release) {
|
||||
const output = runCmd(`../../scripts/tag_latest_release.sh ${release} --dry-run`, false) || '';
|
||||
return output.includes('SKIP_TAG::false');
|
||||
}
|
||||
|
||||
function makeDockerTag(parts) {
|
||||
return `${REPO}:${parts.filter((part) => part).join('-')}`;
|
||||
}
|
||||
|
||||
export function getDockerTags({
|
||||
preset, platforms, sha, buildContext, buildContextRef, forceLatest = false,
|
||||
}) {
|
||||
const tags = new Set();
|
||||
const tagChunks = [];
|
||||
|
||||
const isLatest = isLatestRelease(buildContextRef);
|
||||
|
||||
if (preset !== 'lean') {
|
||||
tagChunks.push(preset);
|
||||
}
|
||||
|
||||
if (platforms.length === 1) {
|
||||
const platform = platforms[0];
|
||||
const shortBuildPlatform = platform.replace('linux/', '').replace('64', '');
|
||||
if (shortBuildPlatform !== 'amd') {
|
||||
tagChunks.push(shortBuildPlatform);
|
||||
}
|
||||
}
|
||||
|
||||
tags.add(makeDockerTag([sha, ...tagChunks]));
|
||||
tags.add(makeDockerTag([sha.slice(0, 7), ...tagChunks]));
|
||||
|
||||
if (buildContext === 'release') {
|
||||
tags.add(makeDockerTag([buildContextRef, ...tagChunks]));
|
||||
if (isLatest || forceLatest) {
|
||||
tags.add(makeDockerTag(['latest', ...tagChunks]));
|
||||
}
|
||||
} else if (buildContext === 'push' && buildContextRef === 'master') {
|
||||
tags.add(makeDockerTag(['master', ...tagChunks]));
|
||||
} else if (buildContext === 'pull_request') {
|
||||
tags.add(makeDockerTag([`pr-${buildContextRef}`, ...tagChunks]));
|
||||
}
|
||||
|
||||
return [...tags];
|
||||
}
|
||||
|
||||
export function getDockerCommand({
|
||||
preset, platform, buildContext, buildContextRef, forceLatest = false,
|
||||
}) {
|
||||
const platforms = platform;
|
||||
|
||||
let buildTarget = '';
|
||||
let pyVer = BASE_PY_IMAGE;
|
||||
let dockerContext = '.';
|
||||
|
||||
if (preset === 'dev') {
|
||||
buildTarget = 'dev';
|
||||
} else if (preset === 'lean') {
|
||||
buildTarget = 'lean';
|
||||
} else if (preset === 'py310') {
|
||||
buildTarget = 'lean';
|
||||
pyVer = '3.10-slim-bookworm';
|
||||
} else if (preset === 'websocket') {
|
||||
dockerContext = 'superset-websocket';
|
||||
} else if (preset === 'ci') {
|
||||
buildTarget = 'ci';
|
||||
} else if (preset === 'dockerize') {
|
||||
dockerContext = '-f dockerize.Dockerfile .';
|
||||
} else {
|
||||
console.error(`Invalid build preset: ${preset}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let ref = buildContextRef;
|
||||
if (!ref) {
|
||||
ref = getBuildContextRef(buildContext);
|
||||
}
|
||||
const sha = getGitSha();
|
||||
const tags = getDockerTags({
|
||||
preset, platforms, sha, buildContext, buildContextRef: ref, forceLatest,
|
||||
}).map((tag) => `-t ${tag}`).join(' \\\n ');
|
||||
const isAuthenticated = !!(process.env.DOCKERHUB_TOKEN);
|
||||
|
||||
const dockerArgs = isAuthenticated ? '--push' : '--load';
|
||||
const targetArgument = buildTarget ? `--target ${buildTarget}` : '';
|
||||
const cacheRef = `${CACHE_REPO}:${pyVer}`;
|
||||
const platformArg = `--platform ${platforms.join(',')}`;
|
||||
const cacheFromArg = `--cache-from=type=registry,ref=${cacheRef}`;
|
||||
const cacheToArg = isAuthenticated ? `--cache-to=type=registry,mode=max,ref=${cacheRef}` : '';
|
||||
const buildArg = pyVer ? `--build-arg PY_VER=${pyVer}` : '';
|
||||
const actor = process.env.GITHUB_ACTOR;
|
||||
|
||||
return `docker buildx build \\
|
||||
${dockerArgs} \\
|
||||
${tags} \\
|
||||
${cacheFromArg} \\
|
||||
${cacheToArg} \\
|
||||
${targetArgument} \\
|
||||
${buildArg} \\
|
||||
${platformArg} \\
|
||||
--label sha=${sha} \\
|
||||
--label target=${buildTarget} \\
|
||||
--label build_trigger=${ref} \\
|
||||
--label base=${pyVer} \\
|
||||
--label build_actor=${actor} \\
|
||||
${dockerContext}
|
||||
`;
|
||||
}
|
||||
244
.github/supersetbot/src/docker.test.js
vendored
244
.github/supersetbot/src/docker.test.js
vendored
@@ -1,244 +0,0 @@
|
||||
import * as dockerUtils from './docker.js';
|
||||
|
||||
const SHA = '22e7c602b9aa321ec7e0df4bb0033048664dcdf0';
|
||||
const PR_ID = '666';
|
||||
const OLD_REL = '2.1.0';
|
||||
const NEW_REL = '2.1.1';
|
||||
const REPO = 'apache/superset';
|
||||
|
||||
beforeEach(() => {
|
||||
process.env.TEST_ENV = 'true';
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete process.env.TEST_ENV;
|
||||
});
|
||||
|
||||
describe('isLatestRelease', () => {
|
||||
test.each([
|
||||
['2.1.0', false],
|
||||
['2.1.1', true],
|
||||
['1.0.0', false],
|
||||
['3.0.0', true],
|
||||
])('returns %s for release %s', (release, expectedBool) => {
|
||||
expect(dockerUtils.isLatestRelease(release)).toBe(expectedBool);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDockerTags', () => {
|
||||
test.each([
|
||||
// PRs
|
||||
[
|
||||
'lean',
|
||||
['linux/arm64'],
|
||||
SHA,
|
||||
'pull_request',
|
||||
PR_ID,
|
||||
[`${REPO}:22e7c60-arm`, `${REPO}:${SHA}-arm`, `${REPO}:pr-${PR_ID}-arm`],
|
||||
],
|
||||
[
|
||||
'ci',
|
||||
['linux/amd64'],
|
||||
SHA,
|
||||
'pull_request',
|
||||
PR_ID,
|
||||
[`${REPO}:22e7c60-ci`, `${REPO}:${SHA}-ci`, `${REPO}:pr-${PR_ID}-ci`],
|
||||
],
|
||||
[
|
||||
'lean',
|
||||
['linux/amd64'],
|
||||
SHA,
|
||||
'pull_request',
|
||||
PR_ID,
|
||||
[`${REPO}:22e7c60`, `${REPO}:${SHA}`, `${REPO}:pr-${PR_ID}`],
|
||||
],
|
||||
[
|
||||
'dev',
|
||||
['linux/arm64'],
|
||||
SHA,
|
||||
'pull_request',
|
||||
PR_ID,
|
||||
[
|
||||
`${REPO}:22e7c60-dev-arm`,
|
||||
`${REPO}:${SHA}-dev-arm`,
|
||||
`${REPO}:pr-${PR_ID}-dev-arm`,
|
||||
],
|
||||
],
|
||||
[
|
||||
'dev',
|
||||
['linux/amd64'],
|
||||
SHA,
|
||||
'pull_request',
|
||||
PR_ID,
|
||||
[`${REPO}:22e7c60-dev`, `${REPO}:${SHA}-dev`, `${REPO}:pr-${PR_ID}-dev`],
|
||||
],
|
||||
// old releases
|
||||
[
|
||||
'lean',
|
||||
['linux/arm64'],
|
||||
SHA,
|
||||
'release',
|
||||
OLD_REL,
|
||||
[`${REPO}:22e7c60-arm`, `${REPO}:${SHA}-arm`, `${REPO}:${OLD_REL}-arm`],
|
||||
],
|
||||
[
|
||||
'lean',
|
||||
['linux/amd64'],
|
||||
SHA,
|
||||
'release',
|
||||
OLD_REL,
|
||||
[`${REPO}:22e7c60`, `${REPO}:${SHA}`, `${REPO}:${OLD_REL}`],
|
||||
],
|
||||
[
|
||||
'dev',
|
||||
['linux/arm64'],
|
||||
SHA,
|
||||
'release',
|
||||
OLD_REL,
|
||||
[
|
||||
`${REPO}:22e7c60-dev-arm`,
|
||||
`${REPO}:${SHA}-dev-arm`,
|
||||
`${REPO}:${OLD_REL}-dev-arm`,
|
||||
],
|
||||
],
|
||||
[
|
||||
'dev',
|
||||
['linux/amd64'],
|
||||
SHA,
|
||||
'release',
|
||||
OLD_REL,
|
||||
[`${REPO}:22e7c60-dev`, `${REPO}:${SHA}-dev`, `${REPO}:${OLD_REL}-dev`],
|
||||
],
|
||||
// new releases
|
||||
[
|
||||
'lean',
|
||||
['linux/arm64'],
|
||||
SHA,
|
||||
'release',
|
||||
NEW_REL,
|
||||
[
|
||||
`${REPO}:22e7c60-arm`,
|
||||
`${REPO}:${SHA}-arm`,
|
||||
`${REPO}:${NEW_REL}-arm`,
|
||||
`${REPO}:latest-arm`,
|
||||
],
|
||||
],
|
||||
[
|
||||
'lean',
|
||||
['linux/amd64'],
|
||||
SHA,
|
||||
'release',
|
||||
NEW_REL,
|
||||
[`${REPO}:22e7c60`, `${REPO}:${SHA}`, `${REPO}:${NEW_REL}`, `${REPO}:latest`],
|
||||
],
|
||||
[
|
||||
'dev',
|
||||
['linux/arm64'],
|
||||
SHA,
|
||||
'release',
|
||||
NEW_REL,
|
||||
[
|
||||
`${REPO}:22e7c60-dev-arm`,
|
||||
`${REPO}:${SHA}-dev-arm`,
|
||||
`${REPO}:${NEW_REL}-dev-arm`,
|
||||
`${REPO}:latest-dev-arm`,
|
||||
],
|
||||
],
|
||||
[
|
||||
'dev',
|
||||
['linux/amd64'],
|
||||
SHA,
|
||||
'release',
|
||||
NEW_REL,
|
||||
[
|
||||
`${REPO}:22e7c60-dev`,
|
||||
`${REPO}:${SHA}-dev`,
|
||||
`${REPO}:${NEW_REL}-dev`,
|
||||
`${REPO}:latest-dev`,
|
||||
],
|
||||
],
|
||||
// merge on master
|
||||
[
|
||||
'lean',
|
||||
['linux/arm64'],
|
||||
SHA,
|
||||
'push',
|
||||
'master',
|
||||
[`${REPO}:22e7c60-arm`, `${REPO}:${SHA}-arm`, `${REPO}:master-arm`],
|
||||
],
|
||||
[
|
||||
'lean',
|
||||
['linux/amd64'],
|
||||
SHA,
|
||||
'push',
|
||||
'master',
|
||||
[`${REPO}:22e7c60`, `${REPO}:${SHA}`, `${REPO}:master`],
|
||||
],
|
||||
[
|
||||
'dev',
|
||||
['linux/arm64'],
|
||||
SHA,
|
||||
'push',
|
||||
'master',
|
||||
[
|
||||
`${REPO}:22e7c60-dev-arm`,
|
||||
`${REPO}:${SHA}-dev-arm`,
|
||||
`${REPO}:master-dev-arm`,
|
||||
],
|
||||
],
|
||||
[
|
||||
'dev',
|
||||
['linux/amd64'],
|
||||
SHA,
|
||||
'push',
|
||||
'master',
|
||||
[`${REPO}:22e7c60-dev`, `${REPO}:${SHA}-dev`, `${REPO}:master-dev`],
|
||||
],
|
||||
|
||||
])('returns expected tags', (preset, platforms, sha, buildContext, buildContextRef, expectedTags) => {
|
||||
const tags = dockerUtils.getDockerTags({
|
||||
preset, platforms, sha, buildContext, buildContextRef,
|
||||
});
|
||||
expect(tags).toEqual(expect.arrayContaining(expectedTags));
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDockerCommand', () => {
|
||||
test.each([
|
||||
[
|
||||
'lean',
|
||||
['linux/amd64'],
|
||||
true,
|
||||
SHA,
|
||||
'push',
|
||||
'master',
|
||||
['--push', `-t ${REPO}:master `],
|
||||
],
|
||||
[
|
||||
'dev',
|
||||
['linux/amd64'],
|
||||
false,
|
||||
SHA,
|
||||
'push',
|
||||
'master',
|
||||
['--load', `-t ${REPO}:master-dev `],
|
||||
],
|
||||
// multi-platform
|
||||
[
|
||||
'lean',
|
||||
['linux/arm64', 'linux/amd64'],
|
||||
true,
|
||||
SHA,
|
||||
'push',
|
||||
'master',
|
||||
['--platform linux/arm64,linux/amd64'],
|
||||
],
|
||||
])('returns expected docker command', (preset, platform, isAuthenticated, sha, buildContext, buildContextRef, contains) => {
|
||||
const cmd = dockerUtils.getDockerCommand({
|
||||
preset, platform, isAuthenticated, sha, buildContext, buildContextRef,
|
||||
});
|
||||
contains.forEach((expectedSubstring) => {
|
||||
expect(cmd).toContain(expectedSubstring);
|
||||
});
|
||||
});
|
||||
});
|
||||
120
.github/supersetbot/src/git.js
vendored
120
.github/supersetbot/src/git.js
vendored
@@ -1,120 +0,0 @@
|
||||
import simpleGit from 'simple-git';
|
||||
import semver from 'semver';
|
||||
|
||||
import GitRelease from './git_release.js';
|
||||
|
||||
export default class Git {
|
||||
#releaseTags;
|
||||
|
||||
constructor(context, mainBranch = 'master') {
|
||||
this.context = context;
|
||||
this.mainBranch = mainBranch;
|
||||
this.releases = new Map();
|
||||
this.git = simpleGit();
|
||||
this.mainBranchGitRelease = this.mainBranchGitRelease.bind(this);
|
||||
this.getReleaseLabels = this.getReleaseLabels.bind(this);
|
||||
}
|
||||
|
||||
async mainBranchGitRelease() {
|
||||
let rel = this.releases.get(this.mainBranch);
|
||||
if (!rel) {
|
||||
rel = await this.loadRelease(this.mainBranch);
|
||||
}
|
||||
return rel;
|
||||
}
|
||||
|
||||
async releaseTags() {
|
||||
if (!this.#releaseTags) {
|
||||
const tags = await this.git.tags();
|
||||
// Filter tags to include only those that match semver and are official releases
|
||||
const semverTags = tags.all.filter((tag) => semver.valid(tag) && !tag.includes('-') && !tag.includes('v'));
|
||||
semverTags.sort((a, b) => semver.compare(a, b));
|
||||
this.#releaseTags = semverTags;
|
||||
}
|
||||
return this.#releaseTags;
|
||||
}
|
||||
|
||||
async loadMainBranch() {
|
||||
await this.loadRelease(this.mainBranch);
|
||||
}
|
||||
|
||||
async loadReleases(tags = null) {
|
||||
const tagsToFetch = tags || await this.releaseTags();
|
||||
if (!tags) {
|
||||
await this.loadMainBranch();
|
||||
}
|
||||
const promises = [];
|
||||
tagsToFetch.forEach((tag) => {
|
||||
promises.push(this.loadRelease(tag));
|
||||
});
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
async loadRelease(tag) {
|
||||
const release = new GitRelease(tag, this.context);
|
||||
await release.load();
|
||||
this.releases.set(tag, release);
|
||||
return release;
|
||||
}
|
||||
|
||||
static shortenSHA(sha) {
|
||||
return sha.substring(0, 7);
|
||||
}
|
||||
|
||||
async getReleaseLabels(prNumber, verbose, excludeCherries = false) {
|
||||
const labels = [];
|
||||
const main = await this.mainBranchGitRelease();
|
||||
const commit = main.prIdCommitMap.get(prNumber);
|
||||
if (commit) {
|
||||
const { sha } = commit;
|
||||
const shortSHA = Git.shortenSHA(sha);
|
||||
if (verbose) {
|
||||
console.log(`PR ${prNumber} is ${shortSHA} on branch ${this.mainBranch}`);
|
||||
}
|
||||
|
||||
let firstGitReleased = null;
|
||||
const tags = await this.releaseTags();
|
||||
tags.forEach((tag) => {
|
||||
const release = this.releases.get(tag);
|
||||
if (release.shaCommitMap.get(sha) && !firstGitReleased && release.tag !== this.mainBranch) {
|
||||
firstGitReleased = release.tag;
|
||||
labels.push(`🚢 ${release.tag}`);
|
||||
}
|
||||
const commitInGitRelease = release.prIdCommitMap.get(prNumber);
|
||||
if (!excludeCherries && commitInGitRelease && commitInGitRelease.sha !== sha) {
|
||||
labels.push(`🍒 ${release.tag}`);
|
||||
}
|
||||
});
|
||||
if (labels.length >= 1) {
|
||||
// using this emoji to show it's been labeled by the bot
|
||||
labels.push('🏷️ bot');
|
||||
}
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
|
||||
async previousRelease(release) {
|
||||
const tags = await this.releaseTags();
|
||||
return tags[tags.indexOf(release) - 1];
|
||||
}
|
||||
|
||||
async getPRsToSync(release, verbose = false, excludeCherries = false) {
|
||||
const prevRelease = await this.previousRelease(release);
|
||||
const releaseRange = new GitRelease(release, this.context, prevRelease);
|
||||
await releaseRange.load();
|
||||
const prIds = releaseRange.prIdCommitMap.keys();
|
||||
|
||||
const prs = [];
|
||||
const promises = [];
|
||||
[...prIds].forEach(prId => {
|
||||
promises.push(
|
||||
this.getReleaseLabels(prId, verbose, excludeCherries)
|
||||
.then((labels) => {
|
||||
prs.push({ prId, labels });
|
||||
}),
|
||||
);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
return prs;
|
||||
}
|
||||
}
|
||||
50
.github/supersetbot/src/git_release.js
vendored
50
.github/supersetbot/src/git_release.js
vendored
@@ -1,50 +0,0 @@
|
||||
import simpleGit from 'simple-git';
|
||||
|
||||
export default class GitRelease {
|
||||
constructor(tag, context, from = null) {
|
||||
this.tag = tag;
|
||||
this.context = context;
|
||||
this.prNumberRegex = /\(#(\d+)\)/;
|
||||
this.shaCommitMap = null;
|
||||
this.prIdCommitMap = null;
|
||||
this.prCommitMap = null;
|
||||
this.git = simpleGit();
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
extractPRNumber(commitMessage) {
|
||||
const match = (commitMessage || '').match(this.prNumberRegex);
|
||||
return match ? parseInt(match[1], 10) : null;
|
||||
}
|
||||
|
||||
async load() {
|
||||
let from = this.from || await this.git.firstCommit();
|
||||
if (from.includes('\n')) {
|
||||
[from] = from.split('\n');
|
||||
}
|
||||
const range = `${this.from || 'first'}..${this.tag}`;
|
||||
const commits = await this.git.log({ from, to: this.tag });
|
||||
this.context.log(`${range} - fetched ${commits.all.length} commits`);
|
||||
|
||||
this.shaCommitMap = new Map();
|
||||
commits.all.forEach((commit) => {
|
||||
const sha = commit.hash.substring(0, 7);
|
||||
this.shaCommitMap.set(
|
||||
sha,
|
||||
{
|
||||
prId: this.extractPRNumber(commit.message),
|
||||
message: commit.message,
|
||||
sha,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
this.prIdCommitMap = new Map();
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const commit of this.shaCommitMap.values()) {
|
||||
if (commit.prId) {
|
||||
this.prIdCommitMap.set(commit.prId, commit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
252
.github/supersetbot/src/github.js
vendored
252
.github/supersetbot/src/github.js
vendored
@@ -1,252 +0,0 @@
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { throttling } from '@octokit/plugin-throttling';
|
||||
|
||||
import { ORG_LIST, PROTECTED_LABEL_PATTERNS, COMMITTER_TEAM } from './metadata.js';
|
||||
|
||||
class Github {
|
||||
#userInTeamCache;
|
||||
|
||||
constructor({ context, issueNumber = null, token = null }) {
|
||||
this.context = context;
|
||||
this.issueNumber = issueNumber;
|
||||
const githubToken = token || process.env.GITHUB_TOKEN;
|
||||
if (!githubToken) {
|
||||
const msg = 'GITHUB_TOKEN is not set';
|
||||
this.context.logError(msg);
|
||||
}
|
||||
const throttledOctokit = Octokit.plugin(throttling);
|
||||
// eslint-disable-next-line new-cap
|
||||
this.octokit = new throttledOctokit({
|
||||
auth: githubToken,
|
||||
throttle: {
|
||||
id: 'supersetbot',
|
||||
onRateLimit: (retryAfter, options, octokit, retryCount) => {
|
||||
const howManyRetries = 10;
|
||||
octokit.log.warn(`Retry ${retryCount} out of ${howManyRetries} - retrying in ${retryAfter} seconds!`);
|
||||
if (retryCount < howManyRetries) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
onSecondaryRateLimit: (retryAfter, options, octokit) => {
|
||||
octokit.log.warn(`SecondaryRateLimit detected for request ${options.method} ${options.url}`);
|
||||
},
|
||||
},
|
||||
});
|
||||
this.syncLabels = this.syncLabels.bind(this);
|
||||
this.#userInTeamCache = new Map();
|
||||
}
|
||||
|
||||
unPackRepo() {
|
||||
const [owner, repo] = this.context.repo.split('/');
|
||||
return { repo, owner };
|
||||
}
|
||||
|
||||
async label(issueNumber, label, actor = null, verbose = false, dryRun = false) {
|
||||
let hasPerm = true;
|
||||
if (actor && Github.isLabelProtected(label)) {
|
||||
hasPerm = await this.checkIfUserInTeam(actor, COMMITTER_TEAM, verbose);
|
||||
}
|
||||
if (hasPerm) {
|
||||
const addLabelWrapped = this.context.commandWrapper({
|
||||
func: this.octokit.rest.issues.addLabels,
|
||||
successMsg: `label "${label}" added to issue ${issueNumber}`,
|
||||
verbose,
|
||||
dryRun,
|
||||
});
|
||||
await addLabelWrapped({
|
||||
...this.unPackRepo(),
|
||||
issue_number: issueNumber,
|
||||
labels: [label],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async createComment(body) {
|
||||
if (this.issueNumber) {
|
||||
await this.octokit.rest.issues.createComment({
|
||||
...this.unPackRepo(),
|
||||
body,
|
||||
issue_number: this.issueNumber,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async unlabel(issueNumber, label, actor = null, verbose = false, dryRun = false) {
|
||||
let hasPerm = true;
|
||||
if (actor && Github.isLabelProtected(label)) {
|
||||
hasPerm = await this.checkIfUserInTeam(actor, COMMITTER_TEAM, verbose);
|
||||
}
|
||||
if (hasPerm) {
|
||||
const removeLabelWrapped = this.context.commandWrapper({
|
||||
func: this.octokit.rest.issues.removeLabel,
|
||||
successMsg: `label "${label}" removed from issue ${issueNumber}`,
|
||||
verbose,
|
||||
dryRun,
|
||||
});
|
||||
await removeLabelWrapped({
|
||||
...this.unPackRepo(),
|
||||
issue_number: issueNumber,
|
||||
name: label,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async assignOrgLabel(issueNumber, verbose = false, dryRun = false) {
|
||||
const issue = await this.octokit.rest.issues.get({
|
||||
...this.unPackRepo(),
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
const username = issue.data.user.login;
|
||||
const orgs = await this.octokit.orgs.listForUser({ username });
|
||||
const orgNames = orgs.data.map((v) => v.login);
|
||||
|
||||
// get list of matching github orgs
|
||||
const matchingOrgs = orgNames.filter((org) => ORG_LIST.includes(org));
|
||||
if (matchingOrgs.length) {
|
||||
const wrapped = this.context.commandWrapper({
|
||||
func: this.octokit.rest.issues.addLabels,
|
||||
successMsg: `added label(s) ${matchingOrgs} to issue ${issueNumber}`,
|
||||
errorMsg: "couldn't add labels to issue",
|
||||
verbose,
|
||||
dryRun,
|
||||
});
|
||||
wrapped({
|
||||
...this.unPackRepo(),
|
||||
issue_number: issueNumber,
|
||||
labels: matchingOrgs,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async searchMergedPRs({
|
||||
query = '',
|
||||
onlyUnlabeled = true,
|
||||
verbose = false,
|
||||
startPage = 0,
|
||||
pages = 5,
|
||||
}) {
|
||||
// look for PRs
|
||||
let q = `repo:${this.context.repo} is:merged ${query}`;
|
||||
if (onlyUnlabeled) {
|
||||
q = `${q} -label:"🏷️ bot"`;
|
||||
}
|
||||
if (verbose) {
|
||||
this.context.log(`Query: ${q}`);
|
||||
}
|
||||
let prs = [];
|
||||
for (let i = 0; i < pages; i += 1) {
|
||||
if (verbose) {
|
||||
this.context.log(`Fetching PRs to process page ${i + 1} out of ${pages}`);
|
||||
}
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const data = await this.octokit.search.issuesAndPullRequests({
|
||||
q,
|
||||
per_page: 100,
|
||||
page: startPage + i,
|
||||
});
|
||||
prs = [...prs, ...data.data.items];
|
||||
}
|
||||
if (verbose) {
|
||||
this.context.log(`Fetched ${prs.length}`);
|
||||
}
|
||||
return prs;
|
||||
}
|
||||
|
||||
async syncLabels({
|
||||
labels,
|
||||
prId,
|
||||
actor = null,
|
||||
verbose = false,
|
||||
dryRun = false,
|
||||
existingLabels = null,
|
||||
}) {
|
||||
if (verbose) {
|
||||
this.context.log(`[PR: ${prId}] - sync labels ${labels}`);
|
||||
}
|
||||
let hasPerm = true;
|
||||
if (actor) {
|
||||
hasPerm = await this.checkIfUserInTeam(actor, COMMITTER_TEAM, verbose);
|
||||
}
|
||||
if (!hasPerm) {
|
||||
return;
|
||||
}
|
||||
let targetLabels = existingLabels;
|
||||
if (targetLabels === null) {
|
||||
// No labels have been passed as an array, so checking against GitHub
|
||||
const resp = await this.octokit.issues.listLabelsOnIssue({
|
||||
...this.unPackRepo(),
|
||||
issue_number: prId,
|
||||
});
|
||||
targetLabels = resp.data.map((l) => l.name);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
this.context.log(`[PR: ${prId}] - target release labels: ${labels}`);
|
||||
this.context.log(`[PR: ${prId}] - existing labels on issue: ${existingLabels}`);
|
||||
}
|
||||
|
||||
// Extract existing labels with the given prefixes
|
||||
const prefixes = ['🚢', '🍒', '🎯', '🏷️'];
|
||||
const existingPrefixLabels = targetLabels
|
||||
.filter((label) => prefixes.some((s) => typeof(label) === 'string' && label.startsWith(s)));
|
||||
|
||||
// Labels to add
|
||||
const labelsToAdd = labels.filter((label) => !existingPrefixLabels.includes(label));
|
||||
if (verbose) {
|
||||
this.context.log(`[PR: ${prId}] - labels to add: ${labelsToAdd}`);
|
||||
}
|
||||
// Labels to remove
|
||||
const labelsToRemove = existingPrefixLabels.filter((label) => !labels.includes(label));
|
||||
if (verbose) {
|
||||
this.context.log(`[PR: ${prId}] - labels to remove: ${labelsToRemove}`);
|
||||
}
|
||||
|
||||
// Add labels
|
||||
if (labelsToAdd.length > 0 && !dryRun) {
|
||||
await this.octokit.issues.addLabels({
|
||||
...this.unPackRepo(),
|
||||
issue_number: prId,
|
||||
labels: labelsToAdd,
|
||||
});
|
||||
}
|
||||
|
||||
// Remove labels
|
||||
if (labelsToRemove.length > 0 && !dryRun) {
|
||||
await Promise.all(labelsToRemove.map((label) => this.octokit.issues.removeLabel({
|
||||
...this.unPackRepo(),
|
||||
issue_number: prId,
|
||||
name: label,
|
||||
})));
|
||||
}
|
||||
this.context.logSuccess(`synched labels for PR ${prId} with labels ${labels}`);
|
||||
}
|
||||
|
||||
async checkIfUserInTeam(username, team, verbose = false) {
|
||||
let isInTeam = this.#userInTeamCache.get([username, team]);
|
||||
if (isInTeam !== undefined) {
|
||||
return isInTeam;
|
||||
}
|
||||
|
||||
const [org, teamSlug] = team.split('/');
|
||||
const wrapped = this.context.commandWrapper({
|
||||
func: this.octokit.teams.getMembershipForUserInOrg,
|
||||
errorMsg: `User "${username}" is not authorized to alter protected labels.`,
|
||||
verbose,
|
||||
});
|
||||
const resp = await wrapped({
|
||||
org,
|
||||
team_slug: teamSlug,
|
||||
username,
|
||||
});
|
||||
isInTeam = resp?.data?.state === 'active';
|
||||
this.#userInTeamCache.set([username, team], isInTeam);
|
||||
return isInTeam;
|
||||
}
|
||||
|
||||
static isLabelProtected(label) {
|
||||
return PROTECTED_LABEL_PATTERNS.some((pattern) => new RegExp(pattern).test(label));
|
||||
}
|
||||
}
|
||||
|
||||
export default Github;
|
||||
39
.github/supersetbot/src/index.js
vendored
39
.github/supersetbot/src/index.js
vendored
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import getCLI from './cli.js';
|
||||
import Context from './context.js';
|
||||
import Github from './github.js';
|
||||
|
||||
async function runCommandFromGithubAction(rawCommand) {
|
||||
const context = new Context('GHA');
|
||||
const cli = getCLI(context);
|
||||
const github = new Github(context);
|
||||
|
||||
// Make rawCommand look like argv
|
||||
const cmd = rawCommand.trim().replace('@supersetbot', 'supersetbot');
|
||||
const args = context.parseArgs(cmd);
|
||||
|
||||
await cli.parseAsync(['node', ...args]);
|
||||
const msg = await context.onDone();
|
||||
|
||||
github.createComment(msg);
|
||||
}
|
||||
|
||||
export { runCommandFromGithubAction };
|
||||
51
.github/supersetbot/src/index.test.js
vendored
51
.github/supersetbot/src/index.test.js
vendored
@@ -1,51 +0,0 @@
|
||||
// import * as stringArgv from 'string-argv';
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
import Context from './context.js';
|
||||
import Github from './github.js';
|
||||
import * as index from './index.js';
|
||||
|
||||
describe('runCommandFromGithubAction', () => {
|
||||
const labelSpy = jest.spyOn(Github.prototype, 'label').mockImplementation(jest.fn());
|
||||
// mocking some of the Context object
|
||||
const onDoneSpy = jest.spyOn(Context.prototype, 'onDone');
|
||||
const doneCommentSpy = jest.spyOn(Context.prototype, 'doneComment');
|
||||
const parseArgsSpy = jest.spyOn(Context.prototype, 'parseArgs');
|
||||
jest.spyOn(Github.prototype, 'createComment').mockImplementation(jest.fn());
|
||||
|
||||
let originalEnv;
|
||||
|
||||
afterEach(() => {
|
||||
process.env = originalEnv;
|
||||
});
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
originalEnv = process.env;
|
||||
process.env.GITHUB_ISSUE_NUMBER = '666';
|
||||
process.env.GITHUB_REPOSITORY = 'apache/superset';
|
||||
});
|
||||
|
||||
it('should strip the command', async () => {
|
||||
await index.runCommandFromGithubAction(' @supersetbot label test-label ');
|
||||
expect(parseArgsSpy).toHaveBeenCalledWith('supersetbot label test-label');
|
||||
|
||||
await index.runCommandFromGithubAction(' \n @supersetbot label test-label \n \n \n');
|
||||
expect(parseArgsSpy).toHaveBeenCalledWith('supersetbot label test-label');
|
||||
|
||||
await index.runCommandFromGithubAction(' \n \t@supersetbot label test-label \t \n \n\t \n');
|
||||
expect(parseArgsSpy).toHaveBeenCalledWith('supersetbot label test-label');
|
||||
});
|
||||
|
||||
it('should parse the raw command correctly and call commands.label and context.onDone', async () => {
|
||||
await index.runCommandFromGithubAction('@supersetbot label test-label');
|
||||
|
||||
expect(labelSpy).toHaveBeenCalled();
|
||||
expect(onDoneSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should generate a good comment message', async () => {
|
||||
await index.runCommandFromGithubAction('@supersetbot label test-label');
|
||||
const comment = doneCommentSpy.mock.results[0].value;
|
||||
expect(comment).toContain('> `supersetbot label test-label`');
|
||||
});
|
||||
});
|
||||
35
.github/supersetbot/src/metadata.js
vendored
35
.github/supersetbot/src/metadata.js
vendored
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
export const ORG_LIST = [
|
||||
'preset-io',
|
||||
'airbnb',
|
||||
'dropbox',
|
||||
'lyft',
|
||||
'Turing',
|
||||
'Superset-Community-Partners',
|
||||
'CybercentreCanada',
|
||||
];
|
||||
export const PROTECTED_LABEL_PATTERNS = [
|
||||
'protected.*',
|
||||
'released.*',
|
||||
'hold.*',
|
||||
'^v\\d+(\\.\\d+)*$',
|
||||
'(🚢|🍒|🎯).*',
|
||||
];
|
||||
export const COMMITTER_TEAM = 'apache/superset-committers';
|
||||
27
.github/supersetbot/src/supersetbot
vendored
27
.github/supersetbot/src/supersetbot
vendored
@@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import getCLI from './cli.js';
|
||||
import Context from './context.js';
|
||||
|
||||
const envContext = new Context('CLI');
|
||||
const cli = getCLI(envContext);
|
||||
|
||||
cli.parse();
|
||||
78
.github/supersetbot/src/utils.js
vendored
78
.github/supersetbot/src/utils.js
vendored
@@ -1,78 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { spawn } from 'child_process';
|
||||
import { readFile } from 'fs/promises';
|
||||
import { fileURLToPath } from 'url';
|
||||
import path from 'path';
|
||||
|
||||
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
async function loadPackageJson() {
|
||||
try {
|
||||
const packageJsonPath = path.join(dirname, '../package.json');
|
||||
const data = await readFile(packageJsonPath, 'utf8');
|
||||
const packageJson = JSON.parse(data);
|
||||
return packageJson;
|
||||
} catch (error) {
|
||||
console.error('Error reading package.json:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
export async function currentPackageVersion() {
|
||||
const data = await loadPackageJson();
|
||||
return data.version;
|
||||
}
|
||||
|
||||
export function runShellCommand(command, raiseOnError = true) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Split the command string into an array of arguments
|
||||
const args = command.split(/\s+/).filter((s) => !!s && s !== '\\');
|
||||
const childProcess = spawn(args.shift(), args);
|
||||
let stdoutData = '';
|
||||
let stderrData = '';
|
||||
|
||||
// Capture stdout data
|
||||
childProcess.stdout.on('data', (data) => {
|
||||
stdoutData += data;
|
||||
console.log(`stdout: ${data}`);
|
||||
});
|
||||
|
||||
// Capture stderr data
|
||||
childProcess.stderr.on('data', (data) => {
|
||||
stderrData += data;
|
||||
console.error(`stderr: ${data}`);
|
||||
});
|
||||
|
||||
// Handle process exit
|
||||
childProcess.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
resolve(stdoutData);
|
||||
} else {
|
||||
const msg = `Command failed with code ${code}: ${stderrData}`;
|
||||
if (raiseOnError) {
|
||||
reject(new Error(msg));
|
||||
} else {
|
||||
console.error(msg);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
175
.github/workflows/bashlib.sh
vendored
175
.github/workflows/bashlib.sh
vendored
@@ -31,20 +31,6 @@ say() {
|
||||
fi
|
||||
}
|
||||
|
||||
# default command to run when the `run` input is empty
|
||||
default-setup-command() {
|
||||
apt-get-install
|
||||
pip-upgrade
|
||||
}
|
||||
|
||||
apt-get-install() {
|
||||
say "::group::apt-get install dependencies"
|
||||
sudo apt-get update && sudo apt-get install --yes \
|
||||
libsasl2-dev \
|
||||
libldap2-dev
|
||||
say "::endgroup::"
|
||||
}
|
||||
|
||||
pip-upgrade() {
|
||||
say "::group::Upgrade pip"
|
||||
pip install --upgrade pip
|
||||
@@ -103,6 +89,8 @@ EOF
|
||||
setup-mysql() {
|
||||
say "::group::Initialize database"
|
||||
mysql -h 127.0.0.1 -P 13306 -u root --password=root <<-EOF
|
||||
SET GLOBAL transaction_isolation='READ-COMMITTED';
|
||||
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
DROP DATABASE IF EXISTS superset;
|
||||
CREATE DATABASE superset DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
|
||||
DROP DATABASE IF EXISTS sqllab_test_db;
|
||||
@@ -129,9 +117,17 @@ testdata() {
|
||||
say "::endgroup::"
|
||||
}
|
||||
|
||||
codecov() {
|
||||
say "::group::Upload code coverage"
|
||||
bash ".github/workflows/codecov.sh" "$@"
|
||||
celery-worker() {
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
say "::group::Start Celery worker"
|
||||
# must specify PYTHONPATH to make `tests.superset_test_config` importable
|
||||
export PYTHONPATH="$GITHUB_WORKSPACE"
|
||||
celery \
|
||||
--app=superset.tasks.celery_app:app \
|
||||
worker \
|
||||
--concurrency=2 \
|
||||
--detach \
|
||||
--optimization=fair
|
||||
say "::endgroup::"
|
||||
}
|
||||
|
||||
@@ -147,73 +143,113 @@ cypress-install() {
|
||||
cache-save cypress
|
||||
}
|
||||
|
||||
# Run Cypress and upload coverage reports
|
||||
cypress-run() {
|
||||
cypress-run-all() {
|
||||
local USE_DASHBOARD=$1
|
||||
local APP_ROOT=$2
|
||||
cd "$GITHUB_WORKSPACE/superset-frontend/cypress-base"
|
||||
|
||||
local page=$1
|
||||
local group=${2:-Default}
|
||||
local cypress="./node_modules/.bin/cypress run"
|
||||
local browser=${CYPRESS_BROWSER:-chrome}
|
||||
|
||||
export TERM="xterm"
|
||||
export ELECTRON_DISABLE_GPU=true # Attempt to disable GPU for Electron-based Cypress
|
||||
|
||||
say "::group::Run Cypress for [$page]"
|
||||
if [[ -z $CYPRESS_KEY ]]; then
|
||||
xvfb-run --auto-servernum --server-args='-screen 0, 1024x768x24' $cypress --spec "cypress/e2e/$page" --browser "$browser"
|
||||
else
|
||||
export CYPRESS_RECORD_KEY=$(echo $CYPRESS_KEY | base64 --decode)
|
||||
# additional flags for Cypress dashboard recording
|
||||
xvfb-run --auto-servernum --server-args='-screen 0, 1024x768x24' $cypress --spec "cypress/e2e/$page" --browser "$browser" \
|
||||
--record --group "$group" --tag "${GITHUB_REPOSITORY},${GITHUB_EVENT_NAME}" \
|
||||
--parallel --ci-build-id "${GITHUB_SHA:0:8}-${NONCE}"
|
||||
|
||||
fi
|
||||
|
||||
# don't add quotes to $record because we do want word splitting
|
||||
say "::endgroup::"
|
||||
}
|
||||
|
||||
cypress-run-all() {
|
||||
# Start Flask and run it in background
|
||||
# --no-debugger means disable the interactive debugger on the 500 page
|
||||
# so errors can print to stderr.
|
||||
local flasklog="${HOME}/flask.log"
|
||||
local port=8081
|
||||
export CYPRESS_BASE_URL="http://localhost:${port}"
|
||||
CYPRESS_BASE_URL="http://localhost:${port}"
|
||||
if [ -n "$APP_ROOT" ]; then
|
||||
export SUPERSET_APP_ROOT=$APP_ROOT
|
||||
CYPRESS_BASE_URL=${CYPRESS_BASE_URL}${APP_ROOT}
|
||||
fi
|
||||
export CYPRESS_BASE_URL
|
||||
|
||||
nohup flask run --no-debugger -p $port >"$flasklog" 2>&1 </dev/null &
|
||||
local flaskProcessId=$!
|
||||
|
||||
cypress-run "*/**/*"
|
||||
USE_DASHBOARD_FLAG=''
|
||||
if [ "$USE_DASHBOARD" = "true" ]; then
|
||||
USE_DASHBOARD_FLAG='--use-dashboard'
|
||||
fi
|
||||
|
||||
# UNCOMMENT the next few commands to monitor memory usage
|
||||
# monitor_memory & # Start memory monitoring in the background
|
||||
# memoryMonitorPid=$!
|
||||
python ../../scripts/cypress_run.py --parallelism $PARALLELISM --parallelism-id $PARALLEL_ID --group $PARALLEL_ID --retries 5 $USE_DASHBOARD_FLAG
|
||||
# kill $memoryMonitorPid
|
||||
|
||||
# After job is done, print out Flask log for debugging
|
||||
say "::group::Flask log for default run"
|
||||
echo "::group::Flask log for default run"
|
||||
cat "$flasklog"
|
||||
say "::endgroup::"
|
||||
|
||||
# Rerun SQL Lab tests with backend persist disabled
|
||||
export SUPERSET_CONFIG=tests.integration_tests.superset_test_config_sqllab_backend_persist_off
|
||||
|
||||
# Restart Flask with new configs
|
||||
echo "::endgroup::"
|
||||
# make sure the program exits
|
||||
kill $flaskProcessId
|
||||
}
|
||||
|
||||
playwright-install() {
|
||||
cd "$GITHUB_WORKSPACE/superset-frontend"
|
||||
|
||||
say "::group::Install Playwright browsers"
|
||||
npx playwright install --with-deps chromium
|
||||
# Create output directories for test results and debugging
|
||||
mkdir -p playwright-results
|
||||
mkdir -p test-results
|
||||
say "::endgroup::"
|
||||
}
|
||||
|
||||
playwright-run() {
|
||||
local APP_ROOT=$1
|
||||
|
||||
# Start Flask from the project root (same as Cypress)
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
local flasklog="${HOME}/flask-playwright.log"
|
||||
local port=8081
|
||||
PLAYWRIGHT_BASE_URL="http://localhost:${port}"
|
||||
if [ -n "$APP_ROOT" ]; then
|
||||
export SUPERSET_APP_ROOT=$APP_ROOT
|
||||
PLAYWRIGHT_BASE_URL=${PLAYWRIGHT_BASE_URL}${APP_ROOT}/
|
||||
fi
|
||||
export PLAYWRIGHT_BASE_URL
|
||||
|
||||
nohup flask run --no-debugger -p $port >"$flasklog" 2>&1 </dev/null &
|
||||
local flaskProcessId=$!
|
||||
|
||||
cypress-run "sqllab/*" "Backend persist"
|
||||
# Ensure cleanup on exit
|
||||
trap "kill $flaskProcessId 2>/dev/null || true" EXIT
|
||||
|
||||
# Upload code coverage separately so each page can have separate flags
|
||||
# -c will clean existing coverage reports, -F means add flags
|
||||
# || true to prevent CI failure on codecov upload
|
||||
codecov -c -F "cypress" || true
|
||||
# Wait for server to be ready with health check
|
||||
local timeout=60
|
||||
say "Waiting for Flask server to start on port $port..."
|
||||
while [ $timeout -gt 0 ]; do
|
||||
if curl -f ${PLAYWRIGHT_BASE_URL}/health >/dev/null 2>&1; then
|
||||
say "Flask server is ready"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
timeout=$((timeout - 1))
|
||||
done
|
||||
|
||||
say "::group::Flask log for backend persist"
|
||||
cat "$flasklog"
|
||||
if [ $timeout -eq 0 ]; then
|
||||
echo "::error::Flask server failed to start within 60 seconds"
|
||||
echo "::group::Flask startup log"
|
||||
cat "$flasklog"
|
||||
echo "::endgroup::"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Change to frontend directory for Playwright execution
|
||||
cd "$GITHUB_WORKSPACE/superset-frontend"
|
||||
|
||||
say "::group::Run Playwright tests"
|
||||
echo "Running Playwright with baseURL: ${PLAYWRIGHT_BASE_URL}"
|
||||
npx playwright test auth/login --reporter=github --output=playwright-results
|
||||
local status=$?
|
||||
say "::endgroup::"
|
||||
|
||||
# After job is done, print out Flask log for debugging
|
||||
echo "::group::Flask log for Playwright run"
|
||||
cat "$flasklog"
|
||||
echo "::endgroup::"
|
||||
# make sure the program exits
|
||||
kill $flaskProcessId
|
||||
|
||||
return $status
|
||||
}
|
||||
|
||||
eyes-storybook-dependencies() {
|
||||
@@ -222,6 +258,21 @@ eyes-storybook-dependencies() {
|
||||
say "::endgroup::"
|
||||
}
|
||||
|
||||
monitor_memory() {
|
||||
# This is a small utility to monitor memory usage. Useful for debugging memory in GHA.
|
||||
# To use wrap your command as follows
|
||||
#
|
||||
# monitor_memory & # Start memory monitoring in the background
|
||||
# memoryMonitorPid=$!
|
||||
# YOUR_COMMAND_HERE
|
||||
# kill $memoryMonitorPid
|
||||
while true; do
|
||||
echo "$(date) - Top 5 memory-consuming processes:"
|
||||
ps -eo pid,comm,%mem --sort=-%mem | head -n 6 # First line is the header, next 5 are top processes
|
||||
sleep 2
|
||||
done
|
||||
}
|
||||
|
||||
cypress-run-applitools() {
|
||||
cd "$GITHUB_WORKSPACE/superset-frontend/cypress-base"
|
||||
|
||||
@@ -235,9 +286,7 @@ cypress-run-applitools() {
|
||||
nohup flask run --no-debugger -p $port >"$flasklog" 2>&1 </dev/null &
|
||||
local flaskProcessId=$!
|
||||
|
||||
$cypress --spec "cypress/e2e/*/**/*.applitools.test.ts" --browser "$browser" --headless --config ignoreTestFiles="[]"
|
||||
|
||||
codecov -c -F "cypress" || true
|
||||
$cypress --spec "cypress/applitools/**/*" --browser "$browser" --headless
|
||||
|
||||
say "::group::Flask log for default run"
|
||||
cat "$flasklog"
|
||||
|
||||
77
.github/workflows/bump-python-package.yml
vendored
Normal file
77
.github/workflows/bump-python-package.yml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
name: Bump Python Package
|
||||
|
||||
on:
|
||||
# Can be triggered manually
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
package:
|
||||
required: false
|
||||
description: The python package to bump (all if empty)
|
||||
group:
|
||||
required: false
|
||||
description: The optional dependency group to bump (as defined in pyproject.toml)
|
||||
limit:
|
||||
required: true
|
||||
description: Max number of PRs to open (0 for no limit)
|
||||
default: 5
|
||||
extra-flags:
|
||||
required: false
|
||||
default: --only-base
|
||||
description: Additional flags to pass to the bump-python command
|
||||
#schedule:
|
||||
# - cron: '0 0 * * *' # Runs daily at midnight UTC
|
||||
|
||||
jobs:
|
||||
bump-python-package:
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
actions: write
|
||||
contents: write
|
||||
pull-requests: write
|
||||
checks: write
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: true
|
||||
ref: master
|
||||
|
||||
- name: Setup supersetbot
|
||||
uses: ./.github/actions/setup-supersetbot/
|
||||
|
||||
- name: Set up Python ${{ inputs.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install uv
|
||||
run: pip install uv
|
||||
|
||||
- name: supersetbot bump-python -p "${{ github.event.inputs.package }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
git config --global user.email "action@github.com"
|
||||
git config --global user.name "GitHub Action"
|
||||
|
||||
PACKAGE_OPT=""
|
||||
if [ -n "${{ github.event.inputs.package }}" ]; then
|
||||
PACKAGE_OPT="-p ${{ github.event.inputs.package }}"
|
||||
fi
|
||||
|
||||
GROUP_OPT=""
|
||||
if [ -n "${{ github.event.inputs.group }}" ]; then
|
||||
GROUP_OPT="-g ${{ github.event.inputs.group }}"
|
||||
fi
|
||||
|
||||
EXTRA_FLAGS="${{ github.event.inputs.extra-flags }}"
|
||||
|
||||
supersetbot bump-python \
|
||||
--verbose \
|
||||
--use-current-repo \
|
||||
--include-subpackages \
|
||||
--limit ${{ github.event.inputs.limit }} \
|
||||
$PACKAGE_OPT \
|
||||
$GROUP_OPT \
|
||||
$EXTRA_FLAGS
|
||||
4
.github/workflows/cancel_duplicates.yml
vendored
4
.github/workflows/cancel_duplicates.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
jobs:
|
||||
cancel-duplicate-runs:
|
||||
name: Cancel duplicate workflow runs
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
actions: write
|
||||
contents: read
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
if: steps.check_queued.outputs.count >= 20
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Cancel duplicate workflow runs
|
||||
if: steps.check_queued.outputs.count >= 20
|
||||
|
||||
59
.github/workflows/check-python-deps.yml
vendored
Normal file
59
.github/workflows/check-python-deps.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: Check python dependencies
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
check-python-deps:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Python
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
|
||||
- name: Run uv
|
||||
if: steps.check.outputs.python
|
||||
run: ./scripts/uv-pip-compile.sh
|
||||
|
||||
- name: Check for uncommitted changes
|
||||
if: steps.check.outputs.python
|
||||
run: |
|
||||
echo "Full diff (for logging/debugging):"
|
||||
git diff
|
||||
|
||||
echo "Filtered diff (excluding comments and whitespace):"
|
||||
filtered_diff=$(git diff -U0 | grep '^[-+]' | grep -vE '^[-+]{3}' | grep -vE '^[-+][[:space:]]*#' | grep -vE '^[-+][[:space:]]*$' || true)
|
||||
echo "$filtered_diff"
|
||||
|
||||
if [[ -n "$filtered_diff" ]]; then
|
||||
echo
|
||||
echo "ERROR: The pinned dependencies are not up-to-date."
|
||||
echo "Please run './scripts/uv-pip-compile.sh' and commit the changes."
|
||||
echo "More info: https://github.com/apache/superset/tree/master/requirements"
|
||||
exit 1
|
||||
else
|
||||
echo "Pinned dependencies are up-to-date."
|
||||
fi
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
- "superset/migrations/**"
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
paths:
|
||||
- "superset/migrations/**"
|
||||
@@ -19,13 +19,13 @@ concurrency:
|
||||
jobs:
|
||||
check_db_migration_conflict:
|
||||
name: Check DB migration conflict
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Check and notify
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
|
||||
82
.github/workflows/claude.yml
vendored
Normal file
82
.github/workflows/claude.yml
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
name: Claude PR Assistant
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
if: |
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude'))
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
allowed: ${{ steps.check.outputs.allowed }}
|
||||
steps:
|
||||
- name: Check if user is allowed
|
||||
id: check
|
||||
run: |
|
||||
# List of allowed users
|
||||
ALLOWED_USERS="mistercrunch,rusackas"
|
||||
|
||||
# Get the commenter's username
|
||||
COMMENTER="${{ github.event.comment.user.login }}"
|
||||
|
||||
echo "Checking permissions for user: $COMMENTER"
|
||||
|
||||
# Check if user is in allowed list
|
||||
if [[ ",$ALLOWED_USERS," == *",$COMMENTER,"* ]]; then
|
||||
echo "allowed=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ User $COMMENTER is allowed to use Claude"
|
||||
else
|
||||
echo "allowed=false" >> $GITHUB_OUTPUT
|
||||
echo "❌ User $COMMENTER is not allowed to use Claude"
|
||||
fi
|
||||
|
||||
deny-access:
|
||||
needs: check-permissions
|
||||
if: needs.check-permissions.outputs.allowed == 'false'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Comment access denied
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const message = `👋 Hi @${{ github.event.comment.user.login || github.event.review.user.login || github.event.issue.user.login }}!
|
||||
|
||||
Thanks for trying to use Claude Code, but currently only certain team members have access to this feature.
|
||||
|
||||
If you believe you should have access, please contact a project maintainer.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: message
|
||||
});
|
||||
|
||||
claude-code-action:
|
||||
needs: check-permissions
|
||||
if: needs.check-permissions.outputs.allowed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
issues: write
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude PR Action
|
||||
uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
timeout_minutes: "60"
|
||||
1903
.github/workflows/codecov.sh
vendored
1903
.github/workflows/codecov.sh
vendored
File diff suppressed because it is too large
Load Diff
17
.github/workflows/codeql-analysis.yml
vendored
17
.github/workflows/codeql-analysis.yml
vendored
@@ -2,14 +2,10 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master", "[0-9].[0-9]"]
|
||||
paths:
|
||||
- "superset/**"
|
||||
branches: ["master", "[0-9].[0-9]*"]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: ["master"]
|
||||
paths:
|
||||
- "superset/**"
|
||||
schedule:
|
||||
- cron: "0 4 * * *"
|
||||
|
||||
@@ -21,7 +17,7 @@ concurrency:
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -35,7 +31,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
@@ -50,6 +52,7 @@ jobs:
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
54
.github/workflows/dependency-review.yml
vendored
54
.github/workflows/dependency-review.yml
vendored
@@ -5,23 +5,67 @@
|
||||
# Source repository: https://github.com/actions/dependency-review-action
|
||||
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
|
||||
name: "Dependency Review"
|
||||
on: [pull_request]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
dependency-review:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout Repository"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: "Dependency Review"
|
||||
uses: actions/dependency-review-action@v4
|
||||
continue-on-error: true
|
||||
with:
|
||||
fail-on-severity: critical
|
||||
# compatible/incompatible licenses addressed here: https://www.apache.org/legal/resolved.html
|
||||
# find SPDX identifiers here: https://spdx.org/licenses/
|
||||
deny-licenses: MS-LPL, BUSL-1.1, QPL-1.0, Sleepycat, SSPL-1.0, CPOL-1.02, AGPL-3.0, GPL-1.0+, BSD-4-Clause-UC, NPL-1.0, NPL-1.1, JSON
|
||||
# adding an exception for an ambigious license on store2, which has been resolved in the latest version. It's MIT: https://github.com/nbubna/store/blob/master/LICENSE-MIT
|
||||
allow-dependencies-licenses: 'pkg:npm/store2@2.14.2'
|
||||
# pkg:npm/store2@2.14.2
|
||||
# adding an exception for an ambigious license on store2, which has been resolved in
|
||||
# the latest version. It's MIT: https://github.com/nbubna/store/blob/master/LICENSE-MIT
|
||||
# pkg:npm/applitools/*
|
||||
# adding exception for all applitools modules (eyes-cypress and its dependencies),
|
||||
# which has an explicit OSS license approved by ASF
|
||||
# license: https://applitools.com/legal/open-source-terms-of-use/
|
||||
# pkg:npm/node-forge@1.3.1
|
||||
# selecting BSD-3-Clause licensing terms for node-forge to ensure compatibility with Apache
|
||||
allow-dependencies-licenses: pkg:npm/store2@2.14.2, pkg:npm/applitools/core, pkg:npm/applitools/core-base, pkg:npm/applitools/css-tree, pkg:npm/applitools/ec-client, pkg:npm/applitools/eg-socks5-proxy-server, pkg:npm/applitools/eyes, pkg:npm/applitools/eyes-cypress, pkg:npm/applitools/nml-client, pkg:npm/applitools/tunnel-client, pkg:npm/applitools/utils, pkg:npm/node-forge@1.3.1, pkg:npm/rgbcolor, pkg:npm/jszip@3.10.1
|
||||
|
||||
python-dependency-liccheck:
|
||||
# NOTE: Configuration for liccheck lives in our pyproject.yml.
|
||||
# You cannot use a liccheck.ini file in this workflow.
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: "Checkout Repository"
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
with:
|
||||
requirements-type: base
|
||||
|
||||
- name: "Set up liccheck"
|
||||
run: |
|
||||
uv pip install --system liccheck
|
||||
- name: "Run liccheck"
|
||||
run: |
|
||||
# run the checks
|
||||
liccheck -R output.txt
|
||||
# Print the report
|
||||
cat output.txt
|
||||
|
||||
85
.github/workflows/docker-release.yml
vendored
85
.github/workflows/docker-release.yml
vendored
@@ -1,85 +0,0 @@
|
||||
name: Docker Publish Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published, edited]
|
||||
|
||||
# Can be triggered manually
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release:
|
||||
required: true
|
||||
description: The version to generate
|
||||
git-ref:
|
||||
required: true
|
||||
description: The git reference to checkout prior to running the docker build
|
||||
force-latest:
|
||||
required: true
|
||||
type: choice
|
||||
default: 'false'
|
||||
description: Whether to force a latest tag on the release
|
||||
options:
|
||||
- true
|
||||
- false
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
- name: "Check for secrets"
|
||||
id: check
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -n "${{ (secrets.DOCKERHUB_USER != '' && secrets.DOCKERHUB_TOKEN != '') || '' }}" ]; then
|
||||
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
docker-release:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
name: docker-release
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
build_preset: ["dev", "lean", "py310", "websocket", "dockerize"]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Setup Node Env
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
- run: npm install -g supersetbot
|
||||
- name: Execute custom Node.js script
|
||||
env:
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
run: |
|
||||
RELEASE="${{ github.event.release.tag_name }}"
|
||||
FORCE_LATEST=""
|
||||
EVENT="${{github.event_name}}"
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
# in the case of a manually-triggered run, read release from input
|
||||
RELEASE="${{ github.event.inputs.release }}"
|
||||
if [ "${{ github.event.inputs.force-latest }}" = "true" ]; then
|
||||
FORCE_LATEST="--force-latest"
|
||||
fi
|
||||
# build_docker.py may not exist on that SHA, let's switcharoo to /tmp
|
||||
cp ./scripts/build_docker.py /tmp
|
||||
git checkout "${{ github.event.inputs.git-ref }}"
|
||||
cp /tmp/build_docker.py scripts/
|
||||
EVENT="release"
|
||||
fi
|
||||
|
||||
supersetbot docker \
|
||||
--preset ${{ matrix.build_preset }} \
|
||||
--context "$EVENT" \
|
||||
--context-ref "$RELEASE" $FORCE_LATEST \
|
||||
--platform "linux/arm64" \
|
||||
--platform "linux/amd64"
|
||||
110
.github/workflows/docker.yml
vendored
110
.github/workflows/docker.yml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
branches:
|
||||
- "master"
|
||||
@@ -14,21 +14,22 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
|
||||
setup_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
matrix_config: ${{ steps.set_matrix.outputs.matrix_config }}
|
||||
steps:
|
||||
- id: set_matrix
|
||||
run: |
|
||||
MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["ci"]'; else echo '["dev", "lean", "py310", "websocket", "dockerize"]'; fi)
|
||||
MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev", "lean"]'; else echo '["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"]'; fi)
|
||||
echo "matrix_config=${MATRIX_CONFIG}" >> $GITHUB_OUTPUT
|
||||
echo $GITHUB_OUTPUT
|
||||
|
||||
docker-build:
|
||||
name: docker-build
|
||||
needs: setup_matrix
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
build_preset: ${{fromJson(needs.setup_matrix.outputs.matrix_config)}}
|
||||
@@ -36,47 +37,104 @@ jobs:
|
||||
env:
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
IMAGE_TAG: apache/superset:GHA-${{ matrix.build_preset }}-${{ github.run_id }}
|
||||
|
||||
steps:
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Try to login to DockerHub
|
||||
continue-on-error: true
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USER }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Setup Node Env
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
- name: install supersetbot
|
||||
run: |
|
||||
npm install -g supersetbot
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Docker Environment
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
|
||||
uses: ./.github/actions/setup-docker
|
||||
with:
|
||||
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
|
||||
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
build: "true"
|
||||
|
||||
- name: Setup supersetbot
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
|
||||
uses: ./.github/actions/setup-supersetbot/
|
||||
|
||||
- name: Build Docker Image
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Single platform builds in pull_request context to speed things up
|
||||
if [ "${{ github.event_name }}" = "push" ]; then
|
||||
PLATFORM_ARG="--platform linux/arm64 --platform linux/amd64"
|
||||
# can only --load images in single-platform builds
|
||||
PUSH_OR_LOAD="--push"
|
||||
elif [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||
PLATFORM_ARG="--platform linux/amd64"
|
||||
PUSH_OR_LOAD="--load"
|
||||
fi
|
||||
|
||||
supersetbot docker \
|
||||
$PUSH_OR_LOAD \
|
||||
--preset ${{ matrix.build_preset }} \
|
||||
--context "$EVENT" \
|
||||
--context-ref "$RELEASE" $FORCE_LATEST \
|
||||
--extra-flags "--build-arg INCLUDE_CHROMIUM=false --tag $IMAGE_TAG" \
|
||||
$PLATFORM_ARG
|
||||
|
||||
# in the context of push (using multi-platform build), we need to pull the image locally
|
||||
- name: Docker pull
|
||||
if: github.event_name == 'push' && (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker)
|
||||
run: docker pull $IMAGE_TAG
|
||||
|
||||
- name: Print docker stats
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
|
||||
run: |
|
||||
echo "SHA: ${{ github.sha }}"
|
||||
echo "IMAGE: $IMAGE_TAG"
|
||||
docker images $IMAGE_TAG
|
||||
docker history $IMAGE_TAG
|
||||
|
||||
- name: docker-compose sanity check
|
||||
if: (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker) && matrix.build_preset == 'dev'
|
||||
shell: bash
|
||||
run: |
|
||||
export SUPERSET_BUILD_TARGET=${{ matrix.build_preset }}
|
||||
# This should reuse the CACHED image built in the previous steps
|
||||
docker compose build superset-init --build-arg DEV_MODE=false --build-arg INCLUDE_CHROMIUM=false
|
||||
docker compose up superset-init --exit-code-from superset-init
|
||||
|
||||
docker-compose-image-tag:
|
||||
# Run this job only on pushes to master (not for PRs)
|
||||
# goal is to check that building the latest image works, not required for all PR pushes
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Docker Environment
|
||||
if: steps.check.outputs.docker
|
||||
uses: ./.github/actions/setup-docker
|
||||
with:
|
||||
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
|
||||
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
build: "false"
|
||||
install-docker-compose: "true"
|
||||
- name: docker-compose sanity check
|
||||
if: steps.check.outputs.docker
|
||||
shell: bash
|
||||
run: |
|
||||
docker compose -f docker-compose-image-tag.yml up superset-init --exit-code-from superset-init
|
||||
|
||||
12
.github/workflows/embedded-sdk-release.yml
vendored
12
.github/workflows/embedded-sdk-release.yml
vendored
@@ -4,11 +4,11 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
@@ -23,16 +23,16 @@ jobs:
|
||||
build:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: superset-embedded-sdk
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "16"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
node-version-file: './superset-embedded-sdk/.nvmrc'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
- run: npm ci
|
||||
- run: npm run ci:release
|
||||
env:
|
||||
|
||||
6
.github/workflows/embedded-sdk-test.yml
vendored
6
.github/workflows/embedded-sdk-test.yml
vendored
@@ -13,15 +13,15 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
embedded-sdk-test:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: superset-embedded-sdk
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version-file: './superset-embedded-sdk/.nvmrc'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
|
||||
14
.github/workflows/ephemeral-env-pr-close.yml
vendored
14
.github/workflows/ephemeral-env-pr-close.yml
vendored
@@ -1,4 +1,10 @@
|
||||
name: Cleanup ephemeral envs (PR close)
|
||||
name: Cleanup ephemeral envs (PR close) [DEPRECATED]
|
||||
|
||||
# ⚠️ DEPRECATION NOTICE ⚠️
|
||||
# This workflow is deprecated and will be removed in a future version.
|
||||
# The new Superset Showtime workflow handles cleanup automatically.
|
||||
# See .github/workflows/showtime.yml and showtime-cleanup.yml for replacements.
|
||||
# Migration guide: https://github.com/mistercrunch/superset-showtime
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
@@ -6,7 +12,7 @@ on:
|
||||
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
@@ -22,7 +28,7 @@ jobs:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
name: Cleanup ephemeral envs
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
@@ -71,5 +77,5 @@ jobs:
|
||||
issue_number: ${{ github.event.number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: 'Ephemeral environment shutdown and build artifacts deleted.'
|
||||
body: '⚠️ **DEPRECATED WORKFLOW** - Ephemeral environment shutdown and build artifacts deleted. Please migrate to the new Superset Showtime system for future PRs.'
|
||||
})
|
||||
|
||||
501
.github/workflows/ephemeral-env.yml
vendored
501
.github/workflows/ephemeral-env.yml
vendored
@@ -1,132 +1,192 @@
|
||||
name: Ephemeral env workflow
|
||||
name: Ephemeral env workflow [DEPRECATED]
|
||||
|
||||
# ⚠️ DEPRECATION NOTICE ⚠️
|
||||
# This workflow is deprecated and will be removed in a future version.
|
||||
# Please use the new Superset Showtime workflow instead:
|
||||
# - Use label "🎪 trigger-start" instead of "testenv-up"
|
||||
# - Showtime provides better reliability and easier management
|
||||
# - See .github/workflows/showtime.yml for the replacement
|
||||
# - Migration guide: https://github.com/mistercrunch/superset-showtime
|
||||
|
||||
# Example manual trigger:
|
||||
# gh workflow run ephemeral-env.yml --ref fix_ephemerals --field label_name="testenv-up" --field issue_number=666
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_target:
|
||||
types:
|
||||
- labeled
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
label_name:
|
||||
description: 'Label name to simulate label-based /testenv trigger'
|
||||
required: true
|
||||
default: 'testenv-up'
|
||||
issue_number:
|
||||
description: 'Issue or PR number'
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
if: github.event.issue.pull_request
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
- name: "Check for secrets"
|
||||
id: check
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -n "${{ (secrets.AWS_ACCESS_KEY_ID != '' && secrets.AWS_SECRET_ACCESS_KEY != '') || '' }}" ]; then
|
||||
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
ephemeral-env-comment:
|
||||
ephemeral-env-label:
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}-comment
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-label
|
||||
cancel-in-progress: true
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
name: Evaluate ephemeral env comment trigger (/testenv)
|
||||
runs-on: ubuntu-latest
|
||||
name: Evaluate ephemeral env label trigger
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
pull-requests: write
|
||||
outputs:
|
||||
slash-command: ${{ steps.eval-body.outputs.result }}
|
||||
slash-command: ${{ steps.eval-label.outputs.result }}
|
||||
feature-flags: ${{ steps.eval-feature-flags.outputs.result }}
|
||||
sha: ${{ steps.get-sha.outputs.sha }}
|
||||
env:
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Debug
|
||||
run: |
|
||||
echo "Comment on PR #${{ github.event.issue.number }} by ${{ github.event.issue.user.login }}, ${{ github.event.comment.author_association }}"
|
||||
- name: Check for the "testenv-up" label
|
||||
id: eval-label
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
LABEL_NAME="${{ github.event.inputs.label_name }}"
|
||||
else
|
||||
LABEL_NAME="${{ github.event.label.name }}"
|
||||
fi
|
||||
|
||||
- name: Eval comment body for /testenv slash command
|
||||
uses: actions/github-script@v7
|
||||
id: eval-body
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
const pattern = /^\/testenv (up|down)/
|
||||
const result = pattern.exec(context.payload.comment.body)
|
||||
return result === null ? 'noop' : result[1]
|
||||
echo "Evaluating label: $LABEL_NAME"
|
||||
|
||||
- name: Eval comment body for feature flags
|
||||
uses: actions/github-script@v7
|
||||
id: eval-feature-flags
|
||||
with:
|
||||
script: |
|
||||
const pattern = /FEATURE_(\w+)=(\w+)/g;
|
||||
let results = [];
|
||||
[...context.payload.comment.body.matchAll(pattern)].forEach(match => {
|
||||
const config = {
|
||||
name: `SUPERSET_FEATURE_${match[1]}`,
|
||||
value: match[2],
|
||||
};
|
||||
results.push(config);
|
||||
});
|
||||
return results;
|
||||
if [[ "$LABEL_NAME" == "testenv-up" ]]; then
|
||||
echo "result=up" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "result=noop" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Limit to committers
|
||||
if: >
|
||||
steps.eval-body.outputs.result != 'noop' &&
|
||||
github.event.comment.author_association != 'MEMBER' &&
|
||||
github.event.comment.author_association != 'OWNER'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
const errMsg = '@${{ github.event.comment.user.login }} Ephemeral environment creation is currently limited to committers.'
|
||||
github.rest.issues.createComment({
|
||||
issue_number: ${{ github.event.issue.number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: errMsg
|
||||
})
|
||||
core.setFailed(errMsg)
|
||||
- name: Get event SHA
|
||||
id: get-sha
|
||||
if: steps.eval-label.outputs.result == 'up'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
let prSha;
|
||||
|
||||
// If event is workflow_dispatch, use the issue_number from inputs
|
||||
if (context.eventName === "workflow_dispatch") {
|
||||
const prNumber = "${{ github.event.inputs.issue_number }}";
|
||||
if (!prNumber) {
|
||||
console.log("No PR number found.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch PR details using the provided issue_number
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber
|
||||
});
|
||||
|
||||
prSha = pr.head.sha;
|
||||
} else {
|
||||
// If it's not workflow_dispatch, use the PR head sha from the event
|
||||
prSha = context.payload.pull_request.head.sha;
|
||||
}
|
||||
|
||||
console.log(`PR SHA: ${prSha}`);
|
||||
core.setOutput("sha", prSha);
|
||||
|
||||
- name: Looking for feature flags in PR description
|
||||
uses: actions/github-script@v7
|
||||
id: eval-feature-flags
|
||||
if: steps.eval-label.outputs.result == 'up'
|
||||
with:
|
||||
script: |
|
||||
const description = context.payload.pull_request
|
||||
? context.payload.pull_request.body || ''
|
||||
: context.payload.inputs.pr_description || '';
|
||||
|
||||
const pattern = /FEATURE_(\w+)=(\w+)/g;
|
||||
let results = [];
|
||||
[...description.matchAll(pattern)].forEach(match => {
|
||||
const config = {
|
||||
name: `SUPERSET_FEATURE_${match[1]}`,
|
||||
value: match[2],
|
||||
};
|
||||
results.push(config);
|
||||
});
|
||||
|
||||
return results;
|
||||
|
||||
- name: Reply with confirmation comment
|
||||
uses: actions/github-script@v7
|
||||
if: steps.eval-label.outputs.result == 'up'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const action = '${{ steps.eval-label.outputs.result }}';
|
||||
const user = context.actor;
|
||||
const runId = context.runId;
|
||||
const workflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
|
||||
|
||||
const issueNumber = context.payload.pull_request
|
||||
? context.payload.pull_request.number
|
||||
: context.payload.inputs.issue_number;
|
||||
|
||||
if (!issueNumber) {
|
||||
throw new Error("Issue number is not available.");
|
||||
}
|
||||
|
||||
const body = `⚠️ **DEPRECATED WORKFLOW** ⚠️\n\n@${user} This workflow is deprecated! Please use the new **Superset Showtime** system instead:\n\n` +
|
||||
`- Replace "testenv-up" label with "🎪 trigger-start"\n` +
|
||||
`- Better reliability and easier management\n` +
|
||||
`- See https://github.com/mistercrunch/superset-showtime for details\n\n` +
|
||||
`Processing your ephemeral environment request [here](${workflowUrl}). Action: **${action}**.` +
|
||||
` More information on [how to use or configure ephemeral environments]` +
|
||||
`(https://superset.apache.org/docs/contributing/howtos/#github-ephemeral-environments)`;
|
||||
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
body,
|
||||
});
|
||||
|
||||
ephemeral-docker-build:
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}-build
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-build
|
||||
cancel-in-progress: true
|
||||
needs: ephemeral-env-comment
|
||||
needs: ephemeral-env-label
|
||||
if: needs.ephemeral-env-label.outputs.slash-command == 'up'
|
||||
name: ephemeral-docker-build
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Get Info from comment
|
||||
uses: actions/github-script@v7
|
||||
id: get-pr-info
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ needs.ephemeral-env-label.outputs.sha }} : ${{steps.get-sha.outputs.sha}} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
script: |
|
||||
const request = {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: ${{ github.event.issue.number }},
|
||||
}
|
||||
core.info(`Getting PR #${request.pull_number} from ${request.owner}/${request.repo}`)
|
||||
const pr = await github.rest.pulls.get(request);
|
||||
return pr.data;
|
||||
|
||||
- name: Debug
|
||||
id: get-sha
|
||||
run: |
|
||||
echo "sha=${{ fromJSON(steps.get-pr-info.outputs.result).head.sha }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} : ${{steps.get-sha.outputs.sha}} )"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ steps.get-sha.outputs.sha }}
|
||||
ref: ${{ needs.ephemeral-env-label.outputs.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Setup Docker Environment
|
||||
uses: ./.github/actions/setup-docker
|
||||
with:
|
||||
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
|
||||
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
build: "true"
|
||||
install-docker-compose: "false"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Setup supersetbot
|
||||
uses: ./.github/actions/setup-supersetbot/
|
||||
|
||||
- name: Build ephemeral env image
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
./scripts/build_docker.py \
|
||||
"ci" \
|
||||
"pull_request" \
|
||||
--build_context_ref ${{ github.event.issue.number }}
|
||||
supersetbot docker \
|
||||
--push \
|
||||
--load \
|
||||
--preset ci \
|
||||
--platform linux/amd64 \
|
||||
--context-ref "$RELEASE" \
|
||||
--extra-flags "--build-arg INCLUDE_CHROMIUM=false"
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
@@ -144,140 +204,141 @@ jobs:
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: superset-ci
|
||||
IMAGE_TAG: apache/superset:${{ steps.get-sha.outputs.sha }}-ci
|
||||
IMAGE_TAG: apache/superset:${{ needs.ephemeral-env-label.outputs.sha }}-ci
|
||||
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
|
||||
run: |
|
||||
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-${{ github.event.issue.number }}-ci
|
||||
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-$PR_NUMBER-ci
|
||||
docker push -a $ECR_REGISTRY/$ECR_REPOSITORY
|
||||
|
||||
ephemeral-env-up:
|
||||
needs: [ephemeral-env-comment, ephemeral-docker-build]
|
||||
if: needs.ephemeral-env-comment.outputs.slash-command == 'up'
|
||||
needs: [ephemeral-env-label, ephemeral-docker-build]
|
||||
if: needs.ephemeral-env-label.outputs.slash-command == 'up'
|
||||
name: Spin up an ephemeral environment
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v2
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v2
|
||||
|
||||
- name: Check target image exists in ECR
|
||||
id: check-image
|
||||
continue-on-error: true
|
||||
run: |
|
||||
aws ecr describe-images \
|
||||
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
|
||||
--repository-name superset-ci \
|
||||
--image-ids imageTag=pr-${{ github.event.issue.number }}-ci
|
||||
- name: Check target image exists in ECR
|
||||
id: check-image
|
||||
continue-on-error: true
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
|
||||
run: |
|
||||
aws ecr describe-images \
|
||||
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
|
||||
--repository-name superset-ci \
|
||||
--image-ids imageTag=pr-$PR_NUMBER-ci
|
||||
|
||||
- name: Fail on missing container image
|
||||
if: steps.check-image.outcome == 'failure'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
const errMsg = '@${{ github.event.comment.user.login }} Container image not yet published for this PR. Please try again when build is complete.'
|
||||
github.rest.issues.createComment({
|
||||
issue_number: ${{ github.event.issue.number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: errMsg
|
||||
})
|
||||
core.setFailed(errMsg)
|
||||
- name: Fail on missing container image
|
||||
if: steps.check-image.outcome == 'failure'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
script: |
|
||||
const errMsg = '@${{ github.event.comment.user.login }} Container image not yet published for this PR. Please try again when build is complete.';
|
||||
github.rest.issues.createComment({
|
||||
issue_number: ${{ github.event.inputs.issue_number || github.event.pull_request.number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: errMsg
|
||||
});
|
||||
core.setFailed(errMsg);
|
||||
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: .github/workflows/ecs-task-definition.json
|
||||
container-name: superset-ci
|
||||
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.issue.number }}-ci
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: .github/workflows/ecs-task-definition.json
|
||||
container-name: superset-ci
|
||||
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-ci
|
||||
|
||||
- name: Update env vars in the Amazon ECS task definition
|
||||
run: |
|
||||
cat <<< "$(jq '.containerDefinitions[0].environment += ${{ needs.ephemeral-env-comment.outputs.feature-flags }}' < ${{ steps.task-def.outputs.task-definition }})" > ${{ steps.task-def.outputs.task-definition }}
|
||||
- name: Update env vars in the Amazon ECS task definition
|
||||
run: |
|
||||
cat <<< "$(jq '.containerDefinitions[0].environment += ${{ needs.ephemeral-env-label.outputs.feature-flags }}' < ${{ steps.task-def.outputs.task-definition }})" > ${{ steps.task-def.outputs.task-definition }}
|
||||
|
||||
- name: Describe ECS service
|
||||
id: describe-services
|
||||
run: |
|
||||
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.issue.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
|
||||
- name: Create ECS service
|
||||
if: steps.describe-services.outputs.active != 'true'
|
||||
id: create-service
|
||||
env:
|
||||
ECR_SUBNETS: subnet-0e15a5034b4121710,subnet-0e8efef4a72224974
|
||||
ECR_SECURITY_GROUP: sg-092ff3a6ae0574d91
|
||||
run: |
|
||||
aws ecs create-service \
|
||||
--cluster superset-ci \
|
||||
--service-name pr-${{ github.event.issue.number }}-service \
|
||||
--task-definition superset-ci \
|
||||
--launch-type FARGATE \
|
||||
--desired-count 1 \
|
||||
--platform-version LATEST \
|
||||
--network-configuration "awsvpcConfiguration={subnets=[$ECR_SUBNETS],securityGroups=[$ECR_SECURITY_GROUP],assignPublicIp=ENABLED}" \
|
||||
--tags key=pr,value=${{ github.event.issue.number }} key=github_user,value=${{ github.actor }}
|
||||
- name: Describe ECS service
|
||||
id: describe-services
|
||||
run: |
|
||||
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
|
||||
- name: Create ECS service
|
||||
id: create-service
|
||||
if: steps.describe-services.outputs.active != 'true'
|
||||
env:
|
||||
ECR_SUBNETS: subnet-0e15a5034b4121710,subnet-0e8efef4a72224974
|
||||
ECR_SECURITY_GROUP: sg-092ff3a6ae0574d91
|
||||
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
|
||||
run: |
|
||||
aws ecs create-service \
|
||||
--cluster superset-ci \
|
||||
--service-name pr-$PR_NUMBER-service \
|
||||
--task-definition superset-ci \
|
||||
--launch-type FARGATE \
|
||||
--desired-count 1 \
|
||||
--platform-version LATEST \
|
||||
--network-configuration "awsvpcConfiguration={subnets=[$ECR_SUBNETS],securityGroups=[$ECR_SECURITY_GROUP],assignPublicIp=ENABLED}" \
|
||||
--tags key=pr,value=$PR_NUMBER key=github_user,value=${{ github.actor }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
id: deploy-task
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
|
||||
with:
|
||||
task-definition: ${{ steps.task-def.outputs.task-definition }}
|
||||
service: pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service
|
||||
cluster: superset-ci
|
||||
wait-for-service-stability: true
|
||||
wait-for-minutes: 10
|
||||
|
||||
- name: Deploy Amazon ECS task definition
|
||||
id: deploy-task
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def.outputs.task-definition }}
|
||||
service: pr-${{ github.event.issue.number }}-service
|
||||
cluster: superset-ci
|
||||
wait-for-service-stability: true
|
||||
wait-for-minutes: 10
|
||||
|
||||
- name: List tasks
|
||||
id: list-tasks
|
||||
run: |
|
||||
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${{ github.event.issue.number }}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get network interface
|
||||
id: get-eni
|
||||
run: |
|
||||
echo "eni=$(aws ecs describe-tasks --cluster superset-ci --tasks ${{ steps.list-tasks.outputs.task }} | jq '.tasks | .[0] | .attachments | .[0] | .details | map(select(.name=="networkInterfaceId")) | .[0] | .value')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get public IP
|
||||
id: get-ip
|
||||
run: |
|
||||
echo "ip=$(aws ec2 describe-network-interfaces --network-interface-ids ${{ steps.get-eni.outputs.eni }} | jq -r '.NetworkInterfaces | first | .Association.PublicIp')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Comment (success)
|
||||
if: ${{ success() }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: ${{ github.event.issue.number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '@${{ github.event.comment.user.login }} Ephemeral environment spinning up at http://${{ steps.get-ip.outputs.ip }}:8080. Credentials are `admin`/`admin`. Please allow several minutes for bootstrapping and startup.'
|
||||
})
|
||||
|
||||
- name: Comment (failure)
|
||||
if: ${{ failure() }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: ${{ github.event.issue.number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '@${{ github.event.comment.user.login }} Ephemeral environment creation failed. Please check the Actions logs for details.'
|
||||
})
|
||||
- name: List tasks
|
||||
id: list-tasks
|
||||
run: |
|
||||
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
|
||||
- name: Get network interface
|
||||
id: get-eni
|
||||
run: |
|
||||
echo "eni=$(aws ecs describe-tasks --cluster superset-ci --tasks ${{ steps.list-tasks.outputs.task }} | jq '.tasks[0].attachments[0].details | map(select(.name=="networkInterfaceId"))[0].value')" >> $GITHUB_OUTPUT
|
||||
- name: Get public IP
|
||||
id: get-ip
|
||||
run: |
|
||||
echo "ip=$(aws ec2 describe-network-interfaces --network-interface-ids ${{ steps.get-eni.outputs.eni }} | jq -r '.NetworkInterfaces | first | .Association.PublicIp')" >> $GITHUB_OUTPUT
|
||||
- name: Comment (success)
|
||||
if: ${{ success() }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
|
||||
github.rest.issues.createComment({
|
||||
issue_number: issue_number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: `@${{ github.actor }} Ephemeral environment spinning up at http://${{ steps.get-ip.outputs.ip }}:8080. Credentials are 'admin'/'admin'. Please allow several minutes for bootstrapping and startup.`
|
||||
});
|
||||
- name: Comment (failure)
|
||||
if: ${{ failure() }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
|
||||
github.rest.issues.createComment({
|
||||
issue_number: issue_number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '@${{ github.event.inputs.user_login || github.event.comment.user.login }} Ephemeral environment creation failed. Please check the Actions logs for details.'
|
||||
})
|
||||
|
||||
10
.github/workflows/generate-FOSSA-report.yml
vendored
10
.github/workflows/generate-FOSSA-report.yml
vendored
@@ -4,11 +4,11 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
@@ -24,15 +24,15 @@ jobs:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
name: Generate Report
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "11"
|
||||
|
||||
28
.github/workflows/github-action-validator.sh
vendored
Executable file
28
.github/workflows/github-action-validator.sh
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# Inspired from https://github.com/mpalmer/action-validator?tab=readme-ov-file#pre-commit-hook-example
|
||||
echo "Running pre-commit hook for GitHub Actions: https://github.com/mpalmer/action-validator"
|
||||
for action in $(git ls-files .github/ | grep -E '^\.github/(workflows|actions)/.*\.ya?ml$'); do
|
||||
if action-validator "$action"; then
|
||||
echo "✅ $action"
|
||||
else
|
||||
echo "❌ $action"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
28
.github/workflows/github-action-validator.yml
vendored
Normal file
28
.github/workflows/github-action-validator.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Validate All GitHub Actions
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
|
||||
validate-all-ghas:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install -g @action-validator/core @action-validator/cli --save-dev
|
||||
|
||||
- name: Run Script
|
||||
run: bash .github/workflows/github-action-validator.sh
|
||||
34
.github/workflows/issue_creation.yml
vendored
Normal file
34
.github/workflows/issue_creation.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: supersetbot orglabel based on author
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [created, edited]
|
||||
|
||||
pull_request:
|
||||
types: [created, edited]
|
||||
|
||||
jobs:
|
||||
superbot-orglabel:
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup supersetbot
|
||||
uses: ./.github/actions/setup-supersetbot/
|
||||
|
||||
- name: Execute supersetbot orglabel command
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Label the issue with the appropriate org using supersetbot
|
||||
# - this requires for the author to be publicly associated with their org
|
||||
# - and for the org to be listed in `supersetbot/src/metadata.js`
|
||||
supersetbot orglabel --issue ${{ github.event.number }} --repo ${{ github.repository }} || true
|
||||
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
||||
with:
|
||||
|
||||
4
.github/workflows/latest-release-tag.yml
vendored
4
.github/workflows/latest-release-tag.yml
vendored
@@ -6,13 +6,13 @@ on:
|
||||
jobs:
|
||||
latest-release:
|
||||
name: Add/update tag to new release
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
6
.github/workflows/license-check.yml
vendored
6
.github/workflows/license-check.yml
vendored
@@ -12,15 +12,15 @@ concurrency:
|
||||
jobs:
|
||||
license_check:
|
||||
name: License Check
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
|
||||
2
.github/workflows/no-hold-label.yml
vendored
2
.github/workflows/no-hold-label.yml
vendored
@@ -11,7 +11,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
check-hold-label:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Check for 'hold' label
|
||||
uses: actions/github-script@v7
|
||||
|
||||
54
.github/workflows/no-op.yml
vendored
54
.github/workflows/no-op.yml
vendored
@@ -1,54 +0,0 @@
|
||||
# no-op.yml
|
||||
#
|
||||
# Purpose:
|
||||
# This workflow provides a workaround for the "required status checks" feature in GitHub Actions
|
||||
# when using path-specific conditions in other workflows. Required checks might remain in a "Pending"
|
||||
# state if the conditions are not met, thus blocking pull requests from being merged.
|
||||
# This no-op (no operation) workflow provides dummy success statuses for these required jobs when
|
||||
# the real jobs do not run due to path-specific conditions.
|
||||
#
|
||||
# How it works:
|
||||
# - It defines jobs with the same names as the required jobs in the main workflows.
|
||||
# - These jobs simply execute a command (`exit 0`) to succeed immediately.
|
||||
# - When a pull request is created or updated, both this no-op workflow and the main workflows are triggered.
|
||||
# - If the main workflows' jobs don't run (due to path conditions), these no-op jobs provide successful statuses.
|
||||
# - If the main workflows' jobs do run and fail, their failure statuses take precedence,
|
||||
# ensuring that pull requests are not merged with failing checks.
|
||||
#
|
||||
# Usage:
|
||||
# - Ensure that the job names in this workflow match exactly the names of the corresponding jobs in the main workflows.
|
||||
# - This workflow should be kept as-is, without path-specific conditions.
|
||||
|
||||
name: no-op Checks
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
frontend-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: No-op for frontend-build
|
||||
run: |
|
||||
echo "This is a no-op step for frontend-build to ensure a successful status."
|
||||
exit 0
|
||||
|
||||
pre-commit:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: No-op for pre-commit
|
||||
run: |
|
||||
echo "This is a no-op step for pre-commit to ensure a successful status."
|
||||
exit 0
|
||||
|
||||
python-lint:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: No-op for python-lint
|
||||
run: |
|
||||
echo "This is a no-op step for python-lint to ensure a successful status."
|
||||
exit 0
|
||||
4
.github/workflows/pr-lint.yml
vendored
4
.github/workflows/pr-lint.yml
vendored
@@ -10,13 +10,13 @@ on:
|
||||
|
||||
jobs:
|
||||
lint-check:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
54
.github/workflows/pre-commit.yml
vendored
54
.github/workflows/pre-commit.yml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
@@ -15,18 +15,20 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
python-version: ["current", "previous", "next"]
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Enable brew and helm-docs
|
||||
# Add brew to the path - see https://github.com/actions/runner-images/issues/6283
|
||||
run: |
|
||||
@@ -36,10 +38,48 @@ jobs:
|
||||
echo "HOMEBREW_CELLAR=$HOMEBREW_CELLAR" >>"${GITHUB_ENV}"
|
||||
echo "HOMEBREW_REPOSITORY=$HOMEBREW_REPOSITORY" >>"${GITHUB_ENV}"
|
||||
brew install norwoodj/tap/helm-docs
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install Frontend Dependencies
|
||||
run: |
|
||||
cd superset-frontend
|
||||
npm ci
|
||||
|
||||
- name: Install Docs Dependencies
|
||||
run: |
|
||||
cd docs
|
||||
yarn install --immutable
|
||||
|
||||
- name: Cache pre-commit environments
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit-v2-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
restore-keys: |
|
||||
pre-commit-v2-${{ runner.os }}-py${{ matrix.python-version }}-
|
||||
|
||||
- name: pre-commit
|
||||
run: |
|
||||
if ! pre-commit run --all-files; then
|
||||
git status
|
||||
git diff
|
||||
set +e # Don't exit immediately on failure
|
||||
export SKIP=eslint-frontend,type-checking-frontend
|
||||
pre-commit run --all-files
|
||||
PRE_COMMIT_EXIT_CODE=$?
|
||||
git diff --quiet --exit-code
|
||||
GIT_DIFF_EXIT_CODE=$?
|
||||
if [ "${PRE_COMMIT_EXIT_CODE}" -ne 0 ] || [ "${GIT_DIFF_EXIT_CODE}" -ne 0 ]; then
|
||||
if [ "${PRE_COMMIT_EXIT_CODE}" -ne 0 ]; then
|
||||
echo "❌ Pre-commit check failed (exit code: ${EXIT_CODE})."
|
||||
else
|
||||
echo "❌ Git working directory is dirty."
|
||||
echo "📌 This likely means that pre-commit made changes that were not committed."
|
||||
echo "🔍 Modified files:"
|
||||
git diff --name-only
|
||||
fi
|
||||
|
||||
echo "🚒 To prevent/address this CI issue, please install/use pre-commit locally."
|
||||
echo "📖 More details here: https://superset.apache.org/docs/contributing/development#git-hooks"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
6
.github/workflows/prefer-typescript.yml
vendored
6
.github/workflows/prefer-typescript.yml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
paths:
|
||||
- "superset-frontend/src/**"
|
||||
pull_request:
|
||||
@@ -21,13 +21,13 @@ jobs:
|
||||
prefer_typescript:
|
||||
if: github.ref == 'ref/heads/master' && github.event_name == 'pull_request'
|
||||
name: Prefer TypeScript
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
18
.github/workflows/release.yml
vendored
18
.github/workflows/release.yml
vendored
@@ -4,11 +4,11 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
@@ -24,15 +24,9 @@ jobs:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
name: Bump version and publish package(s)
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16]
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
# pulls all commits (needed for lerna / semantic release to correctly version)
|
||||
fetch-depth: 0
|
||||
@@ -46,11 +40,11 @@ jobs:
|
||||
git fetch --prune --unshallow
|
||||
git tag -d `git tag | grep -E '^trigger-'`
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
- name: Install Node.js
|
||||
if: env.HAS_TAGS
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
|
||||
- name: Cache npm
|
||||
if: env.HAS_TAGS
|
||||
|
||||
50
.github/workflows/showtime-cleanup.yml
vendored
Normal file
50
.github/workflows/showtime-cleanup.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: 🎪 Showtime Cleanup
|
||||
|
||||
# Scheduled cleanup of expired environments
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 */6 * * *' # Every 6 hours
|
||||
|
||||
# Manual trigger for testing
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
max_age_hours:
|
||||
description: 'Maximum age in hours before cleanup'
|
||||
required: false
|
||||
default: '48'
|
||||
type: string
|
||||
|
||||
# Common environment variables
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_REGION: ${{ vars.AWS_REGION || 'us-west-2' }}
|
||||
GITHUB_ORG: ${{ github.repository_owner }}
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
|
||||
jobs:
|
||||
cleanup-expired:
|
||||
name: Clean up expired showtime environments
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Install Superset Showtime
|
||||
run: pip install superset-showtime
|
||||
|
||||
- name: Cleanup expired environments
|
||||
run: |
|
||||
MAX_AGE="${{ github.event.inputs.max_age_hours || '48' }}"
|
||||
|
||||
# Validate max_age is numeric
|
||||
if [[ ! "$MAX_AGE" =~ ^[0-9]+$ ]]; then
|
||||
echo "❌ Invalid max_age_hours format: $MAX_AGE (must be numeric)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Cleaning up environments older than ${MAX_AGE}h"
|
||||
python -m showtime cleanup --older-than "${MAX_AGE}h"
|
||||
179
.github/workflows/showtime-trigger.yml
vendored
Normal file
179
.github/workflows/showtime-trigger.yml
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
name: 🎪 Superset Showtime
|
||||
|
||||
# Ultra-simple: just sync on any PR state change
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled, unlabeled, synchronize, closed]
|
||||
|
||||
# Manual testing
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: 'PR number to sync'
|
||||
required: true
|
||||
type: number
|
||||
sha:
|
||||
description: 'Specific SHA to deploy (optional, defaults to latest)'
|
||||
required: false
|
||||
type: string
|
||||
|
||||
# Common environment variables for all jobs (non-sensitive only)
|
||||
env:
|
||||
AWS_REGION: us-west-2
|
||||
GITHUB_ORG: ${{ github.repository_owner }}
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
GITHUB_ACTOR: ${{ github.actor }}
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: 🎪 Sync PR to desired state
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 90
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Security Check - Authorize Maintainers Only
|
||||
id: auth
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
script: |
|
||||
const actor = context.actor;
|
||||
console.log(`🔍 Checking authorization for ${actor}`);
|
||||
|
||||
// Early exit for workflow_dispatch - assume authorized since it's manually triggered
|
||||
if (context.eventName === 'workflow_dispatch') {
|
||||
console.log(`✅ Workflow dispatch event - assuming authorized for ${actor}`);
|
||||
core.setOutput('authorized', 'true');
|
||||
return;
|
||||
}
|
||||
|
||||
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
username: actor
|
||||
});
|
||||
|
||||
console.log(`📊 Permission level for ${actor}: ${permission.permission}`);
|
||||
const authorized = ['write', 'admin'].includes(permission.permission);
|
||||
|
||||
// If this is a synchronize event from unauthorized user, check if Showtime is active and set blocked label
|
||||
if (!authorized && context.eventName === 'pull_request_target' && context.payload.action === 'synchronize') {
|
||||
console.log(`🔒 Synchronize event detected - checking if Showtime is active`);
|
||||
|
||||
// Check if PR has any circus tent labels (Showtime is in use)
|
||||
const { data: issue } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number
|
||||
});
|
||||
|
||||
const hasCircusLabels = issue.labels.some(label => label.name.startsWith('🎪 '));
|
||||
|
||||
if (hasCircusLabels) {
|
||||
console.log(`🎪 Circus labels found - setting blocked label to prevent auto-deployment`);
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
labels: ['🎪 🔒 showtime-blocked']
|
||||
});
|
||||
|
||||
console.log(`✅ Blocked label set - Showtime will detect and skip operations`);
|
||||
} else {
|
||||
console.log(`ℹ️ No circus labels found - Showtime not in use, skipping block`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!authorized) {
|
||||
console.log(`🚨 Unauthorized user ${actor} - skipping all operations`);
|
||||
core.setOutput('authorized', 'false');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`✅ Authorized maintainer: ${actor}`);
|
||||
core.setOutput('authorized', 'true');
|
||||
|
||||
- name: Install Superset Showtime
|
||||
if: steps.auth.outputs.authorized == 'true'
|
||||
run: |
|
||||
echo "::notice::Maintainer ${{ github.actor }} triggered deploy for PR ${{ github.event.pull_request.number || github.event.inputs.pr_number }}"
|
||||
pip install --upgrade superset-showtime
|
||||
showtime version
|
||||
|
||||
- name: Check what actions are needed
|
||||
if: steps.auth.outputs.authorized == 'true'
|
||||
id: check
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Bulletproof PR number extraction
|
||||
if [[ -n "${{ github.event.pull_request.number }}" ]]; then
|
||||
PR_NUM="${{ github.event.pull_request.number }}"
|
||||
elif [[ -n "${{ github.event.inputs.pr_number }}" ]]; then
|
||||
PR_NUM="${{ github.event.inputs.pr_number }}"
|
||||
else
|
||||
echo "❌ No PR number found in event or inputs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Using PR number: $PR_NUM"
|
||||
|
||||
# Run sync check-only with optional SHA override
|
||||
if [[ -n "${{ github.event.inputs.sha }}" ]]; then
|
||||
OUTPUT=$(python -m showtime sync $PR_NUM --check-only --sha "${{ github.event.inputs.sha }}")
|
||||
else
|
||||
OUTPUT=$(python -m showtime sync $PR_NUM --check-only)
|
||||
fi
|
||||
echo "$OUTPUT"
|
||||
|
||||
# Extract the outputs we need for conditional steps
|
||||
BUILD=$(echo "$OUTPUT" | grep "build_needed=" | cut -d'=' -f2)
|
||||
SYNC=$(echo "$OUTPUT" | grep "sync_needed=" | cut -d'=' -f2)
|
||||
PR_NUM_OUT=$(echo "$OUTPUT" | grep "pr_number=" | cut -d'=' -f2)
|
||||
TARGET_SHA=$(echo "$OUTPUT" | grep "target_sha=" | cut -d'=' -f2)
|
||||
|
||||
echo "build_needed=$BUILD" >> $GITHUB_OUTPUT
|
||||
echo "sync_needed=$SYNC" >> $GITHUB_OUTPUT
|
||||
echo "pr_number=$PR_NUM_OUT" >> $GITHUB_OUTPUT
|
||||
echo "target_sha=$TARGET_SHA" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout PR code (only if build needed)
|
||||
if: steps.auth.outputs.authorized == 'true' && steps.check.outputs.build_needed == 'true'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ steps.check.outputs.target_sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Docker Environment (only if build needed)
|
||||
if: steps.auth.outputs.authorized == 'true' && steps.check.outputs.build_needed == 'true'
|
||||
uses: ./.github/actions/setup-docker
|
||||
with:
|
||||
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
|
||||
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
build: "true"
|
||||
install-docker-compose: "false"
|
||||
|
||||
- name: Execute sync (handles everything)
|
||||
if: steps.auth.outputs.authorized == 'true' && steps.check.outputs.sync_needed == 'true'
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
run: |
|
||||
PR_NUM="${{ steps.check.outputs.pr_number }}"
|
||||
TARGET_SHA="${{ steps.check.outputs.target_sha }}"
|
||||
if [[ -n "$TARGET_SHA" ]]; then
|
||||
python -m showtime sync $PR_NUM --sha "$TARGET_SHA"
|
||||
else
|
||||
python -m showtime sync $PR_NUM
|
||||
fi
|
||||
67
.github/workflows/superset-app-cli.yml
vendored
Normal file
67
.github/workflows/superset-app-cli.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
name: Superset App CLI tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test-load-examples:
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
REDIS_PORT: 16379
|
||||
SUPERSET__SQLALCHEMY_DATABASE_URI: postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
ports:
|
||||
# Use custom ports for services to avoid accidentally connecting to
|
||||
# GitHub action runner's default installations
|
||||
- 15432:5432
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
- name: Setup Postgres
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: setup-postgres
|
||||
- name: superset init
|
||||
if: steps.check.outputs.python
|
||||
run: |
|
||||
pip install -e .
|
||||
superset db upgrade
|
||||
superset load_test_users
|
||||
- name: superset load_examples
|
||||
if: steps.check.outputs.python
|
||||
run: |
|
||||
# load examples without test data
|
||||
superset load_examples --load-big-data
|
||||
11
.github/workflows/superset-applitool-cypress.yml
vendored
11
.github/workflows/superset-applitool-cypress.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
@@ -21,12 +21,11 @@ jobs:
|
||||
cypress-applitools:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
browser: ["chrome"]
|
||||
node: [16]
|
||||
env:
|
||||
SUPERSET_ENV: development
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
@@ -40,7 +39,7 @@ jobs:
|
||||
APPLITOOLS_BATCH_NAME: Superset Cypress
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
@@ -52,7 +51,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -66,7 +65,7 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install npm dependencies
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
|
||||
@@ -12,7 +12,7 @@ env:
|
||||
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
@@ -27,13 +27,10 @@ jobs:
|
||||
cron:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
node: [16]
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -41,7 +38,7 @@ jobs:
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install eyes-storybook dependencies
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
|
||||
72
.github/workflows/superset-cli.yml
vendored
72
.github/workflows/superset-cli.yml
vendored
@@ -1,72 +0,0 @@
|
||||
name: Superset CLI tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test-load-examples:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
REDIS_PORT: 16379
|
||||
SUPERSET__SQLALCHEMY_DATABASE_URI: postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
ports:
|
||||
# Use custom ports for services to avoid accidentally connecting to
|
||||
# GitHub action runner's default installations
|
||||
- 15432:5432
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check if python changes are present
|
||||
id: check
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outcome == 'failure'
|
||||
- name: Setup Postgres
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: setup-postgres
|
||||
- name: superset init
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
pip install -e .
|
||||
superset db upgrade
|
||||
superset load_test_users
|
||||
- name: superset load_examples
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
# load examples without test data
|
||||
superset load_examples --load-big-data
|
||||
35
.github/workflows/superset-docs-deploy.yml
vendored
35
.github/workflows/superset-docs-deploy.yml
vendored
@@ -4,13 +4,15 @@ on:
|
||||
push:
|
||||
paths:
|
||||
- "docs/**"
|
||||
- "README.md"
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
@@ -26,28 +28,41 @@ jobs:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
name: Build & Deploy
|
||||
runs-on: "ubuntu-latest"
|
||||
defaults:
|
||||
run:
|
||||
working-directory: docs
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Set up Node.js 16
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version-file: './docs/.nvmrc'
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: '21'
|
||||
- name: Install Graphviz
|
||||
run: sudo apt-get install -y graphviz
|
||||
- name: Compute Entity Relationship diagram (ERD)
|
||||
env:
|
||||
SUPERSET_SECRET_KEY: not-a-secret
|
||||
run: |
|
||||
python scripts/erd/erd.py
|
||||
curl -L http://sourceforge.net/projects/plantuml/files/1.2023.7/plantuml.1.2023.7.jar/download > ~/plantuml.jar
|
||||
java -jar ~/plantuml.jar -v -tsvg -r -o "${{ github.workspace }}/docs/static/img/" "${{ github.workspace }}/scripts/erd/erd.puml"
|
||||
- name: yarn install
|
||||
working-directory: docs
|
||||
run: |
|
||||
yarn install --check-cache
|
||||
- name: yarn build
|
||||
working-directory: docs
|
||||
run: |
|
||||
yarn build
|
||||
- name: deploy docs
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: ./.github/actions/github-action-push-to-another-repository
|
||||
env:
|
||||
API_TOKEN_GITHUB: ${{ secrets.SUPERSET_SITE_BUILD }}
|
||||
|
||||
44
.github/workflows/superset-docs-verify.yml
vendored
44
.github/workflows/superset-docs-verify.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "docs/**"
|
||||
- ".github/workflows/superset-docs-verify.yml"
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
@@ -12,22 +13,57 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
linkinator:
|
||||
# See docs here: https://github.com/marketplace/actions/linkinator
|
||||
name: Link Checking
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
# Do not bump this linkinator-action version without opening
|
||||
# an ASF Infra ticket to allow the new version first!
|
||||
- uses: JustinBeckwith/linkinator-action@v1.11.0
|
||||
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
|
||||
with:
|
||||
paths: "**/*.md, **/*.mdx, !superset-frontend/CHANGELOG.md"
|
||||
linksToSkip: >-
|
||||
^https://github.com/apache/(superset|incubator-superset)/(pull|issue)/\d+,
|
||||
http://localhost:8088/,
|
||||
http://127.0.0.1:3000/,
|
||||
http://localhost:9001/,
|
||||
https://charts.bitnami.com/bitnami,
|
||||
https://www.li.me/,
|
||||
https://www.fanatics.com/,
|
||||
https://tails.com/gb/,
|
||||
https://www.techaudit.info/,
|
||||
https://avetilearning.com/,
|
||||
https://www.udemy.com/,
|
||||
https://trustmedis.com/,
|
||||
http://theiconic.com.au/,
|
||||
https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html,
|
||||
^https://img\.shields\.io/.*,
|
||||
https://vkusvill.ru/
|
||||
https://www.linkedin.com/in/mark-thomas-b16751158/
|
||||
https://theiconic.com.au/
|
||||
https://wattbewerb.de/
|
||||
https://timbr.ai/
|
||||
https://opensource.org/license/apache-2-0
|
||||
https://www.plaidcloud.com/
|
||||
build-deploy:
|
||||
name: Build & Deploy
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: docs
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Set up Node.js 16
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
node-version-file: './docs/.nvmrc'
|
||||
- name: yarn install
|
||||
run: |
|
||||
yarn install --check-cache
|
||||
|
||||
102
.github/workflows/superset-e2e.yml
vendored
102
.github/workflows/superset-e2e.yml
vendored
@@ -4,9 +4,23 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
use_dashboard:
|
||||
description: 'Use Cypress Dashboard (true/false) [paid service - trigger manually when needed]. You MUST provide a branch and/or PR number below for this to work.'
|
||||
required: false
|
||||
default: 'false'
|
||||
ref:
|
||||
description: 'The branch or tag to checkout'
|
||||
required: false
|
||||
default: ''
|
||||
pr_id:
|
||||
description: 'The pull request ID to checkout'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
@@ -14,19 +28,21 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
cypress-matrix:
|
||||
runs-on: ubuntu-20.04
|
||||
# Somehow one test flakes on 24.04 for unknown reasons, this is the only GHA left on 22.04
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
strategy:
|
||||
# when one test fails, DO NOT cancel the other
|
||||
# containers, because this will kill Cypress processes
|
||||
# parallel_id, because this will kill Cypress processes
|
||||
# leaving the Dashboard hanging ...
|
||||
# https://github.com/cypress-io/github-action/issues/48
|
||||
fail-fast: false
|
||||
matrix:
|
||||
containers: [1, 2, 3]
|
||||
parallel_id: [0, 1, 2, 3, 4, 5]
|
||||
browser: ["chrome"]
|
||||
app_root: ["", "/app/prefix"]
|
||||
env:
|
||||
SUPERSET_ENV: development
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
@@ -34,9 +50,11 @@ jobs:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
REDIS_PORT: 16379
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
# Only use dashboard when explicitly requested via workflow_dispatch
|
||||
USE_DASHBOARD: ${{ github.event.inputs.use_dashboard == 'true' || 'false' }}
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
@@ -47,77 +65,89 @@ jobs:
|
||||
ports:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout (pull) ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
if: github.event_name == 'push'
|
||||
# -------------------------------------------------------
|
||||
# Conditional checkout based on context
|
||||
- name: Checkout for push or pull_request event
|
||||
if: github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: "Checkout (pull_request) ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target'
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Checkout using ref (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.ref != ''
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: "refs/pull/${{ github.event.number }}/merge"
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
submodules: recursive
|
||||
- name: Check if python or frontend changes are present
|
||||
- name: Checkout using PR ID (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_id != ''
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
|
||||
submodules: recursive
|
||||
# -------------------------------------------------------
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python frontend
|
||||
- name: Setup Python
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/setup-backend/
|
||||
- name: OS dependencies
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
run: apt-get-install
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
- name: Setup postgres
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: setup-postgres
|
||||
- name: Import test data
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: testdata
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install npm dependencies
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: npm-install
|
||||
- name: Build javascript packages
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: build-instrumented-assets
|
||||
- name: Install cypress
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: cypress-install
|
||||
- name: Run Cypress
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
env:
|
||||
CYPRESS_BROWSER: ${{ matrix.browser }}
|
||||
CYPRESS_KEY: YjljODE2MzAtODcwOC00NTA3LWE4NmMtMTU3YmFmMjIzOTRhCg==
|
||||
PARALLEL_ID: ${{ matrix.parallel_id }}
|
||||
PARALLELISM: 6
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
NODE_OPTIONS: "--max-old-space-size=4096"
|
||||
with:
|
||||
run: cypress-run-all
|
||||
run: cypress-run-all ${{ env.USE_DASHBOARD }} ${{ matrix.app_root }}
|
||||
- name: Set safe app root
|
||||
if: failure()
|
||||
id: set-safe-app-root
|
||||
run: |
|
||||
APP_ROOT="${{ matrix.app_root }}"
|
||||
SAFE_APP_ROOT=${APP_ROOT//\//_}
|
||||
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: screenshots
|
||||
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
|
||||
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}-${{ matrix.parallel_id }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
|
||||
|
||||
64
.github/workflows/superset-extensions-cli.yml
vendored
Normal file
64
.github/workflows/superset-extensions-cli.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: Superset Extensions CLI Package Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test-superset-extensions-cli-package:
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["previous", "current", "next"]
|
||||
defaults:
|
||||
run:
|
||||
working-directory: superset-extensions-cli
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Python
|
||||
if: steps.check.outputs.superset-extensions-cli
|
||||
uses: ./.github/actions/setup-backend/
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
requirements-type: dev
|
||||
|
||||
- name: Run pytest with coverage
|
||||
if: steps.check.outputs.superset-extensions-cli
|
||||
run: |
|
||||
pytest --cov=superset_extensions_cli --cov-report=xml --cov-report=term-missing --cov-report=html -v --tb=short
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
if: steps.check.outputs.superset-extensions-cli
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: superset-extensions-cli
|
||||
name: superset-extensions-cli-coverage
|
||||
fail_ci_if_error: false
|
||||
|
||||
- name: Upload HTML coverage report
|
||||
if: steps.check.outputs.superset-extensions-cli
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: superset-extensions-cli-coverage-html
|
||||
path: htmlcov/
|
||||
202
.github/workflows/superset-frontend.yml
vendored
202
.github/workflows/superset-frontend.yml
vendored
@@ -1,89 +1,169 @@
|
||||
name: Frontend
|
||||
name: "Frontend Build CI (unit tests, linting & sanity checks)"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
paths:
|
||||
- "superset-frontend/**"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
paths:
|
||||
- "superset-frontend/**"
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
TAG: apache/superset:GHA-${{ github.run_id }}
|
||||
|
||||
jobs:
|
||||
frontend-build:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
should-run: ${{ steps.check.outputs.frontend }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check npm lock file version
|
||||
run: ./scripts/ci_check_npm_lock_version.sh ./superset-frontend/package-lock.json
|
||||
- name: Check if frontend changes are present
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Check for File Changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Docker Image
|
||||
if: steps.check.outputs.frontend
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh frontend
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: actions/setup-node@v4
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
echo "git rev-parse --short HEAD"
|
||||
git rev-parse --short HEAD
|
||||
echo "git show -s --format=raw HEAD"
|
||||
git show -s --format=raw HEAD
|
||||
docker buildx build \
|
||||
-t $TAG \
|
||||
--cache-from=type=registry,ref=apache/superset-cache:3.10-slim-trixie \
|
||||
--target superset-node-ci \
|
||||
.
|
||||
|
||||
- name: Save Docker Image as Artifact
|
||||
if: steps.check.outputs.frontend
|
||||
run: |
|
||||
docker save $TAG | gzip > docker-image.tar.gz
|
||||
|
||||
- name: Upload Docker Image Artifact
|
||||
if: steps.check.outputs.frontend
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
node-version: "16"
|
||||
- name: Install dependencies
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
name: docker-image
|
||||
path: docker-image.tar.gz
|
||||
|
||||
sharded-jest-tests:
|
||||
needs: frontend-build
|
||||
if: needs.frontend-build.outputs.should-run == 'true'
|
||||
strategy:
|
||||
matrix:
|
||||
shard: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Docker Image Artifact
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
run: npm-install
|
||||
name: docker-image
|
||||
|
||||
- name: Load Docker Image
|
||||
run: docker load < docker-image.tar.gz
|
||||
|
||||
- name: npm run test with coverage
|
||||
run: |
|
||||
mkdir -p ${{ github.workspace }}/superset-frontend/coverage
|
||||
docker run \
|
||||
-v ${{ github.workspace }}/superset-frontend/coverage:/app/superset-frontend/coverage \
|
||||
--rm $TAG \
|
||||
bash -c \
|
||||
"npm run test -- --coverage --shard=${{ matrix.shard }}/8 --coverageReporters=json-summary"
|
||||
|
||||
- name: Upload Coverage Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-artifacts-${{ matrix.shard }}
|
||||
path: superset-frontend/coverage
|
||||
|
||||
report-coverage:
|
||||
needs: [sharded-jest-tests]
|
||||
if: needs.frontend-build.outputs.should-run == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Coverage Artifacts
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: coverage-artifacts-*
|
||||
path: coverage/
|
||||
|
||||
- name: Show Files
|
||||
run: find coverage/
|
||||
|
||||
- name: Merge Code Coverage
|
||||
run: npx nyc merge coverage/ merged-output/coverage-summary.json
|
||||
|
||||
- name: Upload Code Coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
flags: javascript
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
files: merged-output/coverage-summary.json
|
||||
slug: apache/superset
|
||||
|
||||
lint-frontend:
|
||||
needs: frontend-build
|
||||
if: needs.frontend-build.outputs.should-run == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Docker Image Artifact
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: docker-image
|
||||
|
||||
- name: Load Docker Image
|
||||
run: |
|
||||
docker load < docker-image.tar.gz
|
||||
|
||||
- name: eslint
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend
|
||||
run: |
|
||||
npm run eslint -- . --quiet
|
||||
docker run --rm $TAG bash -c \
|
||||
"npm i && npm run eslint -- . --quiet"
|
||||
|
||||
- name: tsc
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend
|
||||
run: |
|
||||
npm run type
|
||||
- name: prettier
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend
|
||||
docker run --rm $TAG bash -c \
|
||||
"npm run plugins:build && npm run type"
|
||||
|
||||
validate-frontend:
|
||||
needs: frontend-build
|
||||
if: needs.frontend-build.outputs.should-run == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Docker Image Artifact
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: docker-image
|
||||
|
||||
- name: Load Docker Image
|
||||
run: docker load < docker-image.tar.gz
|
||||
|
||||
- name: Build Plugins Packages
|
||||
run: |
|
||||
npm run prettier-check
|
||||
- name: Build plugins packages
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend
|
||||
run: npm run plugins:build
|
||||
- name: Build plugins Storybook
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend
|
||||
run: npm run plugins:build-storybook
|
||||
- name: superset-ui/core coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend
|
||||
docker run --rm $TAG bash -c \
|
||||
"npm run plugins:build"
|
||||
|
||||
- name: Build Plugins Storybook
|
||||
run: |
|
||||
npm run core:cover
|
||||
- name: unit tests
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend
|
||||
run: |
|
||||
npm run test -- --coverage --silent
|
||||
# todo: remove this step when fix generator as a project in root jest.config.js
|
||||
- name: generator-superset unit tests
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend/packages/generator-superset
|
||||
run: npx jest
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend
|
||||
run: ../.github/workflows/codecov.sh -c -F javascript
|
||||
docker run --rm $TAG bash -c \
|
||||
"npm run plugins:build-storybook"
|
||||
|
||||
15
.github/workflows/superset-helm-lint.yml
vendored
15
.github/workflows/superset-helm-lint.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Lint and Test Charts
|
||||
name: "Helm: lint and test charts"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -13,23 +13,24 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
lint-test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v3
|
||||
uses: azure/setup-helm@v4
|
||||
with:
|
||||
version: v3.5.4
|
||||
version: v3.16.4
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
with:
|
||||
python-version: "3.9"
|
||||
install-superset: 'false'
|
||||
|
||||
- name: Set up chart-testing
|
||||
uses: ./.github/actions/chart-testing-action
|
||||
|
||||
94
.github/workflows/superset-helm-release.yml
vendored
94
.github/workflows/superset-helm-release.yml
vendored
@@ -1,24 +1,38 @@
|
||||
name: Release Charts
|
||||
# This workflow automates the release process for Helm charts.
|
||||
# The workflow creates a new branch for the release and opens a pull request against the 'gh-pages' branch,
|
||||
# allowing the changes to be reviewed and merged manually.
|
||||
|
||||
name: "Helm: release charts"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
paths:
|
||||
- "helm/**"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: "The branch, tag, or commit SHA to check out"
|
||||
required: false
|
||||
default: "master"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ inputs.ref || github.ref_name }}
|
||||
persist-credentials: true
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -28,18 +42,84 @@ jobs:
|
||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
|
||||
- name: Install Helm
|
||||
uses: azure/setup-helm@v3
|
||||
uses: azure/setup-helm@v4
|
||||
with:
|
||||
version: v3.5.4
|
||||
|
||||
- name: Add bitnami repo dependency
|
||||
run: helm repo add bitnami https://charts.bitnami.com/bitnami
|
||||
|
||||
- name: Fetch/list all tags
|
||||
run: |
|
||||
# Debugging tags
|
||||
git fetch --tags --force
|
||||
git tag -d superset-helm-chart-0.13.4 || true
|
||||
echo "DEBUG TAGS"
|
||||
git show-ref --tags
|
||||
|
||||
- name: Create unique pages branch name
|
||||
id: vars
|
||||
run: echo "branch_name=helm-publish-${GITHUB_SHA:0:7}" >> $GITHUB_ENV
|
||||
|
||||
- name: Force recreate branch from gh-pages
|
||||
run: |
|
||||
# Ensure a clean working directory
|
||||
git reset --hard
|
||||
git clean -fdx
|
||||
git checkout -b local_gha_temp
|
||||
git submodule update
|
||||
|
||||
# Fetch the latest gh-pages branch
|
||||
git fetch origin gh-pages
|
||||
|
||||
# Check out and reset the target branch based on gh-pages
|
||||
git checkout -B ${{ env.branch_name }} origin/gh-pages
|
||||
|
||||
# Remove submodules from the branch
|
||||
git submodule deinit -f --all
|
||||
|
||||
# Force push to the remote branch
|
||||
git push origin ${{ env.branch_name }} --force
|
||||
|
||||
# Return to the original branch
|
||||
git checkout local_gha_temp
|
||||
|
||||
- name: Fetch/list all tags
|
||||
run: |
|
||||
git submodule update
|
||||
cat .github/actions/chart-releaser-action/action.yml
|
||||
|
||||
- name: Run chart-releaser
|
||||
uses: ./.github/actions/chart-releaser-action
|
||||
with:
|
||||
version: v1.6.0
|
||||
charts_dir: helm
|
||||
mark_as_latest: false
|
||||
pages_branch: ${{ env.branch_name }}
|
||||
env:
|
||||
CR_TOKEN: "${{ github.token }}"
|
||||
CR_RELEASE_NAME_TEMPLATE: "superset-helm-chart-{{ .Version }}"
|
||||
|
||||
- name: Open Pull Request
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const branchName = '${{ env.branch_name }}';
|
||||
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
|
||||
|
||||
if (!branchName) {
|
||||
throw new Error("Branch name is not defined.");
|
||||
}
|
||||
|
||||
const pr = await github.rest.pulls.create({
|
||||
owner,
|
||||
repo,
|
||||
title: `Helm chart release for ${branchName}`,
|
||||
head: branchName,
|
||||
base: "gh-pages", // Adjust if the target branch is different
|
||||
body: `This PR releases Helm charts to the gh-pages branch.`,
|
||||
});
|
||||
|
||||
core.info(`Pull request created: ${pr.data.html_url}`);
|
||||
env:
|
||||
BRANCH_NAME: ${{ env.branch_name }}
|
||||
|
||||
141
.github/workflows/superset-playwright.yml
vendored
Normal file
141
.github/workflows/superset-playwright.yml
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
name: Playwright E2E Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: 'The branch or tag to checkout'
|
||||
required: false
|
||||
default: ''
|
||||
pr_id:
|
||||
description: 'The pull request ID to checkout'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
playwright-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
# Allow workflow to succeed even if tests fail during shadow mode
|
||||
continue-on-error: true
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
browser: ["chromium"]
|
||||
app_root: ["", "/app/prefix"]
|
||||
env:
|
||||
SUPERSET_ENV: development
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
SUPERSET__SQLALCHEMY_DATABASE_URI: postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
REDIS_PORT: 16379
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
ports:
|
||||
- 15432:5432
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- 16379:6379
|
||||
steps:
|
||||
# -------------------------------------------------------
|
||||
# Conditional checkout based on context (same as Cypress workflow)
|
||||
- name: Checkout for push or pull_request event
|
||||
if: github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Checkout using ref (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.ref != ''
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
submodules: recursive
|
||||
- name: Checkout using PR ID (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_id != ''
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
|
||||
submodules: recursive
|
||||
# -------------------------------------------------------
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
- name: Setup postgres
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: setup-postgres
|
||||
- name: Import test data
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: testdata
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install npm dependencies
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: npm-install
|
||||
- name: Build javascript packages
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: build-instrumented-assets
|
||||
- name: Install Playwright
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: playwright-install
|
||||
- name: Run Playwright
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=4096"
|
||||
with:
|
||||
run: playwright-run ${{ matrix.app_root }}
|
||||
- name: Set safe app root
|
||||
if: failure()
|
||||
id: set-safe-app-root
|
||||
run: |
|
||||
APP_ROOT="${{ matrix.app_root }}"
|
||||
SAFE_APP_ROOT=${APP_ROOT//\//_}
|
||||
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
|
||||
- name: Upload Playwright Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/superset-frontend/playwright-results/
|
||||
${{ github.workspace }}/superset-frontend/test-results/
|
||||
name: playwright-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
@@ -15,10 +15,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
test-mysql:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
@@ -27,11 +24,16 @@ jobs:
|
||||
mysql+mysqldb://superset:superset@127.0.0.1:13306/superset?charset=utf8mb4&binary_prefix=true
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
image: mysql:8.0
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
ports:
|
||||
- 13306:3306
|
||||
options: >-
|
||||
--health-cmd="mysqladmin ping --silent"
|
||||
--health-interval=10s
|
||||
--health-timeout=5s
|
||||
--health-retries=5
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
options: --entrypoint redis-server
|
||||
@@ -39,44 +41,43 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check if python changes are present
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outcome == 'failure'
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
if: steps.check.outputs.python
|
||||
- name: Setup MySQL
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
setup-mysql
|
||||
- name: Run celery
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: celery --app=superset.tasks.celery_app:app worker -Ofair -c 2 &
|
||||
run: setup-mysql
|
||||
- name: Start Celery worker
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: celery-worker
|
||||
- name: Python integration tests (MySQL)
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
run: |
|
||||
./scripts/python_tests.sh
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash .github/workflows/codecov.sh -c -F python -F mysql
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
flags: python,mysql
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
test-postgres:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9", "3.10"]
|
||||
python-version: ["current", "previous", "next"]
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
@@ -84,7 +85,7 @@ jobs:
|
||||
SUPERSET__SQLALCHEMY_DATABASE_URI: postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
@@ -98,45 +99,44 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check if python changes are present
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Setup Postgres
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
setup-postgres
|
||||
- name: Run celery
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: celery --app=superset.tasks.celery_app:app worker -Ofair -c 2 &
|
||||
- name: Start Celery worker
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: celery-worker
|
||||
- name: Python integration tests (PostgreSQL)
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
run: |
|
||||
./scripts/python_tests.sh
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash .github/workflows/codecov.sh -c -F python -F postgres
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
flags: python,postgres
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
|
||||
test-sqlite:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
@@ -152,37 +152,37 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check if python changes are present
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outcome == 'failure'
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
if: steps.check.outputs.python
|
||||
- name: Install dependencies
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
# sqlite needs this working directory
|
||||
mkdir ${{ github.workspace }}/.temp
|
||||
- name: Run celery
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: celery --app=superset.tasks.celery_app:app worker -Ofair -c 2 &
|
||||
- name: Start Celery worker
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: celery-worker
|
||||
- name: Python integration tests (SQLite)
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
run: |
|
||||
./scripts/python_tests.sh
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash .github/workflows/codecov.sh -c -F python -F sqlite
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
flags: python,sqlite
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
|
||||
66
.github/workflows/superset-python-misc.yml
vendored
66
.github/workflows/superset-python-misc.yml
vendored
@@ -1,66 +0,0 @@
|
||||
# Python Misc unit tests
|
||||
name: Python Misc
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
paths:
|
||||
- "superset/**"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
paths:
|
||||
- "superset/**"
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
python-lint:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check if python changes are present
|
||||
id: check
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outcome == 'failure'
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: pylint
|
||||
if: steps.check.outcome == 'failure'
|
||||
# `-j 0` run Pylint in parallel
|
||||
run: pylint -j 0 superset
|
||||
|
||||
babel-extract:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Test babel extraction
|
||||
run: flask fab babel-extract --target superset/translations --output superset/translations/messages.pot --config superset/translations/babel.cfg -k _,__,t,tn,tct
|
||||
@@ -5,13 +5,9 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
paths:
|
||||
- "superset/**"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
paths:
|
||||
- "superset/**"
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
@@ -20,10 +16,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
test-postgres-presto:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
@@ -32,7 +25,7 @@ jobs:
|
||||
SUPERSET__SQLALCHEMY_EXAMPLES_URI: presto://localhost:15433/memory/default
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
@@ -55,42 +48,43 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check if python changes are present
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python == 'true'
|
||||
- name: Setup Postgres
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: setup-postgres
|
||||
- name: Run celery
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: celery --app=superset.tasks.celery_app:app worker -Ofair -c 2 &
|
||||
run: |
|
||||
echo "${{ steps.check.outputs.python }}"
|
||||
setup-postgres
|
||||
- name: Start Celery worker
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: celery-worker
|
||||
- name: Python unit tests (PostgreSQL)
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
run: |
|
||||
./scripts/python_tests.sh -m 'chart_data_flow or sql_json_flow'
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash .github/workflows/codecov.sh -c -F python -F presto
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
flags: python,presto
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
|
||||
test-postgres-hive:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
@@ -100,7 +94,7 @@ jobs:
|
||||
UPLOAD_FOLDER: /tmp/.superset/uploads/
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
@@ -114,42 +108,45 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check if python changes are present
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create csv upload directory
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
run: sudo mkdir -p /tmp/.superset/uploads
|
||||
- name: Give write access to the csv upload directory
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
run: sudo chown -R $USER:$USER /tmp/.superset
|
||||
- name: Start hadoop and hive
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
run: docker compose -f scripts/databases/hive/docker-compose.yml up -d
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
- name: Setup Postgres
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: setup-postgres
|
||||
- name: Run celery
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: celery --app=superset.tasks.celery_app:app worker -Ofair -c 2 &
|
||||
- name: Start Celery worker
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: celery-worker
|
||||
- name: Python unit tests (PostgreSQL)
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
run: |
|
||||
pip install -e .[hive]
|
||||
./scripts/python_tests.sh -m 'chart_data_flow or sql_json_flow'
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash .github/workflows/codecov.sh -c -F python -F hive
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
flags: python,hive
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
|
||||
49
.github/workflows/superset-python-unittest.yml
vendored
49
.github/workflows/superset-python-unittest.yml
vendored
@@ -5,19 +5,9 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
paths:
|
||||
- "superset/**"
|
||||
- "requirements/**"
|
||||
- "tests/unit_tests/**"
|
||||
- "scripts/**"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
paths:
|
||||
- "superset/**"
|
||||
- "requirements/**"
|
||||
- "tests/unit_tests/**"
|
||||
- "scripts/**"
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
@@ -26,38 +16,45 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9", "3.10"]
|
||||
python-version: ["previous", "current", "next"]
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check if python changes are present
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
env:
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Python unit tests
|
||||
if: steps.check.outcome == 'failure'
|
||||
if: steps.check.outputs.python
|
||||
env:
|
||||
SUPERSET_TESTENV: true
|
||||
SUPERSET_SECRET_KEY: not-a-secret
|
||||
run: |
|
||||
pytest --durations-min=0.5 --cov-report= --cov=superset ./tests/common ./tests/unit_tests --cache-clear
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
pytest --durations-min=0.5 --cov-report= --cov=superset ./tests/common ./tests/unit_tests --cache-clear --maxfail=50
|
||||
- name: Python 100% coverage unit tests
|
||||
if: steps.check.outputs.python
|
||||
env:
|
||||
SUPERSET_TESTENV: true
|
||||
SUPERSET_SECRET_KEY: not-a-secret
|
||||
run: |
|
||||
bash .github/workflows/codecov.sh -c -F python -F unit
|
||||
pytest --durations-min=0.5 --cov=superset/sql/ ./tests/unit_tests/sql/ --cache-clear --cov-fail-under=100
|
||||
- name: Upload code coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
flags: python,unit
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
|
||||
48
.github/workflows/superset-translations.yml
vendored
48
.github/workflows/superset-translations.yml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
@@ -14,48 +14,54 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
frontend-check:
|
||||
runs-on: ubuntu-20.04
|
||||
frontend-check-translations:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outputs.frontend
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install dependencies
|
||||
if: steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: npm-install
|
||||
- name: lint
|
||||
if: steps.check.outputs.frontend
|
||||
working-directory: ./superset-frontend
|
||||
run: |
|
||||
npm run check-translation
|
||||
npm run build-translation
|
||||
|
||||
babel-extract:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Python
|
||||
if: steps.check.outputs.python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
apt-get-install
|
||||
pip-upgrade
|
||||
pip install -r requirements/base.txt
|
||||
- name: Test babel extraction
|
||||
run: ./scripts/babel_update.sh
|
||||
if: steps.check.outputs.python
|
||||
run: ./scripts/translations/babel_update.sh
|
||||
|
||||
6
.github/workflows/superset-websocket.yml
vendored
6
.github/workflows/superset-websocket.yml
vendored
@@ -3,7 +3,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
paths:
|
||||
- "superset-websocket/**"
|
||||
pull_request:
|
||||
@@ -18,10 +18,10 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
app-checks:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install dependencies
|
||||
|
||||
37
.github/workflows/supersetbot.yml
vendored
37
.github/workflows/supersetbot.yml
vendored
@@ -15,43 +15,42 @@ on:
|
||||
|
||||
jobs:
|
||||
supersetbot:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
if: >
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@supersetbot'))
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
steps:
|
||||
- name: Quickly add thumbs up!
|
||||
uses: actions/github-script@v5
|
||||
if: github.event_name == 'issue_comment' && contains(github.event.comment.body, '@supersetbot')
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
|
||||
await github.rest.reactions.createForIssueComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: ${{ github.event.comment.id }},
|
||||
comment_id: context.payload.comment.id,
|
||||
content: '+1'
|
||||
});
|
||||
- name: Execute SupersetBot Command
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
- name: "Checkout ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
node-version: '20'
|
||||
- run: npm install supersetbot
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup supersetbot
|
||||
uses: ./.github/actions/setup-supersetbot/
|
||||
|
||||
- name: Execute custom Node.js script
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_ACTOR: ${{ github.actor }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
GITHUB_ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
COMMENT_BODY: ${{ github.event.comment.body }}
|
||||
INPUT_COMMENT_BODY: ${{ github.event.inputs.comment_body }}
|
||||
COMMENT_BODY: ${{ github.event.comment.body }}${{ github.event.inputs.comment_body }}
|
||||
run: |
|
||||
cat <<EOF > script.js
|
||||
const run = async () => {
|
||||
const { runCommandFromGithubAction } = await import('supersetbot');
|
||||
const cmd = process.env.COMMENT_BODY || process.env.INPUT_COMMENT_BODY;
|
||||
console.log("Executing: ", cmd);
|
||||
await runCommandFromGithubAction(cmd);
|
||||
};
|
||||
run().catch(console.error);
|
||||
EOF
|
||||
node script.js
|
||||
supersetbot run "$COMMENT_BODY"
|
||||
|
||||
134
.github/workflows/tag-release.yml
vendored
Normal file
134
.github/workflows/tag-release.yml
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
name: Publish a Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published, edited]
|
||||
|
||||
# Can be triggered manually
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release:
|
||||
required: true
|
||||
description: The version to generate
|
||||
git-ref:
|
||||
required: true
|
||||
description: The git reference to checkout prior to running the docker build
|
||||
force-latest:
|
||||
required: true
|
||||
type: choice
|
||||
default: 'false'
|
||||
description: Whether to force a latest tag on the release
|
||||
options:
|
||||
- 'true'
|
||||
- 'false'
|
||||
jobs:
|
||||
config:
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
- name: "Check for secrets"
|
||||
id: check
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -n "${{ (secrets.DOCKERHUB_USER != '' && secrets.DOCKERHUB_TOKEN != '') || '' }}" ]; then
|
||||
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
docker-release:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
name: docker-release
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
build_preset: ["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"]
|
||||
fail-fast: false
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Docker Environment
|
||||
uses: ./.github/actions/setup-docker
|
||||
with:
|
||||
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
|
||||
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
install-docker-compose: "false"
|
||||
build: "true"
|
||||
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup supersetbot
|
||||
uses: ./.github/actions/setup-supersetbot/
|
||||
|
||||
- name: Execute custom Node.js script
|
||||
env:
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
RELEASE="${{ github.event.release.tag_name }}"
|
||||
FORCE_LATEST=""
|
||||
EVENT="${{github.event_name}}"
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
# in the case of a manually-triggered run, read release from input
|
||||
RELEASE="${{ github.event.inputs.release }}"
|
||||
if [ "${{ github.event.inputs.force-latest }}" = "true" ]; then
|
||||
FORCE_LATEST="--force-latest"
|
||||
fi
|
||||
git checkout "${{ github.event.inputs.git-ref }}"
|
||||
EVENT="release"
|
||||
fi
|
||||
|
||||
supersetbot docker \
|
||||
--push \
|
||||
--preset ${{ matrix.build_preset }} \
|
||||
--context "$EVENT" \
|
||||
--context-ref "$RELEASE" $FORCE_LATEST \
|
||||
--platform "linux/arm64" \
|
||||
--platform "linux/amd64"
|
||||
|
||||
# Returning to master to support closing setup-supersetbot
|
||||
git checkout master
|
||||
|
||||
update-prs-with-release-info:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup supersetbot
|
||||
uses: ./.github/actions/setup-supersetbot/
|
||||
|
||||
- name: Label the PRs with the right release-related labels
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
export GITHUB_ACTOR=""
|
||||
git fetch --all --tags
|
||||
git checkout master
|
||||
RELEASE="${{ github.event.release.tag_name }}"
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
# in the case of a manually-triggered run, read release from input
|
||||
RELEASE="${{ github.event.inputs.release }}"
|
||||
fi
|
||||
supersetbot release-label $RELEASE
|
||||
12
.github/workflows/tech-debt.yml
vendored
12
.github/workflows/tech-debt.yml
vendored
@@ -4,11 +4,11 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- "[0-9].[0-9]"
|
||||
- "[0-9].[0-9]*"
|
||||
|
||||
jobs:
|
||||
config:
|
||||
runs-on: "ubuntu-latest"
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
has-secrets: ${{ steps.check.outputs.has-secrets }}
|
||||
steps:
|
||||
@@ -23,19 +23,19 @@ jobs:
|
||||
process-and-upload:
|
||||
needs: config
|
||||
if: needs.config.outputs.has-secrets
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
name: Generate Reports
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: npm ci
|
||||
working-directory: ./superset-frontend
|
||||
|
||||
- name: Run Script
|
||||
|
||||
47
.github/workflows/update-monorepo-lockfiles.yml
vendored
47
.github/workflows/update-monorepo-lockfiles.yml
vendored
@@ -1,47 +0,0 @@
|
||||
name: Update Lockfiles for Dependabot Monorepo PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'superset-frontend/packages/**/package.json'
|
||||
- 'superset-frontend/plugins/**/package.json'
|
||||
types: [opened, synchronize, reopened]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.issue.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
update-lock-file:
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
(github.event_name == 'pull_request' && github.event.pull_request.user.login == 'dependabot[bot]') ||
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@supersetbot trigger-dependabot-lockfile') && github.event.issue.pull_request)
|
||||
defaults:
|
||||
run:
|
||||
working-directory: superset-frontend
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref || github.head_ref }} # Checkout the branch that made the PR or the comment's PR branch
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
|
||||
- name: Install Dependencies and Update Lock File
|
||||
run: |
|
||||
npm install
|
||||
|
||||
- name: Commit and Push Changes
|
||||
run: |
|
||||
git config user.name "GitHub-Actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add package-lock.json
|
||||
# Push the changes back to the branch if they exist, and pass if there are no changes
|
||||
git diff --staged --quiet || (git commit -m "Update lock file for Dependabot PR" -a && git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} ${{ github.event.pull_request.head.ref || github.head_ref }})
|
||||
4
.github/workflows/welcome-new-users.yml
vendored
4
.github/workflows/welcome-new-users.yml
vendored
@@ -6,13 +6,13 @@ on:
|
||||
|
||||
jobs:
|
||||
welcome:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Welcome Message
|
||||
uses: actions/first-interaction@v1
|
||||
uses: actions/first-interaction@v3
|
||||
continue-on-error: true
|
||||
with:
|
||||
repo-token: ${{ github.token }}
|
||||
|
||||
32
.gitignore
vendored
32
.gitignore
vendored
@@ -21,6 +21,7 @@
|
||||
*.swp
|
||||
__pycache__
|
||||
|
||||
.aider*
|
||||
.local
|
||||
.cache
|
||||
.bento*
|
||||
@@ -42,7 +43,7 @@ _modules
|
||||
_static
|
||||
build
|
||||
app.db
|
||||
apache_superset.egg-info/
|
||||
*.egg-info/
|
||||
changelog.sh
|
||||
dist
|
||||
dump.rdb
|
||||
@@ -50,7 +51,6 @@ env
|
||||
venv*
|
||||
env_py3
|
||||
envpy3
|
||||
env36
|
||||
local_config.py
|
||||
/superset_config.py
|
||||
/superset_text.yml
|
||||
@@ -66,7 +66,10 @@ superset-websocket/config.json
|
||||
*.js.map
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
superset/static/assets
|
||||
superset/static/assets/*
|
||||
!superset/static/assets/.gitkeep
|
||||
superset/static/uploads/*
|
||||
!superset/static/uploads/.gitkeep
|
||||
superset/static/version_info.json
|
||||
superset-frontend/**/esm/*
|
||||
superset-frontend/**/lib/*
|
||||
@@ -89,6 +92,7 @@ scripts/*.zip
|
||||
# IntelliJ
|
||||
*.iml
|
||||
venv
|
||||
.venv
|
||||
@eaDir/
|
||||
|
||||
# PyCharm
|
||||
@@ -104,11 +108,29 @@ ghostdriver.log
|
||||
testCSV.csv
|
||||
.terser-plugin-cache/
|
||||
apache-superset-*.tar.gz*
|
||||
apache_superset-*.tar.gz*
|
||||
release.json
|
||||
|
||||
# Translation binaries
|
||||
messages.mo
|
||||
# Translation-related files
|
||||
# these json files are generated by ./scripts/po2json.sh
|
||||
superset/translations/**/messages.json
|
||||
# these mo binary files are generated by `pybabel compile`
|
||||
superset/translations/**/messages.mo
|
||||
|
||||
docker/requirements-local.txt
|
||||
|
||||
cache/
|
||||
docker/*local*
|
||||
|
||||
.temp_cache
|
||||
|
||||
# Jest test report
|
||||
test-report.html
|
||||
superset/static/stats/statistics.html
|
||||
|
||||
# LLM-related
|
||||
CLAUDE.local.md
|
||||
PROJECT.md
|
||||
.aider*
|
||||
.claude_rc*
|
||||
.env.local
|
||||
|
||||
@@ -16,32 +16,16 @@
|
||||
#
|
||||
repos:
|
||||
- repo: https://github.com/MarcoGorelli/auto-walrus
|
||||
rev: v0.2.2
|
||||
rev: 0.3.4
|
||||
hooks:
|
||||
- id: auto-walrus
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.4.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args:
|
||||
- --py39-plus
|
||||
- repo: https://github.com/hadialqattan/pycln
|
||||
rev: v2.1.2
|
||||
hooks:
|
||||
- id: pycln
|
||||
args:
|
||||
- --disable-all-dunder-policy
|
||||
- --exclude=superset/config.py
|
||||
- --extend-exclude=tests/integration_tests/superset_test_config.*.py
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
- id: isort
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.3.0
|
||||
rev: v1.15.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
name: mypy (main)
|
||||
args: [--check-untyped-defs]
|
||||
exclude: ^superset-extensions-cli/
|
||||
additional_dependencies: [
|
||||
types-simplejson,
|
||||
types-python-dateutil,
|
||||
@@ -56,33 +40,45 @@ repos:
|
||||
types-paramiko,
|
||||
types-Markdown,
|
||||
]
|
||||
- repo: https://github.com/peterdemin/pip-compile-multi
|
||||
rev: v2.6.2
|
||||
hooks:
|
||||
- id: pip-compile-multi-verify
|
||||
- id: mypy
|
||||
name: mypy (superset-extensions-cli)
|
||||
args: [--check-untyped-defs]
|
||||
files: ^superset-extensions-cli/
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: check-docstring-first
|
||||
- id: check-added-large-files
|
||||
exclude: \.(geojson)$
|
||||
exclude: ^.*\.(geojson)$|^docs/static/img/screenshots/.*|^superset-frontend/CHANGELOG\.md$
|
||||
- id: check-yaml
|
||||
exclude: ^helm/superset/templates/
|
||||
- id: debug-statements
|
||||
- id: end-of-file-fixer
|
||||
exclude: .*/lerna\.json$
|
||||
- id: trailing-whitespace
|
||||
exclude: ^.*\.(snap)
|
||||
args: ["--markdown-linebreak-ext=md"]
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.1.0
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: black
|
||||
language_version: python3
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v3.1.0 # Use the sha or tag you want to point at
|
||||
hooks:
|
||||
- id: prettier
|
||||
args: ["--ignore-path=./superset-frontend/.prettierignore"]
|
||||
files: "superset-frontend"
|
||||
- id: eslint-frontend
|
||||
name: eslint (frontend)
|
||||
entry: ./scripts/eslint.sh
|
||||
language: system
|
||||
pass_filenames: true
|
||||
files: ^superset-frontend/.*\.(js|jsx|ts|tsx)$
|
||||
- id: eslint-docs
|
||||
name: eslint (docs)
|
||||
entry: bash -c 'cd docs && FILES=$(echo "$@" | sed "s|docs/||g") && yarn eslint --fix --ext .js,.jsx,.ts,.tsx --quiet $FILES'
|
||||
language: system
|
||||
pass_filenames: true
|
||||
files: ^docs/.*\.(js|jsx|ts|tsx)$
|
||||
- id: type-checking-frontend
|
||||
name: Type-Checking (Frontend)
|
||||
entry: ./scripts/check-type.js package=superset-frontend excludeDeclarationDir=cypress-base
|
||||
language: system
|
||||
files: ^superset-frontend\/.*\.(js|jsx|ts|tsx)$
|
||||
exclude: ^superset-frontend/cypress-base\/
|
||||
require_serial: true
|
||||
# blacklist unsafe functions like make_url (see #19526)
|
||||
- repo: https://github.com/skorokithakis/blacklist-pre-commit-hook
|
||||
rev: e2f070289d8eddcaec0b580d3bde29437e7c8221
|
||||
@@ -90,7 +86,35 @@ repos:
|
||||
- id: blacklist
|
||||
args: ["--blacklisted-names=make_url", "--ignore=tests/"]
|
||||
- repo: https://github.com/norwoodj/helm-docs
|
||||
rev: v1.11.0
|
||||
rev: v1.14.2
|
||||
hooks:
|
||||
- id: helm-docs
|
||||
files: helm
|
||||
verbose: false
|
||||
args: ["--log-level", "error"]
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.9.7
|
||||
hooks:
|
||||
- id: ruff-format
|
||||
- id: ruff
|
||||
args: [--fix]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: pylint
|
||||
name: pylint with custom Superset plugins
|
||||
entry: bash
|
||||
language: system
|
||||
types: [python]
|
||||
exclude: ^(tests/|superset/migrations/|scripts/|RELEASING/|docker/)
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
TARGET_BRANCH=${GITHUB_BASE_REF:-master}
|
||||
git fetch origin "$TARGET_BRANCH"
|
||||
BASE=$(git merge-base origin/"$TARGET_BRANCH" HEAD)
|
||||
files=$(git diff --name-only --diff-filter=ACM "$BASE"..HEAD | grep '^superset/.*\.py$' || true)
|
||||
if [ -n "$files" ]; then
|
||||
pylint --rcfile=.pylintrc --load-plugins=superset.extensions.pylint --reports=no $files
|
||||
else
|
||||
echo "No Python files to lint."
|
||||
fi
|
||||
|
||||
32
.pylintrc
32
.pylintrc
@@ -36,7 +36,7 @@ persistent=yes
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
load-plugins=superset.extensions.pylint
|
||||
|
||||
# Use multiple processes to speed up Pylint.
|
||||
jobs=2
|
||||
@@ -52,33 +52,9 @@ extension-pkg-whitelist=pyarrow
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
disable=all
|
||||
enable=disallowed-json-import,disallowed-sql-import,consider-using-transaction
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
|
||||
confidence=
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
enable=
|
||||
useless-suppression,
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once).You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
disable=
|
||||
cyclic-import, # re-enable once this no longer raises false positives
|
||||
missing-docstring,
|
||||
duplicate-code,
|
||||
unspecified-encoding,
|
||||
too-many-instance-attributes # re-enable once this no longer raises false positives
|
||||
|
||||
[REPORTS]
|
||||
|
||||
@@ -171,7 +147,7 @@ max-nested-blocks=5
|
||||
[FORMAT]
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=90
|
||||
max-line-length=100
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
@@ -32,6 +32,8 @@ apache_superset.egg-info
|
||||
# json and csv in general cannot have comments
|
||||
.*json
|
||||
.*csv
|
||||
# jinja templates often need to be as-is
|
||||
.*j2
|
||||
# Generated doc files
|
||||
env/*
|
||||
docs/.htaccess*
|
||||
@@ -61,8 +63,27 @@ tsconfig.tsbuildinfo
|
||||
generator-superset/*
|
||||
temporary_superset_ui/*
|
||||
|
||||
# skip license checks for auto-generated test snapshots
|
||||
.*snap
|
||||
|
||||
# docs overrides for third party logos we don't have the rights to
|
||||
google-big-query.svg
|
||||
google-sheets.svg
|
||||
ibm-db2.svg
|
||||
postgresql.svg
|
||||
snowflake.svg
|
||||
ydb.svg
|
||||
loading.svg
|
||||
|
||||
# docs-related
|
||||
erd.puml
|
||||
erd.svg
|
||||
intro_header.txt
|
||||
|
||||
# for LLMs
|
||||
llm-context.md
|
||||
LLMS.md
|
||||
CLAUDE.md
|
||||
CURSOR.md
|
||||
GEMINI.md
|
||||
GPT.md
|
||||
|
||||
63
ASF/doap_Superset.rdf
Normal file
63
ASF/doap_Superset.rdf
Normal file
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/xsl"?>
|
||||
<rdf:RDF xml:lang="en"
|
||||
xmlns="http://usefulinc.com/ns/doap#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:asfext="http://projects.apache.org/ns/asfext#"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/">
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<Project rdf:about="https://superset.apache.org">
|
||||
<created>2024-04-10</created>
|
||||
<license rdf:resource="https://spdx.org/licenses/Apache-2.0" />
|
||||
<name>Apache Superset</name>
|
||||
<homepage rdf:resource="https://superset.apache.org" />
|
||||
<asfext:pmc rdf:resource="https://superset.apache.org" />
|
||||
<shortdesc>Apache Superset™ is an open-source modern data exploration and visualization platform.</shortdesc>
|
||||
<description>Superset is a fast, lightweight, intuitive, business intelligence platform. Loaded with options, Superset makes it easy for users of all skill sets to explore and visualize their data, from simple line charts to highly detailed geospatial charts.
|
||||
|
||||
* Powerful yet easy to use:
|
||||
Superset makes it easy to explore your data, using either our simple no-code viz builder or state-of-the-art SQL IDE.
|
||||
|
||||
* Integrates with modern databases
|
||||
Superset can connect to any SQL-based databases including modern cloud-native databases and engines at petabyte scale.
|
||||
|
||||
* Modern architecture
|
||||
Superset is lightweight and highly scalable, leveraging the power of your existing data infrastructure without requiring yet another ingestion layer.
|
||||
|
||||
* Rich visualizations and dashboards
|
||||
Superset ships with 40+ pre-installed visualization types. Our plug-in architecture makes it easy to build custom visualizations.
|
||||
|
||||
</description>
|
||||
<bug-database rdf:resource="https://github.com/apache/superset/issues" />
|
||||
<mailing-list rdf:resource="https://lists.apache.org/list.html?dev@superset.apache.org" />
|
||||
<download-page rdf:resource="https://dist.apache.org/repos/dist/release/superset/" />
|
||||
<programming-language>JavaScript</programming-language>
|
||||
<programming-language>Python</programming-language>
|
||||
<programming-language>Typescript</programming-language>
|
||||
<category rdf:resource="https://projects.apache.org/category/big-data" />
|
||||
<category rdf:resource="https://projects.apache.org/category/database" />
|
||||
<category rdf:resource="https://projects.apache.org/category/data-engineering" />
|
||||
<category rdf:resource="https://projects.apache.org/category/geospatial" />
|
||||
<repository>
|
||||
<GitRepository>
|
||||
<location rdf:resource="https://github.com/apache/superset.git"/>
|
||||
<browse rdf:resource="https://github.com/apache/superset/"/>
|
||||
</GitRepository>
|
||||
</repository>
|
||||
</Project>
|
||||
</rdf:RDF>
|
||||
11
CHANGELOG.md
11
CHANGELOG.md
@@ -38,3 +38,14 @@ under the License.
|
||||
- [3.0.4](./CHANGELOG/3.0.4.md)
|
||||
- [3.1.0](./CHANGELOG/3.1.0.md)
|
||||
- [3.1.1](./CHANGELOG/3.1.1.md)
|
||||
- [3.1.2](./CHANGELOG/3.1.2.md)
|
||||
- [3.1.3](./CHANGELOG/3.1.3.md)
|
||||
- [4.0.0](./CHANGELOG/4.0.0.md)
|
||||
- [4.0.1](./CHANGELOG/4.0.1.md)
|
||||
- [4.0.2](./CHANGELOG/4.0.2.md)
|
||||
- [4.1.0](./CHANGELOG/4.1.0.md)
|
||||
- [4.1.1](./CHANGELOG/4.1.1.md)
|
||||
- [4.1.2](./CHANGELOG/4.1.2.md)
|
||||
- [4.1.3](./CHANGELOG/4.1.3.md)
|
||||
- [4.1.4](./CHANGELOG/4.1.4.md)
|
||||
- [5.0.0](./CHANGELOG/5.0.0.md)
|
||||
|
||||
93
CHANGELOG/3.1.2.md
Normal file
93
CHANGELOG/3.1.2.md
Normal file
@@ -0,0 +1,93 @@
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
## Change Log
|
||||
|
||||
### 3.1.2 (Thu Mar 28 11:32:00 2024 -0300)
|
||||
|
||||
**Fixes**
|
||||
|
||||
- [#27706](https://github.com/apache/superset/pull/27706) fix: Select onChange is fired when the same item is selected in single mode (@michael-s-molina)
|
||||
- [#27744](https://github.com/apache/superset/pull/27744) fix: reduce alert error to warning (@eschutho)
|
||||
- [#27644](https://github.com/apache/superset/pull/27644) fix: Provide more inclusive error handling for saved queries (@john-bodley)
|
||||
- [#27646](https://github.com/apache/superset/pull/27646) fix: Leverage actual database for rendering Jinjarized SQL (@john-bodley)
|
||||
- [#27636](https://github.com/apache/superset/pull/27636) fix(sqllab): unable to remove table (@justinpark)
|
||||
- [#27022](https://github.com/apache/superset/pull/27022) fix(Chart Annotation modal): Table and Superset annotation options will paginate, exceeding previous max limit 100 (@rtexelm)
|
||||
- [#27552](https://github.com/apache/superset/pull/27552) fix(AlertReports): defaulting grace period to undefined (@fisjac)
|
||||
- [#27551](https://github.com/apache/superset/pull/27551) fix(AlertReports): clearing custom_width when disabled (@fisjac)
|
||||
- [#27601](https://github.com/apache/superset/pull/27601) fix: Persist query params appended to permalink (@kgabryje)
|
||||
- [#27470](https://github.com/apache/superset/pull/27470) fix(sql_parse): Ensure table extraction handles Jinja templating (@john-bodley)
|
||||
- [#19595](https://github.com/apache/superset/pull/19595) fix: Volatile datasource ordering in dashboard export (@pnadolny13)
|
||||
- [#27613](https://github.com/apache/superset/pull/27613) fix(Dashboard): Add editMode conditional for translate3d fix on charts to allow intended Fullscreen (@rtexelm)
|
||||
- [#27388](https://github.com/apache/superset/pull/27388) fix(utils): fix off-by-one error in how rolling window's min_periods truncates dataframe (@sfirke)
|
||||
- [#27577](https://github.com/apache/superset/pull/27577) fix: sqlglot SQL Server (@betodealmeida)
|
||||
- [#27576](https://github.com/apache/superset/pull/27576) fix: bump sqlglot to support materialized CTEs (@betodealmeida)
|
||||
- [#27567](https://github.com/apache/superset/pull/27567) fix(db_engine_specs): Update convert_dttm to work correctly with CrateDB (@hlcianfagna)
|
||||
- [#27605](https://github.com/apache/superset/pull/27605) fix: Skips Hive tests that are blocking PRs (@michael-s-molina)
|
||||
- [#27566](https://github.com/apache/superset/pull/27566) fix: guest queries (@betodealmeida)
|
||||
- [#27464](https://github.com/apache/superset/pull/27464) fix: pass valid SQL to SM (@betodealmeida)
|
||||
- [#26748](https://github.com/apache/superset/pull/26748) fix: `improve _extract_tables_from_sql` (@betodealmeida)
|
||||
- [#27260](https://github.com/apache/superset/pull/27260) fix(alerts/reports): implementing custom_width as an Antd number input (@fisjac)
|
||||
- [#27487](https://github.com/apache/superset/pull/27487) fix(postprocessing): resample with holes (@villebro)
|
||||
- [#27484](https://github.com/apache/superset/pull/27484) fix: check if guest user modified query (@betodealmeida)
|
||||
- [#27471](https://github.com/apache/superset/pull/27471) fix(webpack): remove double-dotted file extensions in webpack config (@rusackas)
|
||||
- [#27411](https://github.com/apache/superset/pull/27411) fix(dashboard): Only fetch CSS templates for dashboard header menu when in edit mode (@mskelton)
|
||||
- [#27262](https://github.com/apache/superset/pull/27262) fix(Alerts & Reports): Fixing bug that resets cron value to default when empty (@fisjac)
|
||||
- [#27315](https://github.com/apache/superset/pull/27315) fix(deps): resolving canvg and html2canvas module not found (@fisjac)
|
||||
- [#27403](https://github.com/apache/superset/pull/27403) fix: missing shared color in mixed timeseries (@justinpark)
|
||||
- [#27391](https://github.com/apache/superset/pull/27391) fix(sqllab): Close already removed tab (@justinpark)
|
||||
- [#27364](https://github.com/apache/superset/pull/27364) fix(API): Updating assets via the API should preserve ownership configuration (@Vitor-Avila)
|
||||
- [#27395](https://github.com/apache/superset/pull/27395) fix: improve explore REST api validations (@dpgaspar)
|
||||
- [#26205](https://github.com/apache/superset/pull/26205) fix(docker): Remove race condition when building image (@alekseyolg)
|
||||
- [#27366](https://github.com/apache/superset/pull/27366) fix: Results section in Explore shows an infinite spinner (@michael-s-molina)
|
||||
- [#27187](https://github.com/apache/superset/pull/27187) fix: numexpr to fix CVE-2023-39631 (2.8.4 => 2.9.0) (@nigzak)
|
||||
- [#27360](https://github.com/apache/superset/pull/27360) fix: Heatmap numeric sorting (@michael-s-molina)
|
||||
- [#27308](https://github.com/apache/superset/pull/27308) fix(dashboard): table chart drag preview overflowing container (@rtexelm)
|
||||
- [#27295](https://github.com/apache/superset/pull/27295) fix(sqllab): invalid dump sql shown after closing tab (@justinpark)
|
||||
- [#27285](https://github.com/apache/superset/pull/27285) fix(plugin-chart-echarts): calculate Gauge Chart intervals correctly when min value is set (@goto-loop)
|
||||
- [#27307](https://github.com/apache/superset/pull/27307) fix: Incorrect data type on import page (@michael-s-molina)
|
||||
- [#27291](https://github.com/apache/superset/pull/27291) fix: Data zoom with horizontal orientation (@michael-s-molina)
|
||||
- [#27273](https://github.com/apache/superset/pull/27273) fix: Navigating to an invalid page index in lists (@michael-s-molina)
|
||||
- [#27271](https://github.com/apache/superset/pull/27271) fix: Inoperable dashboard filter slider when range is <= 1 (@michael-s-molina)
|
||||
- [#27154](https://github.com/apache/superset/pull/27154) fix(import-datasources): Use "admin" user as default for importing datasources (@ddxv)
|
||||
- [#27258](https://github.com/apache/superset/pull/27258) fix: Sorting charts/dashboards makes the applied filters ineffective (@michael-s-molina)
|
||||
- [#27213](https://github.com/apache/superset/pull/27213) fix(trino): bumping trino to fix hudi schema fetching (@rusackas)
|
||||
- [#27236](https://github.com/apache/superset/pull/27236) fix(reports): fixing unit test (@fisjac)
|
||||
- [#27217](https://github.com/apache/superset/pull/27217) fix(sqlglot): Address regressions introduced in #26476 (@john-bodley)
|
||||
- [#27233](https://github.com/apache/superset/pull/27233) fix: bump FAB to 4.4.1 (perf issue) (@dpgaspar)
|
||||
- [#27167](https://github.com/apache/superset/pull/27167) fix: setting important lower bounds versions on requirements (@dpgaspar)
|
||||
- [#27215](https://github.com/apache/superset/pull/27215) fix: no limit in SELECT \* for TOP dbs (@betodealmeida)
|
||||
- [#27191](https://github.com/apache/superset/pull/27191) fix: Failed to execute importScripts on worker-css (@michael-s-molina)
|
||||
- [#27181](https://github.com/apache/superset/pull/27181) fix(sqllab): typeahead search is broken in db selector (@justinpark)
|
||||
- [#27161](https://github.com/apache/superset/pull/27161) fix(ci): mypy pre-commit issues (@dpgaspar)
|
||||
- [#27135](https://github.com/apache/superset/pull/27135) fix: Duplicated toast messages (@michael-s-molina)
|
||||
- [#27132](https://github.com/apache/superset/pull/27132) fix: Plain error message when visiting a dashboard via permalink without permissions (@michael-s-molina)
|
||||
- [#22840](https://github.com/apache/superset/pull/22840) fix(pivot-table-v2): Added forgotten translation pivot table v2 (@Always-prog)
|
||||
- [#27128](https://github.com/apache/superset/pull/27128) fix: RLS modal overflow (@michael-s-molina)
|
||||
- [#27112](https://github.com/apache/superset/pull/27112) fix: gevent upgrade to 23.9.1 (@dpgaspar)
|
||||
- [#27124](https://github.com/apache/superset/pull/27124) fix: bump grpcio, urllib3 and paramiko (@dpgaspar)
|
||||
- [#27113](https://github.com/apache/superset/pull/27113) fix: upgrade cryptography to major 42 (@dpgaspar)
|
||||
- [#27106](https://github.com/apache/superset/pull/27106) fix: Timeseries Y-axis format with contribution mode (@michael-s-molina)
|
||||
|
||||
**Others**
|
||||
|
||||
- [#27281](https://github.com/apache/superset/pull/27281) chore: bump cryptography minimum to 42.0.4 (@sadpandajoe)
|
||||
- [#27232](https://github.com/apache/superset/pull/27232) chore: Removes Chromatic workflow and dependencies (@michael-s-molina)
|
||||
- [#27159](https://github.com/apache/superset/pull/27159) chore: bump FAB to 4.4.0 (@dpgaspar)
|
||||
- [#27129](https://github.com/apache/superset/pull/27129) chore: lower cryptography min version to 41.0.2 (@sadpandajoe)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user